Caesars Cipher - other approaches?

Hey guys, just wanted to show my solution, I think it’s pretty simple and does the job! Hopefully some of you might find it useful.

function rot13(str) {
  var resp = [];
  var code = str.split('');
 
  for(var i=0;i<code.length;i++){
      var index = code[i].charCodeAt();
    
      if(index>77){
             resp.push(String.fromCharCode(index-13));
      }  else if(index<=77&&index>=65){
             resp.push(String.fromCharCode(index+13));
         }else if(index<65){
             resp.push(String.fromCharCode(index));
          }
  }      
        return resp.join('');
}

Cheers!

2 Likes

Here is my code as well; definitely need to work on regex. It would have made this a whole lot simpler like the example way above ^^

function rot13(str) { // LBH QVQ VG!
  var arr = [];
  var newString = '';
  for (var i = 0; i<str.length; i++){
      var val = str.charCodeAt(i);
    if (val >= 65 && val <= 90 ){
        if (val < 78){
          val += 13;
          var hold = String.fromCharCode(val);
          newString += hold; 
          }
        else if (val >= 78) {
          val -= 13;
          var holdE = String.fromCharCode(val);
          newString += holdE;
          }
     }
    else{
      newString += str[i];
     }
  }
   return newString;
}

Well, it took a long time to write this code without any hints. It may look quite dirty, but works perfectly. :heart_eyes:

function rot13(str) {
 var myStr = "";
 var charNum = 0;
  var arr = str.split(" ");

    for(j=0;j<arr.length;j++){
    var word = arr[j];
    var empcon = "";
     
        for(i=0;i<word.length;i++){         
        var new_sym ='';
        charNum = word.charCodeAt(i);

              if(charNum < 65 || charNum >90){
                new_sym = String.fromCharCode(charNum);
              }
              else if (charNum+13<=90){
              new_sym = String.fromCharCode(charNum+13);
              }else if(charNum+13>90){
              new_sym = String.fromCharCode(64 + (charNum+13-90));
              }
          
          empcon += new_sym ;
         }
     myStr += empcon + " ";
    }

return myStr.replace(/\s*$/,'');
} 

 // Change the inputs below to test
rot13("SERR PBQR PNZC.");

Here is mine in repl.it

Here is mine. It’s not pretty but I think it may be fairly legible to people with basic knowledge.


function rot13(str) { // LBH QVQ VG!
  
  var regEx = /[A-M]/;
  var regEx2 = /[N-Z]/;
  var holder = [];
  
   for (var i = 0; i < str.length; i++) { 
      if (regEx.test(str[i])) {           //test if str[i] is A-M
        holder[i] = str.charCodeAt(i)+13; //if true, push ASCII+13 to holder
      } else if (regEx2.test(str[i])) {   //test if str[i] is N-Z
        holder[i] = str.charCodeAt(i)-13; //if true, push ASCII-13 to holder
      } else if (!regEx.test(str[i]) && !regEx2.test(str[i])) { //test if str[i] is neither A-M nor N-Z, i.e non-alphabetic
        holder[i] = str.charCodeAt(i); //if true, push to holder as is
      }
     } return String.fromCharCode.apply(null, holder); //return holder array as string by using .apply method
  
}

// Change the inputs below to test
rot13("FREE PIZZA!");

I had to take a break from this one, disappointing being right at the end of those challenges. When I came back to it though, it was really fun to work through. I used a fairly simple solution without RegEx though:

function rot13(str) { // LBH QVQ VG!
  var tst = []; var i = 0;            // tst is array of inputs, i is iteration through strings
  var arr = [];                       // arr is array to return(?), l is length of strings to find
  ////////////////////////////////////////////////////////////////////////////////////////////////
  
  tst = str.split('');              // split string into array of strings no seperator counts each
                                    // element  
  
  function change(num) {                // function to get unicode of decoded letter
    if ((num > 90) || (num < 65)) { return num; }    // leave alone if not capital letter
    else if ((num + 13) > 90) {         // subtract if adding goes beyond Z
         return num - 13;
       }
    else return num + 13;               
  }
  
  while ( i < tst.length ) {            // iterate through array of strings to find uni vals
    var word = tst[i]; var uni = [];    // word is current string, uni is temp array of unicode
    var dec = [];                       // dec is array (yes another) to decypher unicode vals
      for ( var n=0; n < word.length; n++) {
        uni.push(word.charCodeAt(n));        // get array of unicode for decyphering
      }
    for (var p= 0; p< uni.length; p++) {    // loop through cyphered unicode
      dec.push(change(uni[p]));             // using change function, find decyphered unicode values
      arr.push(String.fromCharCode(dec[p]));  // create array of letters from decyphered unicode
      }
    i++;
  }
  /*x = arr.toString(); var re = (/,/g);
  x = x.replace(re, " ");*/
  //return String.fromCharCode(91);            //testing
  
  return arr.join('');                         // join to string (remove commas with (''))
  
}

// Change the inputs below to test              A=65, Z=90
rot13("XYNGH ORENGN AVXGH!");

I also find it fun to comment the crap out of challenges I finished afterward (can ya tell?)

TL;DR - Basically I made a function to translate unicode into letters and told it to leave anything that wasn’t a capital letter alone, that way I didn’t have to worry about putting spaces and exclamations back in. I’m happy with how it turned out.

