# freeCodeCamp Algorithm Challenge Guide: Caesars Cipher

freeCodeCamp Algorithm Challenge Guide: Caesars Cipher
0
#1

Remember to use `Read-Search-Ask` if you get stuck. Try to pair program and write your own code

### Problem Explanation:

• You need to write a function, which will take a string encoded with Caesar cipher as a parameter and decode it.
• The one used here is ROT13 where the value of the letter is shifted by 13 places. e.g. βAβ βNβ, βTβ βGβ.
• You have to shift it back 13 positions, such that βNβ βAβ.

## Hint: 1

Use String.charCodeAt() to convert the English character to ASCII.

try to solve the problem now

## Hint: 2

Use String.fromCharCode() to convert ASCII to English character.

try to solve the problem now

## Hint: 3

Leave anything that doesnβt come between A-Z as it is.

try to solve the problem now

## Basic Code Solution:

``````function rot13(str) {
// Split str into a character array
return str.split('')
// Iterate over each character in the array
.map.call(str, function(char) {
// Convert char to a character code
x = char.charCodeAt(0);
// Checks if character lies between A-Z
if (x < 65 || x > 90) {
return String.fromCharCode(x);  // Return un-converted character
}
//N = ASCII 78, if the character code is less than 78, shift forward 13 places
else if (x < 78) {
return String.fromCharCode(x + 13);
}
// Otherwise shift the character 13 places backward
return String.fromCharCode(x - 13);
}).join('');  // Rejoin the array into a string
}
``````

### Code Explanation:

• A string variable `nstr` is declared and initialized to store the decoded string.
• The for loop is used to loop through each character of the input string.
• If the character is not uppercase English alphabets(i.e. its ascii doesnβt lie between 65 and 91 ), weβll leave it as it is and continue with next iteration.
• If itβs the uppercase English alphabet, weβll subtract 13 from itβs ascii code.
• If the ascii code is less than 78, itβll get out of range when subtracted by 13 so weβll add 26 (number of letters in English alphabets) to it so that after A itβll go back to Z. e.g. M(77) 77-13 = 64(Not an English alphabet) +26 = 90 Z(90).

## Intermediate Code Solution:

``````// Solution with Regular expression and Array of ASCII character codes
function rot13(str) {
var rotCharArray = [];
var regEx = /[A-Z]/ ;
str = str.split("");
for (var x in str) {
if (regEx.test(str[x])) {
// A more general approach
// possible because of modular arithmetic
// and cyclic nature of rot13 transform
rotCharArray.push((str[x].charCodeAt() - 65 + 13) % 26 + 65);
} else {
rotCharArray.push(str[x].charCodeAt());
}
}
str = String.fromCharCode.apply(String, rotCharArray);
return str;
}

// Change the inputs below to test
rot13("LBH QVQ VG!");
``````

### Code Explanation:

• An empty array is created in a variable called `rotCharArray` to store the character codes.
• The `regEx` variable stores a regular expression for all uppercase letters from A to Z.
• We split `str` into a character array and then use a for loop to loop through each character in the array.
• Using an if statement, we test to see if the string only contains uppercase letters from A to Z.
• If it returns true, we use the `charCodeAt()` function and rot13 transformation to return the correct value, otherwise we return the initial value.
• We then return the string with the character codes from the `rotCharArray` variable.

### Algorithm Explanation:

