Caesars Cipher not working : prints double whitespace & "C↵" to console

Hello!

Not the most refined code but I think I’m almost there. My goal is to solve then refine where I can. Anyways, I’m getting weird characters added to my code somehow.

["F", "R", "E", "E", " ", "C", "O", "Da", "E", " ", "C↵", "A", "M", "P"]

The above array was copied/pasted directly from chrome js console. It is the result of console.log(result);

Looking at the above array, three odd characters are coming up in my code :
1)“Da” - ok, when looking at this while I type this topic preview and in my js console there is no “Da” it looks like “D”. When I submit this topic it comes up “Da”. ??

2)whitespace - the last whitespace between “E” & “C↵” in my chrome js console actually looks like a string with whitespace but two characters long such as “blank blank” and not just “blank”. It is not showing in the preview as I type this topic.

3)“C↵” - where the heck did this come from??

I would like it to look like :

["F", "R", "E", "E", " ", "C", "O", "D", "E", " ", "C", "A", "M", "P"]

Does anyone know why I get a whitespace character with twice the whitespace, the very odd "C↵" and why “D” comes out “Da” ? Bizarre!

 function rot13(str) {
      //string to array : 
      var arr = str.split(''); 
      console.log(arr);// ["S", "E", "R", "R", " ", "P", "B", "Q", "R", " ", "P", "N", "Z", "C"]
      //empty array will hold unicode 
      var unicode = [];
      //empty array that will hold shifted unicode 
      var shifted = [];
      //loop through arr and change each letter to unicode :
     for(var i = 0; i < arr.length; i++) {
          var toUnicode = arr[i].charCodeAt(arr[i]);
          unicode.push(toUnicode);
        }
      console.log(unicode);//[83, 69, 82, 82, 32, 80, 66, 81, 82, 32, 80, 78, 90, 67]
      //we need to loop through array unicode and check whether each item needs
      //to be shifted by +13 or by -13
      //we also need a place to put the new values
      for(var j = 0; j < unicode.length; j++) {
        if(unicode[j] == 32) {
          shifted.push(unicode[j]);
        }
        else if (unicode[j] >= 65 && unicode[j] <= 77 ) {
            shifted.push(unicode[j] + 13);
        } else {
            shifted.push(unicode[j] - 13);
       }
      }
      console.log(shifted);//[70, 82, 69, 69, 32, 67, 79, 68, 69, 32, 67, 65, 77, 80]
      var result = shifted.map(String.fromCharCode);
      console.log(result);//["F", "R", "E", "E", " ", "C", "O", "Da", "E", " 	", "C↵", "A", "M", "P"]

    }

    rot13("SERR PBQR PNZC");

Hi.

It’s too late here, to study or discover your code, so I’ll give you some tips:

  1. You need to split your str (string):
    Explanation: you have got from string “LOL” array of [“L”, “O”, “L”]
  2. Then you need to transform your array of string to array of numbers using ASCII table:
    Explanation: transform this array [“L”, “O”, “L”] to this one [76, 79, 76]
  3. The next step is using for loop (for example) to shift letters:
    Explanation: conver this [76, 79, 76] to this one [89, 66, 89]
  4. Then you can convert numbers to letters:
    Explanation: [89, 66, 89] —> [“Y”, “B”, “Y”]
  5. The last step is to convert array to string:
    Explanation: [“Y”, “B”, “Y”] —> “YBY”

Useful functions:
charCodeAt()
fromCharCode()
push()
split()

Hope, this tips will help you. Good luck!

The way you are using String.fromCharCode with map is the issue. Map passes several arguments to the inner function. The first is the value of the current item. The second is the index in the array, which is where the \u0000 and \u0001 come from (add more character codes and you get \u0002, \u0003…). The third argument is a reference to the array that is being traversed, which is converted to the number \u0000.

String.fromCharCode excepts one or more arguments and combines them all together after converting them to their corresponding string values. Hence, after the map, instead of an array of characters with each length = 1, you have an array of characters with each length = 3 (one for each of the arguments passed in)

Since you only want to use the array item, then you need to do one of the following:

var result = shifted.map(function(item) { return String.fromCharCode(item) });

or using arrow functions in ES6:

var result = shifted.map(item => String.fromCharCode(item));
1 Like

Just wanted to send a big thanks! for explaining this. It is not always easy to figure out what is happening under the hood in JavaScript and you’re explanation is an enlightenment. I tried the code and it works great.

Thanks again for everyone’s help!

My current working solution. If anyone has suggestions on how I can tighten this up I would appreciate it :

function rot13(str) {
  var arr = str.split(''); 
  var unicode = [];
  var shifted = [];
 for(var i = 0; i < arr.length; i++) {
      var toUnicode = arr[i].charCodeAt(arr[i]);
      unicode.push(toUnicode);
    }
for(var j = 0; j < unicode.length; j++) {
    if(unicode[j] == 32) {
      shifted.push(unicode[j]);
    } else if(unicode[j] == 32) {
      shifted.push(unicode[j]);
    } else if(unicode[j] == 33) {
      shifted.push(unicode[j]);
    } else if(unicode[j] == 63) {
      shifted.push(unicode[j]);
    } else if(unicode[j] == 46) {
      shifted.push(unicode[j]);
    } else if (unicode[j] >= 65 && unicode[j] <= 77 ) {
        shifted.push(unicode[j] + 13);
    } else {
        shifted.push(unicode[j] - 13);
   }
  }
  var result = shifted.map(function(item) { return String.fromCharCode(item) }).join('');  

return result;

}