Post your Caesar's Cipher solutions here! (Fall 2022)

Hey folks! Congrats on making it through week 4 of the free JS bootcamp!

Let’s post our solutions! Here’s my initial one:

const CHARACTER_CHART = {
  A: 'N',
  B: 'O',
  C: 'P',
  D: 'Q',
  E: 'R',
  F: 'S',
  G: 'T',
  H: 'U',
  I: 'V',
  J: 'W',
  K: 'X',
  L: 'Y',
  M: 'Z',
  N: 'A',
  O: 'B',
  P: 'C',
  Q: 'D',
  R: 'E',
  S: 'F',
  T: 'G',
  U: 'H',
  V: 'I',
  W: 'J',
  X: 'K',
  Y: 'L',
  Z: 'M'
};

function rot13(encodedStr) {
  let decodedStr = ""
  for (let i=0; i < encodedStr.length; i++) {
    const char = encodedStr[i];
    if (CHARACTER_CHART.hasOwnProperty(char)) {
      decodedStr += CHARACTER_CHART[char];
    } else {
      decodedStr += char;
    }
  }

  return decodedStr;
}
rot13("SERR PBQR PNZC");
1 Like

Here’s mine. Probably should have kept with strings instead of making it an array first haha

function rot13(str) {
  let unicode = [];
  for (let letter of str) {
    if (letter.match(/[A-M]/)) {
      unicode.push(letter.charCodeAt() - 13 + 26);
    } else if (letter.match(/[N-Z]/)) {
      unicode.push(letter.charCodeAt() - 13);
    } else if (letter.match(/[^A-Z]/)) {
      unicode.push(letter.charCodeAt());
    }
  }
  return String.fromCharCode(...unicode)
}

rot13("SERR PBQR PNZC");
console.log(rot13("SERR PBQR PNZC"))
4 Likes

Hi everyone!! :smile:

I have did this (using an array) because I did not know how to use ASCII at that moment and I am trying to update my array knowledge, but I will switch it later on. I wanted to share it anyway because is different, but it is not the best solution for sure. :sweat_smile: :rofl:

function rot13(str) {

  // reference: https://en.wikipedia.org/wiki/Caesar_cipher

  // Create an array with english alphabet to use as a model
  const arrALPHABET = [ 
    'A',
    'B',
    'C',
    'D',
    'E',
    'F',
    'G',
    'H',
    'I',
    'J',
    'K',
    'L',
    'M',
    'N',
    'O',
    'P',
    'Q',
    'R',
    'S',
    'T',
    'U',
    'V',
    'W',
    'X',
    'Y',
    'Z' 
  ];
  // arrALPHABET.forEach(letter => {
  //   console.log({letter, index: arrALPHABET.indexOf(letter)})
  // });

  // Creates an array from the argument string passed 
  // and it converts to to upper case
  const argArray  = [...str.toUpperCase()];
  // console.log(argArray);

  // Creates a new variable to hold indexes
  let letterIndex;

  // Map throw the array and applies the ROT13 cipher using arrALPHABET as reference
  return argArray.map( (item) => {
    
      // Check if the item is an empty space 
      // or the alphabet does not includes that character or symbol
      // and return it as it is
      if(item === " " || !arrALPHABET.includes(item)) {
        return item;
      }

      // Search for the index of the item inside our reference alphabet
      letterIndex = arrALPHABET.indexOf(item);

      // If the index after add 13 is bigger than our alphabet length
      // will start over from the beginning of the alphabet
      if(letterIndex + 13 > 25) {

          letterIndex = letterIndex - 26 + 13;
          // return the character found inside the alphabet at that index
          return item = arrALPHABET[letterIndex];
        }

      // If the index for that character + 13 is smaller 
      // or equal than arrALPHABET.length return the letter found at that spot
      return item = arrALPHABET[letterIndex + 13];
    })
      // Convert the resulting array into a string again
    .join("");
  
}

rot13("SERR PBQR PNZC");
// console.log(rot13("SERR YBIR!")); --> FREE LOVE!

Well done everybody!!

2 Likes

I didn’t want the extra solutions to be left out, so as a good adult I used them all :blush:

//num = 1 => cipher shifts each letter 1 to the right, so decipher shifts each letter 1 to the left: A => Z
function makeDecipherTable(num) { 
    //deal with input nums out of range
  if (Math.abs(num) > 26) { num = num % 26; }
  if (num < 0) { num = num + 26; }
  const decipherTable = {};
  const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  let currentLetter;
  for (let i = 0; i < 26; i++) {
    currentLetter = alphabet[i - num];
    if (!currentLetter) {
      currentLetter = alphabet[i - num + 26];
    }
    decipherTable[alphabet[i]] = currentLetter;
  }
  return decipherTable;
}