``````ALPHA	KEY	BASE 	 	 	 ROTATED	ROT13
-------------------------------------------------------------
[A]     65  <=>   0 + 13  =>  13 % 26  <=>  13 + 65 = 78 [N]
[B]     66  <=>   1 + 13  =>  14 % 26  <=>  14 + 65 = 79 [O]
[C]     67  <=>   2 + 13  =>  15 % 26  <=>  15 + 65 = 80 [P]
[D]     68  <=>   3 + 13  =>  16 % 26  <=>  16 + 65 = 81 [Q]
[E]     69  <=>   4 + 13  =>  17 % 26  <=>  17 + 65 = 82 [R]
[F]     70  <=>   5 + 13  =>  18 % 26  <=>  18 + 65 = 83 [S]
[G]     71  <=>   6 + 13  =>  19 % 26  <=>  19 + 65 = 84 [T]
[H]     72  <=>   7 + 13  =>  20 % 26  <=>  20 + 65 = 85 [U]
[I]     73  <=>   8 + 13  =>  21 % 26  <=>  21 + 65 = 86 [V]
[J]     74  <=>   9 + 13  =>  22 % 26  <=>  22 + 65 = 87 [W]
[K]     75  <=>  10 + 13  =>  23 % 26  <=>  23 + 65 = 88 [X]
[L]     76  <=>  11 + 13  =>  24 % 26  <=>  24 + 65 = 89 [Y]
[M]     77  <=>  12 + 13  =>  25 % 26  <=>  25 + 65 = 90 [Z]
[N]     78  <=>  13 + 13  =>  26 % 26  <=>   0 + 65 = 65 [A]
[O]     79  <=>  14 + 13  =>  27 % 26  <=>   1 + 65 = 66 [B]
[P]     80  <=>  15 + 13  =>  28 % 26  <=>   2 + 65 = 67 [C]
[Q]     81  <=>  16 + 13  =>  29 % 26  <=>   3 + 65 = 68 [D]
[R]     82  <=>  17 + 13  =>  30 % 26  <=>   4 + 65 = 69 [E]
[S]     83  <=>  18 + 13  =>  31 % 26  <=>   5 + 65 = 70 [F]
[T]     84  <=>  19 + 13  =>  32 % 26  <=>   6 + 65 = 71 [G]
[U]     85  <=>  20 + 13  =>  33 % 26  <=>   7 + 65 = 72 [H]
[V]     86  <=>  21 + 13  =>  34 % 26  <=>   8 + 65 = 73 [I]
[W]     87  <=>  22 + 13  =>  35 % 26  <=>   9 + 65 = 74 [J]
[X]     88  <=>  23 + 13  =>  36 % 26  <=>  10 + 65 = 75 [K]
[Y]     89  <=>  24 + 13  =>  37 % 26  <=>  11 + 65 = 76 [L]
[Z]     90  <=>  25 + 13  =>  38 % 26  <=>  12 + 65 = 77 [M]
``````

``````function rot13(str) { // LBH QVQ VG!
return str.replace(/[A-Z]/g, L => String.fromCharCode((L.charCodeAt(0) % 26) + 65));
}
``````

### Algorithm Explanation:

Understanding modulo operator (sometimes called modulus operator) symbolically represented as `%` in JavaScript is key to understanding the algorithm.
This is an interesting operator which shows up in various places of Engineering e.g. in cryptography.

Basically, operated on a number, it divides the number by the given divisor and gives the remainder of the division.
For Example,

• `0 % 5 = 0` because `0 / 5 = 0` and the remainder is `0`.
• `2 % 5 = 2` because `2 / 5 = 0` and the remainder is `2`
• `4 % 5 = 4` because `4 / 5 = 0` and the remainder is `4`
Β
• `5 % 5 = 0` because `5 / 5 = 1` and the remainder is `0`
• `7 % 5 = 2` because `7 / 5 = 1` and the remainder is `2`
• `9 % 5 = 4` because `9 / 5 = 1` and the remainder is `4`
Β
• `10 % 5 = 0` because `10 / 5 = 2` and the remainder is `0`

But you must have noticed a pattern here.
As you might have noticed, the amazing modulo operator wraps over the LHS value when it just reaches multiples of the RHS value.
e.g. in our case, when `LHS = 5`, it wrapped over to `0`
OR
when `LHS = 10`, it wrapped over to `0` again.

Hence, we see the following pattern emerging

`````` 0 β 0
1 β 1
2 β 2
3 β 3
4 β 4
5 β 0
6 β 1
7 β 2
8 β 3
9 β 4
10 β 0
``````

Hence, we conclude that using modulo operator, one can map a range of values to a range between [`0` to `DIVISOR - 1`]. In our case, we mapped [`5 - 9`] between [`0 - 4`] or mapped [`6 - 10`] between [`0 - 4`].

Did you understand till this?

Now let us consider mapping a range of `26` numbers i.e. between [`65 - 90`] (which represents uppercase English alphabets in Unicode character set) to a range of numbers between [`0 - 25`].

``````[A]  65 % 26 β 13
[B]  66 % 26 β 14
[C]  67 % 26 β 15
[D]  68 % 26 β 16
[E]  69 % 26 β 17
[F]  70 % 26 β 18
[G]  71 % 26 β 19
[H]  72 % 26 β 20
[I]  73 % 26 β 21
[J]  74 % 26 β 22
[K]  75 % 26 β 23
[L]  76 % 26 β 24
[M]  77 % 26 β 25
[N]  78 % 26 β  0
[O]  79 % 26 β  1
[P]  80 % 26 β  2
[Q]  81 % 26 β  3
[R]  82 % 26 β  4
[S]  83 % 26 β  5
[T]  84 % 26 β  6
[U]  85 % 26 β  7
[V]  86 % 26 β  8
[W]  87 % 26 β  9
[X]  88 % 26 β 10
[Y]  89 % 26 β 11
[Z]  90 % 26 β 12
``````

