# Caesars Cipher challenge [SOLVED]

I can’t see what the char methods to transform from/to ASCII has to do with rotating the char positions. I’m just stuck on that to begin with. Why’s important? I mean. Why do I have to do that in the first place?

Don’t worry about which char methods you might use until you develop an algorithm of how to solve the problem. Once you have outlined the steps your program would need to perform to solve the challenge (the algorithm), then you can research the various JavaScript functions available which will help you code your algorithm.

Thank you for your answer. Still, the instructions are confusing to me, and I quote:

One of the simplest and most widely known ciphers is a Caesar cipher, also known as a shift cipher. In a shift cipher the meanings of the letters are shifted by some set amount.

A common modern use is the ROT13 cipher, where the values of the letters are shifted by 13 places. Thus ‘A’ ‘N’, ‘B’ ‘O’ and so on.

Write a function which takes a ROT13 encoded string as input and returns a decoded string.

All letters will be uppercase. Do not transform any non-alphabetic character (i.e. spaces, punctuation), but do pass them on.

And then, you have to dig into this:

String.prototype.charCodeAt()
String.fromCharCode()

Seriously? I study those methods and I realize- what they’re good for in this challenge? So, I get stuck. I press the “emergency” Get a hint button, which tells me this:

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

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

Leave anything that doesn’t come between A-Z as it is.

Which is of no help to me, hence this post. And although, I appreciate your answer, the truth is that it confuses me even more (I’m sorry). Because, somehow, I see that none of the above is useful. So, how shall I continue?

And before you ask me about the written in natural language the algorithm, let me answer that it should be pretty straight forward: I’ve to rotate each character 13 positions. So, again, what the charCodeAt and fromCharCode methods has to do with that?

OK, maybe I can help you to understand how you might use charCodeAt and fromCharCode.

In the example function call:

``````rot13("SERR PBQR PNZC");
``````

you can look at the first test and see this is supposed to return the following string.

“FREE CODE CAMP”

The “S” becomes “F”, the “E” becomes “R”, the "R"s become "E"s and so forth. So the first 4 letters of the returned string will be “FREE”. You will also notice from the instructions that any character which is not A-Z should not be transformed.

You said your algorithm should be straight forward “rotate each character 13 positions”. How would you begin to do that? I see the following steps as a first pass attempt at an algorithm.

1. Start at the first character in the string.
2. Is this character the letter A-Z
3. If step #2 was Yes, continue to step #4 below. If not, do not convert the letter and go back to step 2.
4. Convert the current letter to the letter 13 characters beyond current letter.
5. Last character in string? If not, go back to step 2.
6. return converted string

Now that we have the basic steps, we need to break down how step #4 above would work. I will not give you the complete algorithm, but I will show you how you could get the first letter with a a different example with only one letter.
We will convert “E” to “R” (the letter 13 characters beyond “E”). We can not just add 13 to the letter “E” like:

``````var currentLetter = "E";
var convertedLetter = currentLetter + 13;
``````

The above would yield the string "E13 which is clearly not what we want. What we need to do is convert the letter “E” to an actual number to which we could then add the number 13. It just so happens that we can use the function charCodeAt to convert a specific character of a string to its ASCII Code. The integers 65-90 are the ASCII code equivalents of the letters A-Z. The charCodeAt function has one parameter which represents the index of the string (remember zero based). If you do not specify the index, the default of 0 is assumed. So, if I have:

``````var currentLetter = "E";
var asciiCode = currentLetter.charCodeAt();
``````

Now, asciiCode has the number 69 assigned to it and then we can do:

``````var plus13 = asciiCode + 13;
``````

Now plus13 is 82 which is the ASCII code for the letter “R”. Now we can use:

``````var convertedLetter = String.fromCharCode(plus13); // this converts the ASCII code 82 to the letter "R"
``````

No you see how to use these functions, you should be able to figure out an if statement or two to start the conversion process. The “tricky” part is how to deal with letters such as “Q”, which needs to convert to “D”. I will let you figure out that part by yourself.

3 Likes

Needless to say, your didactic ways helped me.
I’ve got it. I’m just struggling with the spaces for the time being.
Thank you.