//arrow function with a look up object to convert the characters that have an entry in the table, and returns without change if not
const decode = (letter, table) => letter in table ? table[letter] : letter;
//function to decode each character in a string, using decode function as callback
const decodeString_1 = (str, decode) => str.replace(/[A-Z]/g, decode);
//other variations iterating over array for practice
const decodeString_2 = (str, decode) => [...str].map(letter => decode(letter)).join("");
const decodeString_3 = (str, decode) => [...str].reduce((a,b) => a + decode(b), "");
//special case ROT13 cipher
const decodeRot13 = (letter) => decode(letter, makeDecipherTable(13));
//take randomly one of the decoding functions to solve the problem
const rot13 = (str) => [decodeString_1, decodeString_2, decodeString_3][Math.floor(Math.random() * 3)](str, decodeRot13);
3 Likes

Here is my code:

function rot13(str) {
  const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 let newStr = "";
 for (let i = 0; i < str.length; i++) {
   let phil = alphabet.indexOf(str[i]);
   if (phil == -1) {
     newStr += str[i];
   } else {
     let newPhil = (phil + 13) % 26;
     newStr += alphabet[newPhil]; 
   } 
 }
  return newStr;
}
console.log(rot13("SERR PBQR PNZC"));
3 Likes

This is how I have done mine:
const lookUpTable = {
‘A’: ‘N’,
‘B’: ‘O’,
‘C’: ‘P’,
‘D’: ‘Q’,
‘E’: ‘R’,
‘F’: ‘S’,
‘G’: ‘T’,
‘H’: ‘U’,
‘I’: ‘V’,
‘J’: ‘W’,
‘K’: ‘X’,
‘L’: ‘Y’,
‘M’: ‘Z’,
‘N’: ‘A’,
‘O’: ‘B’,
‘P’: ‘C’,
‘Q’: ‘D’,
‘R’: ‘E’,
‘S’: ‘F’,
‘T’: ‘G’,
‘U’: ‘H’,
‘V’: ‘I’,
‘W’: ‘J’,
‘X’: ‘K’,
‘Y’: ‘L’,
‘Z’: ‘M’
};

const rot13 = str => {
// declare variable for storing the encrypted string
let encryptedString = ‘’;
// loop through all the character of the string
for(let i = 0; i <str.length; i++){
//check if the character is an alphabet
if (/[a-z]/i.test(str[i])) {
// encrypt the alphabet character
encryptedString += lookUpTable[str[i]];
}else {
// otherwise store the character without encrypting it
encryptedString += str[i];
}
}
// return encrypted final string
return encryptedString;
}
console.log(rot13(“GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.”));

2 Likes

Here is my initial solution, without the benefit of the solutions done in class. I might have time to try to debug the last solution done in class, but I didn’t have time to copy the code. (solution with ROTATION) If someone posts it, I’ll take a look at it, I think the unicode (?) character number computation is somewhat trivial compared to the rest of the work involved. Anyway here’s my initial solution:

function rot13(str) {
const alphabet = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’;
const alphabetCipher = ‘NOPQRSTUVWXYZABCDEFGHIJKLM’;
let rotStrArr = ;

for (let char of str.toUpperCase()) {
// check if current character is uppercase letter
let index = alphabet.indexOf(char);

// if not letter, append char, if letter, append letter shifted according to cipher
const cipheredChar = index === -1 ? char : alphabetCipher[index];
rotStrArr.push(cipheredChar);

}

// debug statement only
console.log(rotStrArr.join(‘’));

return rotStrArr.join(‘’);
}

rot13(‘SERR PBQR PNZC’);
rot13(‘Hello World’);
rot13(‘URYYB JBEYQ’);

2 Likes
function rot13(str) {
  const ALPHABET = [...Array(26).keys()].map((e,i)=> String.fromCharCode(i + 65));
  let newStr = ''
  let pos = -1;
  for(let c = 0; c < str.length; c++) {
    pos = ALPHABET.indexOf(str[c]);
    newStr += pos >= 0 ? ALPHABET[(pos + 13) %26] : str[c];
  }
  return newStr;
}
2 Likes

My solution:

const alphabet13 = {
  A: 'N',
  B: 'O',
  C: 'P',
  D: 'Q',
  E: 'R',
  F: 'S',
  G: 'T',
  H: 'U',
  I: 'V',
  J: 'W',
  K: 'X',
  L: 'Y',
  M: 'Z',
  N: 'A',
  O: 'B',
  P: 'C',
  Q: 'D',
  R: 'E',
  S: 'F',
  T: 'G',
  U: 'H',
  V: 'I',
  W: 'J',
  X: 'K',
  Y: 'L',
  Z: 'M'
}