As you can notice, each number in the range of [`65 - 90`] maps to a unique number between [`0 - 25`].
You might have also noticed that each given number (e.g. `65`) maps to another number (e.g. `13`) which can be used as an offset value (i.e. `65 + OFFSET`) to get the ROT13 of the given number.

E.g. `65` maps to `13` which can be taken as an offset value and added to `65` to give `78`.

``````[A]  65 % 26 β 13 + 65 =  78 [N]
[B]  66 % 26 β 14 + 65 =  79 [O]
[C]  67 % 26 β 15 + 65 =  80 [P]
[D]  68 % 26 β 16 + 65 =  81 [Q]
[E]  69 % 26 β 17 + 65 =  82 [R]
[F]  70 % 26 β 18 + 65 =  83 [S]
[G]  71 % 26 β 19 + 65 =  84 [T]
[H]  72 % 26 β 20 + 65 =  85 [U]
[I]  73 % 26 β 21 + 65 =  86 [V]
[J]  74 % 26 β 22 + 65 =  87 [W]
[K]  75 % 26 β 23 + 65 =  88 [X]
[L]  76 % 26 β 24 + 65 =  89 [Y]
[M]  77 % 26 β 25 + 65 =  90 [Z]
[N]  78 % 26 β  0 + 65 =  65 [A]
[O]  79 % 26 β  1 + 65 =  66 [B]
[P]  80 % 26 β  2 + 65 =  67 [C]
[Q]  81 % 26 β  3 + 65 =  68 [D]
[R]  82 % 26 β  4 + 65 =  69 [E]
[S]  83 % 26 β  5 + 65 =  70 [F]
[T]  84 % 26 β  6 + 65 =  71 [G]
[U]  85 % 26 β  7 + 65 =  72 [H]
[V]  86 % 26 β  8 + 65 =  73 [I]
[W]  87 % 26 β  9 + 65 =  74 [J]
[X]  88 % 26 β 10 + 65 =  75 [K]
[Y]  89 % 26 β 11 + 65 =  76 [L]
[Z]  90 % 26 β 12 + 65 =  77 [M]
``````

### Code Explanation:

• `String.prototype.replace` function lets you transform a `String` based on some pattern match (defined by a regular expression), and the transformation function (which is applied to each of the pattern matches).
• Arrow function syntax is used to write the function parameter to `replace()`.
• `L` represents a single unit, from every pattern match with `/[A-Z]/g` - which is every uppercase letter in the alphabet, from `A` to `Z`, present in the string.
• The arrow function applies the `rot13` transform on every uppercase letter from English alphabet present in the given string.

## NOTE TO CONTRIBUTORS:

• DO NOT add solutions that are similar to any existing solutions. If you think it is similar but better, then try to merge (or replace) the existing similar solution.
• Categorize the solution in one of the following categories β Basic, Intermediate and Advanced.

See `Wiki Challenge Solution Template` for reference.

18 Likes

Question about these type of exercices (Roman Numeral Converter & Caesars Cipher)
Caesars Cipher to web browser
Caesars Cipher - other approaches?
closed #2
0 Likes

opened #3
0 Likes

#4

hi buddy iβm confused about βwhen do you use call in the map functionβ. can you please explain?

1 Like

#5

The call() method calls a function with a given this value and arguments provided individually.

MDN

Personally I think it can be done without it.

1 Like

#6

The Basic Code Solution no longer matches the basic Code Explanation.

17 Likes

#7

yes it can @Rafase282

2 Likes

#8

The advanced solution is very nice.

6 Likes

#9

Hi coders, I did ROT13 in a bit different way than others posted solutions here. Just wanna share with you guys to see if it is a good solution or not and plus how could I improve it. Thanks

``````
function rot13(str) { // LBH QVQ VG!
var newStr = "";

for ( var i = 0; i < str.length; i++ ) {

char = str.charCodeAt(i);

if ( char < 65 || char > 90 ) {
char = char;
}
else {
char += 13;

if ( char > 90 ) {
char = ( char - 90 ) + 64;
}
}

newStr += String.fromCharCode(char);
}

return newStr;
}``````
33 Likes

