Caesar Cipher in Javascript

27,290

Solution 1

I have tried to make it simple and I earned FREE PIZZA!. Check my solution for this.

    function rot13(str) {
    
    var alphabets =['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'," ", "-", "_", ".", "&","?", "!", "@", "#", "/"];
    
    var alphabets13 = ['N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M', " ", "-", "_", ".", "&","?", "!", "@", "#", "/"];
    
    var resultStr = [];
    for(let i=0; i<str.length; i++){
        for(let j =0; j<alphabets.length; j++){
            if(str[i] === alphabets[j]){
            resultStr.push(alphabets13[j]);
            }
        }
    }
    return resultStr.join("");
  };

  rot13("SERR CVMMN!");

Solution 2

Using modulus operator; makes the sentence uppercase;

function cipherRot13(str) {
  str = str.toUpperCase();
  return str.replace(/[A-Z]/g, rot13);

  function rot13(correspondance) {
    const charCode = correspondance.charCodeAt();
    //A = 65, Z = 90
    return String.fromCharCode(
            ((charCode + 13) <= 90) ? charCode + 13
                                    : (charCode + 13) % 90 + 64
           );
    
  }
}

Solution 3

You can build the algorithm for ROT13 directly... or just use a Caesar Cipher algorithm with the appropriate key.

The alternative that I'm proposing to your example is just a particular usage of a regular Caesar Cipher algorithm – a very simple form of encryption, in which each letter in the original message is shifted to the left or right by a certain number of positions.

To decrypt the message we simply shift back the letters the same number of positions.

Example:

  • JAVASCRIPT becomes MDYDVFULSW if we shift all letters by 3 positions
  • MDYDVFULSW turns back to JAVASCRIPT if we shift back all letters by 3 positions.

If after shifting a letter goes outside the range of letters, then the letter is wrapped around in alphabet. Example: Letter Z becomes C if is shifted by 3 positions.

This “wrap-around” effect means use of modulo. In mathematical terms, the above can be expressed as this:

En(x) = (x + n) mod 26

Dn(x) = (x – n) mod 26

Trying to implement this algorithm in JavaScript without the use of a proper modulo operator will produce either incorrect results or a very cryptic and difficult to understand code.

The biggest problem is that JavaScript doesn't contain a modulo operator. The % operator is just the reminder of the division - not modulo. However, it is pretty easy to implement modulo as a custom function:

// Implement modulo by replacing the negative operand 
// with an equivalent positive operand that has the same wrap-around effect
function mod(n, p)
{
    if ( n < 0 )
        n = p - Math.abs(n) % p;

    return n % p;
}

There are other ways of implementing modulo... if you are interested you can consult this article.

By using the mod function defined above, the code expresses the mathematical equation identically:

// Function will implement Caesar Cipher to
// encrypt / decrypt the msg by shifting the letters
// of the message acording to the key
function encrypt(msg, key)
{
    var encMsg = "";

    for(var i = 0; i < msg.length; i++)
    {
        var code = msg.charCodeAt(i);

        // Encrypt only letters in 'A' ... 'Z' interval
        if (code >= 65 && code <= 65 + 26 - 1)
        {
            code -= 65;
            code = mod(code + key, 26);
            code += 65;
        }

        encMsg += String.fromCharCode(code);
    }

    return encMsg;
}

To encode using ROT13 ... is now just a matter of choosing the appropriate key as indicated by algorithm name.

Solution 4

Note : This function will take care of alphabetic(a-z or A-Z) and all others will be ignored.

Considered points are

  1. Handle negative number

  2. Can take care of big number.

  3. Handle special character, number and space will print as it is sd

    function caesarCipher(word, next) { next = next % 26; let res = ""; for (const letter of word) {

    let letterCode = letter.charCodeAt(0);
    if (letterCode >= 65 && letterCode <= 90) {
      letterCode = letterCode + next;
      if (letterCode > 90) {
        letterCode = letterCode - 26;
      } else if (letterCode < 65) {
        letterCode = letterCode + 26;
      }
    } else if (letterCode >= 97 && letterCode <= 122) {
      letterCode = letterCode + next;
    
      if (letterCode > 122) {
        letterCode = letterCode - 26;
      } else if (letterCode < 97) {
        letterCode = letterCode + 26;
      }
    }
    
        res = res + String.fromCharCode(letterCode);
      }
    
    return res;  }
    
    console.log(caesarCipher("Zoo  Keeper 666  %^&*(", 2));
    console.log(caesarCipher("Big Car", -16));
    

