Search code examples
javaencryptioncaesar-cipher

Substituting characters with other characters


I want the decipher a certain text. When I encounter a letter in the string, I want to substitute it with the next letter in the alphabet. Then in the next round I want a substitution with the second next letter.

a -> b

k -> l

Then in the second round it should try

a -> c

k -> m

The problem with characters is that it includes all kinds of strange characters, and when you encounter a z and try to substitute it, it gets substituted with a strange symbol.

Anyone who can help me make some sort of circular list from A-Z? In the following snippet I create a list which contains a to z. In the loop a character is picked, it's index is searched and 'adjusted' and the new character should be retreived. But it doesn't work. (one reason the list being not circular)

public static void decipher(){
    String cyphertext = "aVaqrprzoreoeratraWhyvhfraJnygreUbyynaqreqrgjrroebrefinaRqvguZnetbganneNzfgreqnzNaarjvytenntzrrxbzraznnezbrgabtrrarragvwqwrovwbznoyvwiraBznmnyurgzbrvyvwxuroorabzNaarabtrracnnejrxraqnnegrubhqrafpuevwsgRqvguSenaxvarraoevrsnnaTregehqAnhznaauhaiebrtrerohhezrvfwrvaSenaxshegnzZnva";
    char[] plaintext = new char[cyphertext.length()];

    List<Character> a2z = new ArrayList<Character>(26);
    for (char c = 'A'; c <= 'Z'; c++){
        a2z.add(Character.valueOf(c));
    }

    for(int i = 1; i < 26; i++){
        for(int j = 0; j < cyphertext.length(); j++){
            char currentChar = cyphertext.charAt(j);
            int newCharIndex = a2z.indexOf(currentChar)+i;
            plaintext[j] = a2z.get(newCharIndex);
        }
    }
}

Solution

  • You don't need a circular list to handle the edge cases. Further, you should keep in mind that characters A-Z have ascii values between 65-90 and a-z between 97-122. You could create two circular lists, but they're not needed because the edge-cases are easy to handle:

    public static void main(String[] args) {
        String cyphertext = "aVaqrprzoreoeratraWhyvhfraJnygreUbyynaqreqrgjrroebrefinaRqvguZnetbganneNzfgreqnzNaarjvytenntzrrxbzraznnezbrgabtrrarragvwqwrovwbznoyvwiraBznmnyurgzbrvyvwxuroorabzNaarabtrracnnejrxraqnnegrubhqrafpuevwsgRqvguSenaxvarraoevrsnnaTregehqAnhznaauhaiebrtrerohhezrvfwrvaSenaxshegnzZnva";
        char[] plaintext = new char[cyphertext.length()];
    
        // first shift
        shiftLetters(cyphertext, plaintext, 1);
        // update cyphertext with the intermediate result
        cyphertext = new String(plaintext);
        // second shift
        shiftLetters(cyphertext, plaintext, 2);
        // print result
        System.out.println(new String(plaintext));
    
    }
    
    private static void shiftLetters(String cyphertext, char[] plaintext, int shifts) {
        for (int i=0; i<cyphertext.length(); i++){
            int tmp = cyphertext.charAt(i) + shifts;
            tmp = handleEdgeCases(tmp);
            plaintext[i] = (char)(tmp);
        }
    }
    
    // here we handle the "circular" cases
    private static int handleEdgeCases(int tmp) {
        if (tmp > 90 && tmp < 97) {
            tmp = tmp - 90 + 65;
        } else if (tmp > 122) {
            tmp = tmp - 122 + 97;
        }
        return tmp;
    }