#10

Hey, I like your code. Mine looks actually quite similar but maybe a smidgen cleaner and more readable. Check it out:

(Sorry couldnβt figure out how to style it properly on the fly so I just cut it outβ¦ Is there a template or something? ;))

27 Likes

#11

yeah its a bit nicer, keep coding.

2 Likes

#12

This was my answer, any pointers or feedback greatly appreciated as iβm sure it could be optimised/tidied. Thanks!

``````function rot13(str) { // LBH QVQ VG!
// Create new empty array
var newWord = [];
// create for loop for length of str
for (i = 0; i < str.length; i++) {
// put charcode at i in to it's own variable
var newLet = str.charCodeAt(i);
// if charcode is between A-Za-z
if (newLet >= 65 && newLet <= 90) {
// take away 13 from the charcode
newLet -= 13;
// if charcode is now below A-Z (in the numbers)
if (newLet < 65) {
// add 26 to get to A-Z equivalent
newLet += 26;
}
}
// push the new charcode, converted to the actual character, in to an array
newWord.push(String.fromCharCode(newLet));
}
// join the array back together and return the answer
return newWord.join('');
}``````
1 Like

#13

This was my attempt

12 Likes

#14

Thank you. I also followed a similar path; and IMHO our way looks much prettier than others . The place I was stuck (and the reason why I came to this wiki) was how to solve the rotation within A - Z range. Didnβt think of using the center location (letter N-78) and moving forward/backward.
Very nice. This was fun.

2 Likes

#15

1 Like

#16

I did the same solution too

1 Like

#17
``````function rot13(str) { // LBH QVQ VG!
var arr = str.split("");
var newVal=0;

return arr.map(function(val){

if (val !== " " && val.charCodeAt() >= 65 && val.charCodeAt() <= 90){

newVal= val.charCodeAt() + 13;

if ( newVal  > 90){
newVal-= 26;
}

newVal = String.fromCharCode(newVal);

return newVal;

}
else{
return val;
}

}).join("");

}
``````

This is a solution I made without using a for loop.

4 Likes

#18

Hereβs what I did:

``````function rot13(str){
return str.split('').map(function(val){
var c = val.charCodeAt(0) - 65;
if (c >= 0 && c <= 25)
return String.fromCharCode( ((c + 13) % 26) + 65 );
else
return val;
}).join('');
}
``````
1. Split the string to get individual characters.
2. Shift character values to a range between 0 and 25 (26 characters) by subtracting 65. If a character is not in the range, skip and return the array value;
Ex: `66` is the code for letter `B`. If we do `66 - 65` we get `1`, so that A is in position 0, B in 1, C in 2 etc.
3. Add 13 (our rot value) to the value.
4. Get the modulo 26 of the operation. If the number is less than 26, we get the same number. If itβs larger than 26, we get the remainder.
Ex: `13 % 26 = 13` and `42 % 26 = 16`.
5. Return the result and shift back to the actual letter codes.
6. Join back return;
3 Likes

#19

Please what is wrong with my code?
function rot13(str) { // LBH QVQ VG!
var b =[];
var c =[]; var res =[];

for(i=0; i < str.length; i++){
b.push(str.charCodeAt(i));
}

for(j=0; j < b.length; j++){
if(b[j] >= 65 && b[j] <=77 ){
c.push(b[j]+13);
}else if( b[j]>=78 && b[j] <=90){
c.push(b[j]-13);
} else if (b[j] === 32 || b[j] === (β!β,β?β,β.β) ){
c.push(b[j]);
}
} for(v = 0; v < c.length; v++){ res.push(String.fromCharCode(c[v]));}
return res.join(ββ);
}

// Change the inputs below to test
rot13(βSERR PBQR PNZCβ);

1 Like

#20

Changed to this:
function rot13(str) { // LBH QVQ VG!
var newWord = [];

for(i=0; i < str.length; i++){
var newLet = str.charCodeAt(i);

if(newLet >= 65 && newLet <=77 ){
newLet += 13;
}else if( newLet >=78 && newLet <=90){
newLet -= 13;
}else if (newLet === 32 || newLet === (β!β,β?β,β.β)){

newLet = newLet;
}

``````newWord.push(String.fromCharCode(newLet));
``````

}

return newWord.join(ββ);
}

Why this one works? What about β!β,"?" and β.β ?

2 Likes