function rot13(str) {
  const uncodedString = str.split('');
  const decodedString = [];
  uncodedString.forEach((letter, index) => {
    const isLetterRegex = /[A-Z]/g;
    if (isLetterRegex.test(letter) === true) {
      decodedString.push(alphabet13[letter]);
    } else {
      decodedString.push(letter);
    }
  });
  return decodedString.join('');
}

rot13("SERR PBQR PNZC");
2 Likes

Here is one of n solutions to Caesar’s Cipher.
Cheers, T.

const rot13 = (str) => {
  const shiftBy = 13;
  let charPositionInAlphabet = 0;
  let newCharPositionInAlphabet = 0;
  let strCeasarsCipher = "";

  // Traverse every character of the paramerter String "str"
  for (const chr of str) {
    // If the character is not an alphabet, add it to the Cipher string, and "continue"
    if (chr.match(/[\W_]/g)) {
      strCeasarsCipher += chr;

      continue;
    }
    
    // Find the postion of the current character (converted to Uppercase)
    // in the Alphabet (A-Z), where A=1, B=2, ... Z=26
    charPositionInAlphabet = (chr.toUpperCase().charCodeAt() -
                              "A".charCodeAt()) + 1;

    // What if the current character is E (Alphabet position 5)? Subtracting 13 (shiftBy in this case)
    // would result in NEGATIVE. But, the new Chiper character should be R
    (charPositionInAlphabet - shiftBy) > 0 ?
      newCharPositionInAlphabet = charPositionInAlphabet - shiftBy :
      newCharPositionInAlphabet = charPositionInAlphabet + shiftBy;

    // Build the new Cipher String
    strCeasarsCipher += String.fromCharCode("A".charCodeAt() - 1 + newCharPositionInAlphabet);
  }

  return strCeasarsCipher;
}

console.log(rot13("SERR PBQR PNZC"));
console.log(rot13("SERR CVMMN!"));
console.log(rot13("SERR YBIR?"));
console.log(rot13("GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT."));
1 Like

Hi Timiphil, yours is almost exactly the same as mine (the indexOf method saved my life for this one ;-)):

function rot13(str) {
// string for aphabet indexing:
  let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  let newString = "";
  let index = 0;

//looping through the encoded string:
  for (let i = 0; i < str.length; i++) {
    if(alphabet.indexOf(str[i]) === -1) {
      newString += str[i];
    } else if (alphabet.indexOf(str[i]) < 13) {
      index = alphabet.indexOf(str[i]) + 13;
      newString += alphabet[index];
    } else {
      index = alphabet.indexOf(str[i]) - 13;
      newString += alphabet[index];
    }  
  }
  return newString;
}
console.log(rot13("SERR PBQR PNZC"));
3 Likes
function rot13(str) {
//declare variable to be returned as initially empty string
let deciphered = "";
//loop through alphabet(i.e. individual alphabetic strings)
for (let i = 0;  i < str.length;  i++){
//declare asciiNum variable
let asciiNum = str[i].charCodeAt():
//if/else-if/else conditional statements
if(asciiNum >= 65 && asciiNum <= 77){
//add converted unicode values to characters(between 65 - i.e. "A" - and 77) using accumulator rule to initially declared variable
deciphered += String.fromCharCode(asciiNum + 13);
} else if(asciiNum >= 78 && asciiNum <= 90){ 
//add converted characters again using - 13 for characters between 78 and 90
deciphered += String.fromCharCode(asciiNum - 13);
} else {
//add function of string increment to accumulated (initially declared) variable
deciphered += str[i];
}
}
//return declared variable
return deciphered; 
}
2 Likes

Hey Brett - awesome that you got through the challenge! Well done!

For readability, you can post the solution as ‘code’, by selecting the post and either wrapping it in three backticks

```
code code code
```

There is also a shortcut in the menu, the icon looks like </>. Select all your code and hit that button :slight_smile:

Cheers!

2 Likes

Hi Sandra,
The indexOf() method is powerful syntax in Javascript. I enjoyed using it.

I’m glad you came up with a solution. Keep it going!!!

Happy Coding!

2 Likes

Hey Syl,
I appreciate your assistance with clarifying the steps to posting algorithms and associated shortcut menu instructions on Class Central.

Please have a good rest of your day/night.

1 Like

Whoops! I should have posted this in the Roman numeral section! Deleted.

But - while I am here - I cannot imagine EVER being able to do the Caesar’s Cipher problem without a great deal of handholding. :smile:

Update - I actually forgot I had attempted this one again last night - I needed a lot of help from the previous solutions in this chat - I don’t think I could attempt it alone yet.

