Caesars Cipher - Where am I going wrong here?

Tell us what’s happening:

Hello!

I’ve completed the assignment already using a different solution - but I cannot see why my first attempt won’t work. I’ve spent quite a long time trying to spot the mistake - please can somebody put me out of my misery and tell me why it won’t work this way?

Your code so far


function rot13(str) {
	let regex = /[A-Z]/;

	for (let i = 0; i < str.length; i++) {
		if (regex.test(str[i])) {
			str[i].charCodeAt() < 78
				? (str = str.replace(str[i], String.fromCharCode(str[i].charCodeAt() + 13)))
				: (str = str.replace(str[i], String.fromCharCode(str[i].charCodeAt() - 13)));
		}
	}

	return str;
}

// Change the inputs below to test
console.log(rot13("SERR PBQR PNZC"));
console.log(rot13('LBH QVQ VG!'));

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36.

Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/caesars-cipher

Not that the following will give you a correct solution, but it is a better approach to how you should be using the ternary operator. This help you to avoid the duplicate code you had and makes it a bit more readable.

for (let i = 0; i < str.length; i++) {
  if (regex.test(str[i])) {
    const num= str[i].charCodeAt() < 78 ? 13 : -13;
    const newCode = str[i].charCodeAt() + num;
    str = str.replace(str[i], String.fromCharCode(newCode));
  }
}

However, the real issue you are having is in the replace. Let’s walk through the above for loop to see what is happening:

1st iteration:
i=0, str[0]=S, newCode=70, String.fromCharCode(70)=F
so str becomes FERR PBQR PNZC
So far so good

2nd iteration:
i=1, str[1]=E, newCode=82, String.fromCharCode(82)=R
so str becomes FRRR PBQR PNZC
Still fine so far

3rd iteration:
i=2, str[2]=R, newCode=69, String.fromCharCode(69)=E
This is where the problem begins. Your replace instructs JavaScript to "replace the first instance of the letter R with E. so str becomes FERR PBQR PNZC

The replace method will find the first instance of where it matches what you put for the first argument and replaces it with what you specify in the second argument.

You will need to rethink your logic just a bit here to accomplish your ultimate goal.

Thanks for your response Randell, that has really helped me to understand :slightly_smiling_face:

My understanding of how .replace() worked was wrong, now it is much clearer! Much appreciated :+1: