javascriptfunctionfor-loopcaesar-cipher

how to ignore punctuation and symbols in Caesar Cipher



const alphabet = 'abcdefghijklmnopqrstuvwxyz';
let code = 2;

function decodeMessage(message, secret) {
    let decoded = ''


    for (let i = 0; i < message.length; i++) {
        let charNum = message.charCodeAt(i);



          decoded += String.fromCharCode(((message.charCodeAt(i) + secret - 97) % 26) + 97);
      

        }
        return decoded
   
}


const message = 'hello, how are you doing, my general?';
const secret_msg = decodeMessage(message, code);
console.log('Secret =>', secret_msg);

setTimeout(() => {
    code *= -1;
    const message_encoded = decodeMessage(secret_msg, code);
    console.log('Original =>', message_encoded);
}, 3000)

I was expecting it to return: 'hello, how are you doing, my general?', but instead, it converts symbols and space into other symbols and capitalized letters. I do not use and need capitalized letters in the cipher.

Secret => jgnnqHVjqyVctgVaqwVfqkpiHVoaVigpgtcn[

Original => helloThowTareT_ouTdoingTm_TgeneralY

Thank you.


Solution

  • You have two issues in your code : the punctuation should not be ciphered, and when secret is negative, the ciphered character underflows the alphabet list.

    To avoid ciphering the punctuation, you could use a regular expression. The regex below use \w to match word letters and set punctuation apart. Then each word is ciphered with your Caesar algorithm and punctuation is set up again at its place.

    To fix the second issue (that shows _ instead of y in your example), you can add 26 before applying the modulo, to guarantee to work with a positive number before adding 97.

    Here is the fixed decodeMessage function :

    function decodeMessage(message, secret) {
      let decoded = ''
    
      // step through words using a regular expression
      let expression = new RegExp(/([^\w]*)(\w+)([^\w]*)/g);
      let result = expression.exec(message);
    
      // global regex exec method will return null as soon as no more match is found
      while(result){
        decoded += result[1];
        for (let i = 0; i < result[2].length; i++) {
          let charNum = result[2].charCodeAt(i);
          decoded += String.fromCharCode((((result[2].charCodeAt(i) + secret - 97 + 26) % 26) + 97));
        }
        decoded += result[3];
    
        // match the next word
        result = expression.exec(message);
      }
      return decoded 
    }