I think the code here is asking whether a letter is present and, if so, to return the letter at the relevant index in the string - so it returns the “thing” and not the “key”, correct?
And the period(.) before test - is that the same as the period used when calling functions to objects? 'Scuse my ignorance :slight_smile:

if (/[A-Za-z]/.test(str[i]))
const ALPHABET = {
 "A": "N",
 "B": "O",
 "C": "P",
 "D": "Q",
 "E": "R",
 "F": "S",
 "G": "T",
 "H": "U",
 "I": "V",
 "J": "W",
 "K": "X",
 "L": "Y",
 "M": "Z",
 "N": "A",
 "O": "B",
 "P": "C",
 "Q": "D",
 "R": "E",
 "S": "F",
 "T": "G",
 "U": "H",
 "V": "I",
 "W": "J",
 "X": "K",
 "Y": "L",
 "Z": "M"
};

function rot13(str) {
let newStr = "";
for (let i=0; i<str.length; i++) {
  if (/[A-Za-z]/.test(str[i])) {
    newStr += ALPHABET[str[i]];

  } else {
    newStr += str[i];
  }
}
return newStr;

}
    
console.log(rot13("SERR PBQR PNZC"));
4 Likes

Hi Jane @Jane2963637

Please, don’t apologizes for not knowing something or asking. It is a great question, like mostly all that start for What… and How… Asking yourself and others is the first step to the deep knowledge.

Here a few quotes from people far smarter than me :wink: that I hope makes you feel better :

We are all very ignorant. What happens is that we are not all ignorant of the same things.
Albert Einstein

The ignorant affirms, the wise doubts and reflects.
Aristotle 384 BC - 322 BC

Being aware of one’s own ignorance is a great step towards knowledge.
Benjamin Disraeli (1804-1881)

True ignorance is not the absence of knowledge, but the refusal to acquire it.
Karl Popper (1902-1994)

After this digression… :sweat_smile: About your question:

Regular expressions are objects so they also have properties: regular ones and functions, last ones are called methods. You can access object’s properties using dot notation . and bracket notation [].

object.property or object[property or variable or expression]

  • The code loops throw the whole string.
  • Checks if the substring(letter / character, as spaces, for example) (at index i) match that regex.

/[A-Za-z]/.test(str[i]) return true or false

Access to the ALPHABET object using bracket notation, note that str[i] uses bracket notation as well and it is an expression. It is the same as ALPHABET[character] at index i.

  • If that condition is true, it concats the pair character from the ALPHABET object to the newStr string.

newStr += ALPHABET[str[i]];

  • If not just leave the character as it is in the new string, for example spaces.
 } else {
    newStr += str[i];
  }
  • Finally, return the new string we have created (newStr).

I hope I have explained it well enough to be understood. :smile:

Happy coding Jane!! Back to the JS basics, try to solve challenges with those basics and you will master this eventually. Those basics are mostly the same in all programming languages, so they are truly important. It will help you in the future. :sunglasses:

Links it might help you:

# MDN Web Docs Glossary: Definitions of Web-related terms

Python’s tutor It has an option for JS too. It helps to visualize the ejecution of your code

# Property accessors
# JavaScript object basics
#Method
#RegExp.prototype.test()

3 Likes

Thanks so much Carlos! Funnily enough, I am going through the early basic JavaScript exercises again today! I am (mostly) zooming through them this time. So this should help me with these problems in future.

That is what I thought was happening in the code - it is nice to have it all explained so well - thank you.

Thanks for all the quotes, and all the great links. Much appreciated! :grinning:

Happy coding to you as well! :slight_smile:

3 Likes

No problem Jane.

I am happy to help.

Have the best weekend!!

3 Likes
function rot13(str) {
//declare map to be used for letter conversion
const CONVERSION_MAP = {
'A':'N','B':'O','C':'P','D':'Q','E':'R','F':'S','G':'T','H':'U','I':'V','J':'W','K':'X','L':'Y','M':'Z','N':'A','O':'B','P':'C','Q':'D','R':'E','S':'F','T':'G','U':'H','V':'I','W':'J','X':'K','Y':'L','Z':'M'}

//Define empty converted string
let convertedStr = '';

//loop through str, retrieve letter from str, define convertedletters variable
for (let i=0; i < str.length; i++) {
  let letter = str[i];
  let convertedLetter = '';
//if letter is a letter then convert using conversion map and add to convertedLetter variable
  if (/[a-z]/i.test(letter)) {
    convertedLetter = CONVERSION_MAP[letter];
  }
//otherwise return symbol characters as they are not to be converted
else {
    convertedLetter = letter;
}
//Add each converted letter to string  
convertedStr += convertedLetter
}
//return fully converted string
  return convertedStr;
}
3 Likes