Glad my ramblings helped you a little. Feel free to post what code you have so far and we can take a look to give you some hints for next steps.

1 Like

I’m here:

``````function rot13(str) {

var arr=str.split("");

var arr1=[];
var arr2=[];

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

var item=arr[i];

if (item.match(/[A-Z]/)) {

if ( item.charCodeAt() >=65 && item.charCodeAt() <=77 ) {

arr1.push(item.charCodeAt()+13);

}
else {

arr1.push(item.charCodeAt()-13);
}
}
}

for (j=0;j<arr1.length;j++){

var item2=arr1[j];
arr2.push(String.fromCharCode(item2));

}

var test=arr2.join("");
return test;
}
``````

But this returns some ascii as spaces, so, it doesn’t validate.

I was thinking in splitting the array on each word, then split again, and create new arrays as much words as were split? Sounds too convoluted.

OK. You are almost there. You have:

``````if (item.match(/[A-Z]/)) {
``````

Why not have an else with the following block which executes?

``````arr1.push(item.charCodeAt())
``````

This would convert spaces and punctuation which out shifting by +/- 13.

Also, since you are using some variant of the following several times in your code:

``````arr1.push(item.charCodeAt() ...)
``````

You could add the following before the if (item.match(/[A-Z]/)) { line of code:

``````var ascii = item.charCodeAt();
``````

and then instead of using arr1.push 2 different times in your code and not even need the else statement using the following in your inner if/else statement:

``````ascii += 13 // for the if
.
.
.
ascii -= 13 // for the else

``````

Then on the line following the closing } of the if (item.match(/[A-Z]/)) { statement, you could use one single instance
of the push function:

``````arr1.push(ascii);
``````

Everything else from the 2nd for loop and after would still work.

1 Like

Of course.
Your suggestions made the code cleaner and, the missing `else` did the trick. Really appreciated.

If you post your final solution, I might be able to give you extra pointers if you are interested.

1 Like

Of course I’m interested. But I feel kind of embarrassed for receiving so much help. Also, is not like cheating if I don’t realize myself of the lacking and improving details?

``````function rot13(str) {

var arr=str.split("");

var arr1=[];
var arr2=[];

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

var item=arr[i];
var ascii=item.charCodeAt();

if (item.match(/[A-Z]/)) {

if ( ascii >=65 && ascii <=77 ) {

ascii += 13;

}
else {

ascii -= 13;
}

arr1.push(ascii);
}
else {

arr1.push(item.charCodeAt());
}

}

for (j=0;j<arr1.length;j++){

var item2=arr1[j];
arr2.push(String.fromCharCode(item2));

}

var test=arr2.join("");

return test;
``````

I only helped explain how to use some functions and gave you a basic algorithm. The rest you came up with on your (minus the else statement suggestion). The whole point is you solved the challenge without someone just writing all the code out for you.

Now, since you have solved the problem, any advice I or anyone gives you on your solution is just extra learning you can store away in your brain for a later challenge.

OK, now for some solution suggestions. Since you already have the line:

``````var ascii=item.charCodeAt();
``````

you really don’t need the following else (I suggested)

``````   else {

arr1.push(item.charCodeAt());
}
``````

as long as you move the arr1.push(ascii); line outside of the if (item.match(/[A-Z]/)) { code block. Currently, it is on the last line of the true block.

Also, the following code:

`````` for (j=0;j<arr1.length;j++){
var item2=arr1[j];
arr2.push(String.fromCharCode(item2));
}
``````

creates an extra iteration of the arr1, when this can all be handled on a line right before the arr1.push(ascii); Create another variable (i.e. converted) and assign String.fromCharcode(ascii) to it.Then you would use arr1.push(converted) and avoid the extra for loop (an increase in efficiency).

Finally, instead of returning a joined version of arr2, you could simply write:

``````return arr1.join(""); // putting the join within the return statement avoids using the test variable.
``````
2 Likes

Thank you. That indeed cleaned even more. I’m the master of redundancy.
Well, I left a couple of challenges behind that I got stuck. I’ll get back to them.

You’re a great asset to this commnity.

1 Like