Hey Campers!

I thought it’d be nice to share my solution with ya’ll. I took a simpler approach in solving this. I’m open for suggestions. Thanks!


function rot13(str) { // LBH QVQ VG!
  var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  str = str.split('');
  var res = '';

  for (var i = 0; i < str.length; i++) {
    if (alphabet.indexOf(str[i]) !== -1) {     // if letter exists in alphabet do the following
      if (alphabet.indexOf(str[i]) < 13) {      // if letter is positioned before the first 13 characters
        res += String.fromCharCode(str[i].charCodeAt(0) + 13);  // decode letter by adding 13 more ie 'E'->'R'
      } else {
        res += String.fromCharCode(str[i].charCodeAt(0) - 13); // if not, decode letter by subtracting 13 letter ie 'S'->'F'
      }
    } else {
      res += str[i];       // if character is not part of alphabet, simply append to solution string
    }
  }
  
  return res;
} 

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

Happy Coding~

what is the test method ?

Another nice thing about @joesmith100’s solution: you can make it case-insensitive by just adding i flags to both the regexes:

Spoiler
  return str.replace(/[A-Z]/ig, function(c) { 
    return String.fromCharCode(c.charCodeAt() + (/[A-M]/i.test(c) ? 13 : -13));
  });
}

rot13("serr PBQR PNZC");
1 Like

A post was split to a new topic: Caesars Cipher questions

@joesmith100

Creative, never would of thought of that.

Hi Everyone,

So I just finished Caesars Cipher. Mine was much different from the solutions provided in the guide, so I thought I would post it here to get some feedback. Let me know what you think. Thanks!

function rot13(str) { // LBH QVQ VG!
  var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var cipher = "NOPQRSTUVWXYZABCDEFGHIJKLM";
  
  var replacer = [];
  for (var x = 0; x < str.length; x++)  { //loops through the given string
  var index = alphabet.indexOf(str[x]);  //sets the index of letter from the coded string
  if (cipher.charCodeAt(index) > 0) {  //check to see if the letter is alphanumeric
     replacer.push(String.fromCharCode(cipher.charCodeAt(index))); //add to array
  }
    else replacer.push(str[x]); //adds non-alphanumeric to the array
  }
  return replacer.join(""); //combines it all back together
}

// Change the inputs below to test
rot13("SERR CVMMN!");

This is my solution. Someday maybe I’ll be able to made more efficient code. :frowning:

function rot13(str) { // LBH QVQ VG!
  
  var finish = str.length;
  var result = "";
  var letterA;
  var letterB;
 
  for (i = 0; i < finish; i++) {
    
    letterA = (str.charCodeAt(i));
    
    if (letterA >= 78 & letterA <= 90) {
      letterA = letterA - 13;
      letterB = String.fromCharCode(letterA);
      result = result + letterB;
    }
    else if (letterA >= 65 & letterA < 78) {
      letterA = letterA + 13;
      letterB = String.fromCharCode(letterA);
      result = result + letterB;
    }
    else if (letterA >= 32 & letterA <= 64) {
      letterA = letterA;
      letterB = String.fromCharCode(letterA);
      result = result + letterB;
    }
  }
  
  
  return result;
}

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

My code is very similar to yours, as all beginners are since we only know if statements.

I have seen 3 line solutions which i don’t understand:

–> freeCodeCamp Algorithm Challenge Guide: Caesars Cipher

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

I studied this. They are the Arrow functions: MDN

But I need more practice. The % 26 is very clever!

here is mine :slightly_smiling_face:

function rot13(str) { // LBH QVQ VG!

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

if (str.charCodeAt(i) >= 65 && str.charCodeAt(i)+13 <= 90) {
  newstrarray = newstrarray + String.fromCharCode(str.charCodeAt(i)+13);
}
  else if (str.charCodeAt(i)+13 > 90) {
    var newchar = str.charCodeAt(i)+13 - 90 + 64;
    newstrarray = newstrarray + String.fromCharCode(newchar);
  }
  else {
    newstrarray = newstrarray + str[i];
  }

}

str = newstrarray;
return str;
}

Here is my solution. I’m not using charCodeAt. Nevertheless it seems to work for the assertions of FCC.

Any tips?

function rot13(str) {

  var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var result = "";

  function shift(letter) {
    var shiftNum = 13;
    var index = alphabet.indexOf(letter);
    if (index >= shiftNum) {
     return alphabet[index - shiftNum];
    } else if (index < shiftNum) {
      return alphabet[index - shiftNum + alphabet.length];
    }
  }

  for (let i = 0; i < str.length; i++) {
    if (str[i].match(/\w/)) {
        result = result.concat(
            shift(str[i])
            );
    } else if (str[i].match(/\s/) || str[i].match(/\W/)) {
      result = result.concat(str[i]);
    }
  }
  return result;
}

If you’re going to do it that way and define the alphabet, why not define the alphabet after it’s been transformed as well (var rot13alphabet = "NOPQRSTUVWXYZAB..."), which gets rid of the first block of logic?

Check the index of the current character in the real alphabet. If the index is -1, ie it isn’t there (eg, it’s a space), just add that character to result. If it is there, add the character in the rot13 alphabet to result. Then no need for regex either (or character codes).

Good point, thanks for taking your time to review my code!