Mudar String conforme o char array JAVA

Eu tenho uma questão em mãos que deve ser fácil, mas estou parada.
Então eu tenho 2 Strings que são dadas pelo scanner. No exemplo que dou passei o passo a frente e inventei as 2 Strings. A String s é a frase que quero modificar conforme a k.
As letras em s iguais a k são modificadas 2 letra seguinte(A fica C…) e as outras continuam iguais. Mas se fizer 2 for, dá print mais do que uma vez e a modificação também nao esta correta.

 public static void main(String args[]) {

// sao exemplos, porque quero que s e k sejam dados pelo scanner
  String s = "MY DOG IS CALLED BOBBY";
  char[] s1 = s.toCharArray();
  String k = "AB";
  char[] c = {'A','B'}; 
  
  for(char a : s1){
        for(char b : c){
          if(a == b){
              System.out.print(a += 2);
          } else {
              System.out.print(a);
          }
      }
  }
}

}

Não entendi, qual deveria ser o resultado? Você quer trocar todas as letras A e B da string s por duas letras à frente?

E se a letra for “Z”, o resultado de “duas letras à frente” é o que? “B”?

Peço desculpa, não ter explicado muito bem.
Então o alfabeto seria circular, realmente esqueci me dessa situação do Z porque ficaria a letra B.
Então para isso poderia fazer um char array de 26 indices, com as posições 2 a frente.
A frase final ficaria “MY DOG IS CCLLED DODDY” porque só as letras A e B são mudadas

Não precisa de toCharArray (pois este método cria um array à toa), pode percorrer os caracteres com um for simples, usando charAt para pegar cada um deles.

E para o k, eu criei um Set. Talvez seja exagero, mas se as strings forem muito grandes, fazer um for dentro do outro pode acabar ficando mais lento (um Set é mais “otimizado” para buscas, então verificar se o caractere está lá fica mais rápido).

String s = "MY DOG IS CALLED BOBBY";
String k = "AB";

Set<Character> kChars = new HashSet<>();
for (int i = 0; i < k.length(); i++) {
    kChars.add(k.charAt(i));
}

for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
    if (kChars.contains(c)) {
        c = (char) (((c - 63) % 26) + 65);
    }
    System.out.print(c);
}

Repare também no cálculo. Primeiro eu substraio 63 (que seria subtrair 65 para “normalizar”, ou seja, “A” passa a ser zero, “B” vira 1, etc), e depois somo 2 para obter “dois caracteres à frente”, e pego o resto da divisão por 26 para que o “Z” volte para o “A”. Depois somo 65 para voltar a ter código correto (“A” volta a ser 65, “B” será 66, etc).


Se quiser, também pode criar um Map que mapeia cada caractere para a sua substituição. Aí é só verificar se cada caractere de s tem um mapeamento:

String s = "MY DOG IS CALLED BOBBY";
String k = "AB";

Map<Character, Character> kChars = new HashMap<>();
for (int i = 0; i < k.length(); i++) {
    char c = k.charAt(i);
    kChars.put(c, (char) (((c - 63) % 26) + 65));
}

for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
    System.out.print(kChars.getOrDefault(c, c));
}

Claro, também dá pra usar dois loops aninhados. Só que você precisa controlar se o caractere já foi encontrado em k, e neste caso não deve imprimi-lo novamente:

String s = "MY DOG IS CALLED BOBBY";
String k = "AB";
for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
    boolean found = false; // encontrei este caractere em k?
    for (int j = 0; j < k.length(); j++) {
        if (c == k.charAt(j)) {
            System.out.print((char) (((c - 63) % 26) + 65));
            found = true;
            break; // já encontrei, sai do for mais interno
        }
    }
    if (!found) { // se não encontrou o caractere em K, imprime
        System.out.print(c);
    }
}
1 curtida

agradeço muito!!!