3

My ROT13 JS function works fine for the most part, but some of the characters just come out wrong, e.g. HELLO comes back with U,R,Y,Y,\.

Could somebody please explain to me what I am doing wrong?

P.s I'm doing the freeCodeCamp Caesars Cipher Challenge.

function rot13(str) { // LBH QVQ VG!
  var stringArray = str.split("");
  var stringArray2 = [];
  var stringArray3 = [];
  for( var i in stringArray){
    var y = stringArray[i].charCodeAt();
    y += 13;
    stringArray2.push(y);
  }
  for (var u in stringArray2){
    var x = String.fromCharCode(stringArray2[u]);
    stringArray3.push(x);
  }
  var transformed = stringArray3.join().toString();
  return transformed;
}

// Change the inputs below to test
console.log(rot13("HELLO"));
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • Welcome to SO! Could you provide an example of the function not working, like input:...., expected:...., but got: ..... – georg Apr 03 '17 at 09:54
  • Of course, sorry for not including it in the entry in the first place! "HELLO" comes back with " U, R, Y, Y, \" –  Apr 03 '17 at 09:58
  • Thanks! Ok, two problems: first (minor): you need `.join('')`, not just `.join()` to get rid of commas. Second (major): this thing is called "rot" for a reason: when `y+13` is greater than `Z` it should *rotate* and start from the beginning, that is, `Z + 13` should give `A + 12` etc. – georg Apr 03 '17 at 10:08
  • I get it, now that I think about it this way it looks so obvious! Guess I was too deep in thoughts about other aspects of the problem! Thank you, that really clarifies what happened! –  Apr 03 '17 at 11:36

2 Answers2

0

I'd like to offer you an alternative to your ROT13 function.

The alternative that I'm proposing is just a particular usage of a regular Caesar Cipher algorithm – a very simple form of encryption, in which each letter in the original message is shifted to the left or right by a certain number of positions.

To decrypt the message we simply shift back the letters the same number of positions.

Example:

  • JAVASCRIPT becomes MDYDVFULSW if we shift all letters by 3 positions
  • MDYDVFULSW turns back to JAVASCRIPT if we shift back all letters by 3 positions.

If after shifting a letter goes outside the range of letters, then the letter is wrapped around in alphabet. Example: Letter Z becomes C if is shifted by 3 positions.

This “wrap-around” effect means use of modulo. In mathematical terms, the above can be expressed as this:

En(x) = (x + n) mod 26

Dn(x) = (x – n) mod 26

Trying to implement this algorithm in JavaScript without the use of a proper modulo operator will produce either incorrect results or a very cryptic and difficult to understand code.

The biggest problem is that JavaScript doesn't contain a modulo operator. The % operator is just the reminder of the division - not modulo. However, it is pretty easy to implement modulo as a custom function:

// Implement modulo by replacing the negative operand 
// with an equivalent positive operand that has the same wrap-around effect
function mod(n, p)
{
    if ( n < 0 )
        n = p - Math.abs(n) % p;

    return n % p;
}

There are other ways of implementing modulo... if you are interested you can consult this article.

By using the mod function defined above, the code expresses the mathematical equation identically:

// Function will implement Caesar Cipher to
// encrypt / decrypt the msg by shifting the letters
// of the message acording to the key
function encrypt(msg, key)
{
    var encMsg = "";

    for(var i = 0; i < msg.length; i++)
    {
        var code = msg.charCodeAt(i);

        // Encrypt only letters in 'A' ... 'Z' interval
        if (code >= 65 && code <= 65 + 26 - 1)
        {
            code -= 65;
            code = mod(code + key, 26);
            code += 65;
        }

        encMsg += String.fromCharCode(code);
    }

    return encMsg;
}

To encode using ROT13 ... is now just a matter of choosing the appropriate key as indicated by algorithm name.

codeguppy
  • 175
  • 2
  • 4
0
function rot13(str) {
  str = str.split("");
  function a(item){
    let result;
    if (item.charCodeAt()>=65&&item.charCodeAt()<78){
      result= String.fromCharCode(item.charCodeAt()+13); 
    }
    else if(item.charCodeAt()>=78&&item.charCodeAt()<=95){
      result= String.fromCharCode(item.charCodeAt()-13);
    }
    else{
      result = item;
    }
    return result;
  }
  str = str.map(item=>a(item)).join("");
  console.log(str);
  return str;
}

rot13("GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.");