Output

Bqq  Mggrgt 666  %^&*(
Lsq Mkb

Solution 5

2020 TypeScript Version:

  • A shift argument must be given, but you can choose 13 for rot13 or any other number.
// TypeScript Type: Alphabet
type Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

// Helper Function: Caesar Cipher
export const caesarCipher = (string: string, shift: number) => {
  // Alphabet
  const alphabet: Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

  // Encoded Text
  let encodedText: string = '';

  // Adjust Shift (Over 26 Characters)
  if (shift > 26) {
    // Assign Remainder As Shift
    shift = shift % 26;
  }

  // Iterate Over Data
  let i: number = 0;
  while (i < string.length) {
    // Valid Alphabet Characters
    if (alphabet.indexOf(string[i]) !== -1) {
      // Find Alphabet Index
      const alphabetIndex: number = alphabet.indexOf((string[i]).toUpperCase());

      // Alphabet Index Is In Alphabet Range
      if (alphabet[alphabetIndex + shift]) {
        // Append To String
        encodedText += alphabet[alphabetIndex + shift];
      }
      // Alphabet Index Out Of Range (Adjust Alphabet By 26 Characters)
      else {
        // Append To String
        encodedText += alphabet[alphabetIndex + shift - 26];
      }
    }
    // Special Characters
    else {
      // Append To String
      encodedText += string[i];
    }

    // Increase I
    i++;
  }

  return encodedText;
};

Example #1:

console.log(caesarCipher('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 2));

Output:
CDEFGHIJKLMNOPQRSTUVWXYZAB

Example #2:

console.log(caesarCipher('GUR DHVPX OEBJA QBT WHZCRQ BIRE GUR YNML SBK.', 26 + 13));

Output:
THE QUICK BROWN DOG JUMPED OVER THE LAZY FOX.
Share:
27,290
unlucky
Author by

unlucky

Updated on April 02, 2022

Comments

  • unlucky
    unlucky about 2 years

    I am trying to write a program to solve the following problem in javascript (Written below this paragraph). I don't know why my code isn't working. Could someone help me? I'm new to javascript; this is a free code camp question.

    "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."

    function rot13(str) { // LBH QVQ VG!
      
      var string = "";
      for(var i = 0; i < str.length; i++) {
        var temp = str.charAt(i);
        if(temp !== " " || temp!== "!" || temp!== "?") {
           string += String.fromCharCode(13 + String.prototype.charCodeAt(temp));
        } else {
          string += temp;
        }
      }
      
      return string;
    }
    
    // Change the inputs below to test
    console.log(rot13("SERR PBQR PNZC")); //should decode to "FREE CODE CAMP"

    • therobinkim
      therobinkim about 7 years
      Standard debugging questions: What did you expect? (Looks like you already wrote it in as a comment as "FREE CODE CAMP.") What did you get instead? Any hypotheses as to why your result is different than what you wanted?
    • david25272
      david25272 about 7 years
      String.prototype.charCodeAt(temp) is not the way to call a method on a string (or any object), and you're using the wrong type of argument. Replace it with str.charCodeAt(i) and at least you'll start to to get some output. You should probably start to debug the rest of the errors yourself.
    • user3847870
      user3847870 about 4 years
      If user enters z , you are just adding 13 to its ascii value which is wrong. Try this function rot13(message) { var decipher = ''; for( var i = 0 ; i<message.length ; i++) { console.log(i); decipher=decipher+String.fromCharCode((message.charCodeAt(i)‌​+13 - 65)%26 + 65) } console.log(decipher); return decipher; }
  • melpomene
    melpomene about 7 years
    There are at least three different problems in OP's code.
  • melpomene
    melpomene about 7 years
    More feedback: OP's code never computes A+13 or Z+13.
  • Glen Pierce
    Glen Pierce about 7 years
    Ok, maybe you're seeing something I don't. The last line of code reads console.log(rot13("SERR PBQR PNZC")); //should decode to "FREE CODE CAMP"
  • melpomene
    melpomene about 7 years
    What's the significance of the last line?
  • Glen Pierce
    Glen Pierce about 7 years
    It includes the letter "Z", but now I think I see what you're saying... String.fromCharCode(13 + String.prototype.charCodeAt(temp)); Might this contain another of the three problems in question?
  • Ondiek Elijah
    Ondiek Elijah about 3 years
    Works like a charm