[Solved] Java incrementing every character in a string by a large amount?


First I’m going to remove all of the I/O (except for outputting the result), get rid of the decryption piece for brevity, and write encrypt(String) and encrypt(char) as pure functions.

public class EncryptionMain {

    public static void main(String args[]){
        System.out.println(encrypt("Hello"));
    }

    static String encrypt(String plaintext) {
        StringBuilder ciphertext = new StringBuilder(plaintext);
        for (int i = 0; i < ciphertext.length(); i++) {
            ciphertext.setCharAt(i, encrypt(ciphertext.charAt(i)));
        }
        return ciphertext.toString();
    }

    static char encrypt(char c) {
        int switchInc = 1; // 0 = BACK 1 = FORWARD

        for(int e = 0; e < 1000; e++){
            if (c == '!') {
                switchInc = 1;
            } else if (c == '~') {
                switchInc = 0;
            }

            switch (switchInc) {
                case 0: c--; break;
                default: c++; break;
            }
        }
        return c;
    }
}

And, whoops! – just by doing that, I accidentally fixed the bug. Here, I’ll add it back:

public class EncryptionMain {

    public static void main(String args[]){
        System.out.println(encrypt("Hello"));
    }

    static String encrypt(String plaintext) {
        StringBuilder ciphertext = new StringBuilder(plaintext);
        for (int i = 0; i < ciphertext.length(); i++) {
            ciphertext.setCharAt(i, encrypt(ciphertext.charAt(i)));
        }
        return ciphertext.toString();
    }

    static int switchInc = 1; // 0 = BACK 1 = FORWARD

    static char encrypt(char c) {

        for(int e = 0; e < 1000; e++){
            if (c == '!') {
                switchInc = 1;
            } else if (c == '~') {
                switchInc = 0;
            }

            switch (switchInc) {
                case 0: c--; break;
                default: c++; break;
            }
        }
        return c;
    }
}

Edit – Here’s a working Caesar cipher I referred to in the comments below.

main/cipher/Cipher.java

package cipher;

public final class Cipher {

    public Cipher(Range range, int key) {
        this.range = range;
        this.key = key;
    }

    public final Range range;
    public final int key;

    public String encrypt(String plaintext) {
        return cipher(plaintext, key);
    }

    public String decrypt(String ciphertext) {
        return cipher(ciphertext, -key);
    }

    String cipher(String in, int n) {
        StringBuilder out = new StringBuilder(in.length());
        for (int i = 0; i < in.length(); i++) {
            out.append(range.shift(in.charAt(i), n));
        }
        return out.toString();
    }
}

main/cipher/Range.java

package cipher;

public final class Range {

    public final char min;
    public final char max;
    public final int size;

    public static Range inclusive(char min, char max) {
        return new Range(min, max);
    }

    Range(char min, char max) {
        this.min = min;
        this.max = max;
        size = max - min + 1;
    }

    /** Shift c up by i places, wrapping around to the
     * beginning of the range when it reaches the end. */
    public char shift(char c, int i) {
        return (char) (min + mod(c - min + i, size));
    }

    /** x mod a */
    static int mod(int x, int a) {
        return ((x % a) + a) % a;
    }
}

test/cipher/CipherTest.java

package cipher;

import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;

public class CipherTest {

    @Test
    public void testZeroKey() throws Exception {
        Cipher cipher = new Cipher(Range.inclusive('a', 'z'), 0);
        assertEquals(cipher.encrypt("abcxyz"), "abcxyz");
        assertEquals(cipher.decrypt("abcxyz"), "abcxyz");
    }

    @Test
    public void testOneKey() throws Exception {
        Cipher cipher = new Cipher(Range.inclusive('a', 'z'), 1);
        assertEquals(cipher.encrypt("abcxyz"), "bcdyza");
        assertEquals(cipher.decrypt("bcdyza"), "abcxyz");
    }

    @Test
    public void testSizePlusOneKey() throws Exception {
        Cipher cipher = new Cipher(Range.inclusive('a', 'z'), 27);
        assertEquals(cipher.encrypt("abcxyz"), "bcdyza");
        assertEquals(cipher.decrypt("bcdyza"), "abcxyz");
    }
}

test/cipher/RangeTest.java

package cipher;

import org.testng.Assert;
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;
import static cipher.Range.mod;

public class RangeTest {

    @Test
    public void testSize() {
        Assert.assertEquals(Range.inclusive('a', 'c').size, 3);
    }

    @Test
    public void testMod() throws Exception {
        assertEquals(mod(-2, 5), 3);
        assertEquals(mod(-1, 5), 4);
        assertEquals(mod(0, 5), 0);
        assertEquals(mod(1, 5), 1);
        assertEquals(mod(2, 5), 2);
        assertEquals(mod(3, 5), 3);
        assertEquals(mod(4, 5), 4);
        assertEquals(mod(5, 5), 0);
        assertEquals(mod(6, 5), 1);
    }

    @Test
    public void testShift() throws Exception {
        Range r = Range.inclusive('a', 'd');
        Assert.assertEquals(r.shift('a', -2), 'c');
        Assert.assertEquals(r.shift('a', -1), 'd');
        Assert.assertEquals(r.shift('a', 0), 'a');
        Assert.assertEquals(r.shift('a', 1), 'b');
        Assert.assertEquals(r.shift('a', 2), 'c');
        Assert.assertEquals(r.shift('a', 3), 'd');
        Assert.assertEquals(r.shift('a', 4), 'a');
        Assert.assertEquals(r.shift('a', 5), 'b');
    }
}

17

solved Java incrementing every character in a string by a large amount?