1

I am new at javascript and this is the last course from Basic Algorithm Scripting.I am trying to understand this line of codes as I get on the next part of Front End Development Certificate from free code camp,I want to understand eveything.I've been looking for solutions and found this. I understand some lines on the comments but I am having a hard time understanding in the formula, this code works 100% but I just need some further understanding. This is the code:

function rot13(str) {

  //retCharArray is an Array of character codes for the solution
  var rotCharArray = [];

  //regular expression for all upper case letter from A to Z
  var regEx = /[A-Z]/;

  //split str into a character array
  str = str.split("");

  for (var x in str) { //iterate over each character in the array
    //regEx.test(str[x]) will return (true or false) if it maches the regEx or not
    if (regEx.test(str[x])) {
      // A more general approach
      // possible because of modular arithmetic 
      // and cyclic nature of rot13 transform

      // I DON'T CLEARLY UNDERSTAND THIS CODE BELOW
      rotCharArray.push((str[x].charCodeAt() - 65 + 13) % 26 + 65);
    } else {
      rotCharArray.push(str[x].charCodeAt());
    }
  }
  //make a string with character codes from an array of character codes
  str = String.fromCharCode.apply(String, rotCharArray);
  return str;
}

// Change the inputs below to test
rot13("SDASasd");
Barmar
  • 741,623
  • 53
  • 500
  • 612

3 Answers3

4

The two answers above go half way to answering your issue here, but they don't really see your problem which is that to answer the Free Code Camp challenge you have to go off and understand the math behind the caesar cypher and the ROT13 arithmetic. I had problems with this too.

Let's look at it together and go over it step by step. (I do understand not everyone studied this in high-school - I didn't!):

  // I DON'T CLEARLY UNDERSTAND THIS CODE BELOW
  rotCharArray.push((str[x].charCodeAt() - 65 + 13) % 26 + 65);
} else {
  rotCharArray.push(str[x].charCodeAt());
}

Both @bastos.sergio's and @caulitomaz's answers help, but they only partially explain and do not point you to further research:

@bastos.sergio's

"Get the modulo of 26 (this ensures that the encoding will not encrypt to anything above the 'Z' letter, for instance the 'Z' letter will convert to (90-65+13) % 26 + 65) = 77 'M' Letter. Essentially, it will make the encryption algorithm loop to the beginning."

@caulitomaz's

In the english alphabet there are 26 characters. That is why you apply the cypher rotation of 13 and then apply the modulo operation.

What they're both referring to here is "Modular Arithmetic":

Modular arithmetic shows that some numbers are 'congruent', that is they share the same remainder when a modulo operation is applied to them.

For example, 2 % 12, 14 % 12, 26 % 12 = remainder 2. This way, when you have numbers that must appear within a range, or a device that only show numbers in a range, then you can work out where that number 'loops back'.

Notice in my example, that used % 12 - this is the total hours that a 12-hour clock can show. So if it's 2am, and I want to know the time 12 hours later, I add 12. But my clock can't show 14:00 (not in 12-hour mode). Modulo 12 gives me the real time.

Example: It's 4am. My plane has been been delayed 29 hours (it's a terrible airline). How do I work out the new take off time? 4 + 29 % 12 = 9am. (If the delay was less than 24, I need to swap am/pm, but you should get the picture.)

ROT13

Here we have a special case of the rotational cipher with ROT 13 where applying the cipher twice will give you the original character to be encoded, because the alphabet only has 26 characters and 13 is exactly half of 26.

x = ROT13(ROT13(x))

So actually, we don't need to worry about adding 13 or subtracting 13 when applying or reversing the encryption, we just apply it again to get the original.

So, then, how the algorithm works:

  1. As already pointed out our character codes for uppercase A-Z are in the range 65 (A) to 90 (Z). But we want to work with modular arithmetic to find where the range of 0-26 the new letter falls . So subtract 65 from the character code of the target letter: str[x].charCodeAt() - 65

  2. Apply the cipher: add 13

    (str[x].charCodeAt() - 65 + 13)

  3. Apply the modulo to find the letter which has 'looped' around. Which for us is % 26 (the number of characters in the alphabet):

    (str[x].charCodeAt() - 65 + 13) % 26

  4. Add back the 65 so we have a character code within the range 65...90

    (str[x].charCodeAt() - 65 + 13) % 26 + 65)

Worked example(s):

ROT13(X)

'X'.charCodeAt(0) = 88

- 65 = 23 

+ 13 = 36

%26 = 10 

+65 = 75 

charCodeFrom(75) = K

ROT13(K)

'K'.charCodateAt(0) = 75

- 65 = 10

+ 13 = 23

%26 = 23

+65 = 88

charCodeFrom(88) = X

Source(s):

http://betterexplained.com/articles/fun-with-modular-arithmetic/ https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/what-is-modular-arithmetic

Sagar Thatte
  • 75
  • 1
  • 8
ortonomy
  • 653
  • 10
  • 18
1

Since you are using only uppercase characters, you need to understand which range of character codes you are working with. Uppercase 'A' corresponds to 65.

'A'.charCodeAt(0) returns 65

And your maximum value is 'Z', which corresponds to 90.

In the english alphabet there are 26 characters. That is why you apply the cypher rotation of 13 and then apply the modulo operation.

To retrieve a correct charCode, 65 is added again to the result.

rotCharArray.push((str[x].charCodeAt() - 65 + 13) % 26 + 65);

caulitomaz
  • 2,141
  • 14
  • 20
0

First. the code converts only uppercase letters (look at at the ascii table below)

(str[x].charCodeAt() - 65 + 13) % 26 + 65

This translates to,

  1. Get the charcode number (it will be between 65 and 90) subtract 65
  2. Add 13
  3. Get the modulo of 26 (this ensures that the encoding will not encrypt to anything above the 'Z' letter, for instance the 'Z' letter will convert to (90-65+13) % 26 + 65) = 77 'M' Letter. Essentially, it will make the encryption algorithm loop to the beginning.
  4. Add back 65

ASCII table

bastos.sergio
  • 6,684
  • 4
  • 26
  • 36