javascriptencryptionfromcharcode

Caesar cipher only gets first value right


My caesar cipher only works for the first letter, I've tried moving variables around, using a nested for loop, and just cant seem to figure it out. FREE PIZZA should translate to SERR CVMMN, but it gives me a bunch of weird symbols, and lowercase translations.

function rot13(str) { // LBH QVQ VG!
let x = str;
let y = [];
let n = ''
for(let i = 0; i < x.length; i++) {

    y.push(x.charCodeAt(i) + 13)

    console.log(x.charCodeAt(i))

}
console.log(y)

for(let j = 0; j < y.length; j++){
  console.log(y[j])
 n += String.fromCharCode(y[j])
}
console.log(n)

  return n;
}

Solution

  • When you use charCode, you get the unicode values of the characters, which are in the range 65–90 for the uppercase english alphabet. When you add 13, you get the unicode values for the characters "NOPQRSTUVWXYZ[]^_`abcdefg", which is not what you want.

    You need to find a way to only make english characters map to the the english character 13 steps away, and make this wrap around so that the later characters map to the earlier ones (so that Z maps to M).

    This is probably easier to achieve if you drop using unicode values, instead using your own alphabet, like in the snippet below:

    function rot13(str) {
      let x = str.toUpperCase();
      let y = [];
      let n = "";
      let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
      for (let i = 0; i < x.length; i++) {
        if (alphabet.indexOf(x.charAt(i)) > -1) {
          n += alphabet.charAt((alphabet.indexOf(x.charAt(i)) + 13) % 26);
        } else {
          n += x.charAt(i);
        }
      }
      return n;
    }
    
    console.log(rot13("FREE PIZZA"));

    An even simpler approach is to just use a lookup table (avoiding math altogether):

    function rot13(str) {
      let x = str.toUpperCase().split("");
      let table = {
        A: "N", B: "O", C: "P", D: "Q",
        E: "R", F: "S", G: "T", H: "U",
        I: "V", J: "W", K: "X", L: "Y",
        M: "Z", N: "A", O: "B", P: "C",
        Q: "D", R: "E", S: "F", T: "G",
        U: "H", V: "I", W: "J", X: "K",
        Y: "L", Z: "M"
      };
      for (let i = 0; i < x.length; i++) {
        if (table[x[i]]) {
          x[i] = table[x[i]];
        }
      }
      return x.join("");
    }
    
    console.log(rot13("FREE PIZZA"));