DEV Community

loading...

Coding Challenge: Caesar Cipher

Anthony Gedeon
An ambitious programmer that will change the world with software.
・3 min read

Around 58 BC, Julius Caesar created a substitution cipher. It could encrypt a message by moving each letter by a number. Say I wanted to encrypt my name, Anthony, here's how I would do it

Shift "Anthony" by 2 and the outcome will be "Cpvjqpa"

How the cipher works is simple, move every single letter to a new position. Here's an image explaining what I mean.

Alt Text

My Solution

As part of The Odin Project exercise, I was task with completing this challenge and passing all the given tests.

const caesar = function(string, shift) {
const encrypt = string.replace(/\w/g, letter => {
let letterToShift = ((((shift > 0 ? letter.toUpperCase().charCodeAt() - 65 : letter.toUpperCase().charCodeAt() + 65) + shift) % 26) + 65)
return String.fromCharCode(letterToShift);
});
return encrypt.replace(/(?<=\w)[\w]/g, letter => letter.toLowerCase())
}
Enter fullscreen mode Exit fullscreen mode




What the code does

So let's break down this code

  1. Each time the caesar function is called, it gets 2 arguments. Those arguments are 'Anthony' and 2.
  2. Were calling the replace method on the string argument which is Anthony. The first argument is a regex that takes every word character. The second argument is a function that when used will replace each letter. It's like Array.prototype.map but you can target what you want to replace.
  3. LetterToShift is a messy formula that calculates the shift. Here's how it works, in the innermost parenthesis I use a ternary operator because if the shift was negative then I would need to add 65 because I want it to go back to the char code of 65 (65 == "A"), but if it was greater than 0 then I would add 65.
  4. So since our shift is greater than 0 the following code converts "A" to uppercase and then get the char code of "A" which is 65 then it subtracts 65 which leads to 0
  5. Now add the 0 to the shift which is 2 and then use the modulo operator % by 26, 2 % 26 = 2
    • The purpose of the % is to get the number that corresponds with the shift in the alphabets
  6. Just add 2 + 65 and you get 67.

    "C".charCodeAt() // 67
    
  7. And fromCharCode(67) converts each charCode to the letter

  8. Repeat steps 3 - 7 for the matching letters.

  9. Once all letters have been replace exit the function and go to the last step which is

    encrypt.replace(/(?<=\w)[\w]/g, letter => letter.toLowerCase())

All this does is lowercase the letters that come after a Letter. For instance:

"ANTHONY" -> "Anthony"

"HELLO, WORLD!" -> "Hello, World!"

Enter fullscreen mode Exit fullscreen mode




Clarifications

  • 65-90 are all the uppercase alphabets (A-Z) that's why I need to uppercase all the matching letters

Refactoring

This code is a mess but fortunately, I had someone on twitter give me some guidance on how I could improve the caesar function.

Not a lot of major changes, but feel free to give me suggestions on what I can change.

Conclusion

Solving problems can be hard but also fun once you get the trick, I spent 2 days on this problem but eventually, I got it and with the help of @TypeEugene (Give him a follow on Twitter ) I was able to clean up some of the code.

Of course, this code is not perfect, I bet you could improve this code with ease, but unfortunately, I don't have good problem-solving skills YET. I know with time I will be able to stare at this code and find multiple ways to improve

Hope this helped you in some way!

Discussion (4)

Collapse
rodiongork profile image
Rodion Gorkovenko

Hi Friend :)

Please don't be offended, but as this exercise is quite common, there are some quite common hints about things to improve. One of particular is

- 65

try to make sure your code never has such magic constants :) make some constant like this

letterAcode = 'A'.charCodeAt(0);

and use it further in your code instead of 65. It will also prevent your code from breaking if you switch to some different codepage. This is only theoretical for Latin letters (they have same codes in almost all codepages), but quite adequate to make your code working with national alphabets...

Good luck!

Collapse
anthonygedeon profile image
Anthony Gedeon Author

Hey Rodion, I'm honestly never offended, I'm happy that I actually got my code reviewed once again!

So, describing what the magic number does with variable naming helps with clarification, gotcha! Oh and I don't have to worry about accidentally switching 65 to something else.

Thank you!

Collapse
rodiongork profile image
Rodion Gorkovenko

(on the other hand I'm glad that someone nowadays remember codes of letters!)

Anthony, just forgot to mention - by the way if you can lay your hands on the book "Clean Code" by Robert Martin - you may find it nice and useful. At least first 1/3 of it. Further the author becomes unbearable :)

Though perhaps you've already seen it, of course!

Thread Thread
anthonygedeon profile image
Anthony Gedeon Author

Clean Code has been on my book list for quite some time now, I will read it tonight.