Caesars Cipher project

Please, can experienced developers help point out my error(s) on this Caeser’s Cipher project? I have retrieved decoded values from the Cipher input values but my challenge is that I want to account for the non-alphabtic characters and the return the value of the decoded Cipher. When I try to push none-alphabetic characters to the characters decoded, the characters are pushed more than once, example is when it gets to an empty string which it is supposed to push the empty string once so that when I join the Decoded array to string, the empty string is converted to space in the words. Same goes for other characters that are not empty string like (!,.) etc.

function rot13(str) { // LBH QVQ VG!
//encode a list of the english alphabets and set it to alpha 
const alpha = ['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'];
//encode a list of the caeser's cipher and set it to cipher
const cipher = ['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'];
//get the input values in encoded cipher and split to individual items
const inputStr = str.split('');
let regEX = /\W|\s/;
//create an empty container to hold the index values of found alpha letters and set it to alphaIndex;
const alphaIndex = [];
//iterate over the inputStr value to acess each item
for(let i = 0; i < inputStr.length; ++i){
  //check if an item is a string from english letter alphabets
  let index = alpha.indexOf(inputStr[i]);
  // console.log(index);
  //if letter is english letter alpha, take the index of the letter ocurrence and store it on the decodedIndex
  if(index >= 0){
    // console.log(inputStr[i]);
    alphaIndex.push(index);
    } else {
      alphaIndex.push(inputStr[i]);
    }
} // end of iteration for inputStr
//TESTING ALPHAINDEX
console.log(alphaIndex);
//create a container to hold the decoded values and set it to decoded
const decoded = [];

//iterate over the length of alphaIndex values to acess individual item
for(let i = alphaIndex.length; i > 0; --i){
  let popped = alphaIndex.shift();
  // console.log(popped) //take out the first values of alphaIndex
  for(let j = 0; j < cipher.length; ++j){
    if(popped === j){
      decoded.push(cipher[j]);
    }//
////////////////THIS IS WHERE I HAVE THE HUGE CHALLENGE
     if(regEX.test(popped)){
        decoded.push(popped);
     }//
  }
}

  // console.log(alphaIndex);
  console.log(decoded.join(''));
  // console.log(cipher[18]+cipher[4]+cipher[17]+cipher[17]+' '+ cipher[15]+cipher[1]+cipher[16]+cipher[17]+' '+cipher[15]+cipher[13]+cipher[25]+cipher[2])
  return str;
}

// Change the inputs below to test
// rot13("SERR PBQR PNZC");
rot13("SERR CVMMN!");
// rot13("GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.")

Can you format your code with a code block to make it easier to read :slight_smile:

Questioning here … couldn’t you cipher[???] here?

It looks like your cipher might break if you have for example rot13('pa55w0rd')

okay, it did not pass the test for the condition you gave rot13(‘pa55word’),
I am still learning, let me see how I can fix it.

I forgot this is one of the Javascript projects;

https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/javascript-algorithms-and-data-structures-projects/caesars-cipher

ignore what I said above… the test does not deal with numbers … only Capital letters/spaces/punctuation but you could handle them the same…

Look at your algorithm again and how you are processing what you have. I think you can trim out about half your code, everything after //TESTING ALPHAINDEX

I’ve edited your post for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

See this post to find the backtick on your keyboard. The “preformatted text” tool in the editor (</>) will also add backticks around text.

Note: Backticks are not single quotes.

markdown_Forums

1 Like

thank you so much, you have given me another clue on how to solve it, let me try out what I just figured from

Thank you @ilenia, looks better now. I appreciate

@pjonp, I did it, sir. Thank you so much for guiding me, I trimmed the code as you pointed out and figured out my mistake from the initial code. It passed all the test cases given. I also appreciate everyone that contributed to the success of writing this code, you are special people, thank you all. Here’s my code for the problem

function rot13(str) { // LBH QVQ VG!
    //encode a list of the english alphabets and set it to alpha 
    const alpha = ['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'];
    //encode a list of the caeser's cipher and set it to cipher
    const cipher = ['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'];
    //get the input values in encoded cipher and split to individual items
    const inputStr = str.split('');
    const regEX = /\W+|\s+/;
    const regEX2 = /[A-Z]/;
    //create an empty container to hold the index values of found alpha letters and set it to alphaIndex;
    const alphaIndex = [];
    //iterate over the inputStr value to acess each item
    for(let i = 0; i < inputStr.length; ++i){
      //check if an item is a string from english letter alphabets
      if(regEX2.test(inputStr[i])){
        //if it return true, get the index of the letter from alpha values
        let index = alpha.indexOf(inputStr[i]);
        // console.log(index);
        //iterate over the cipher values to acess each value by the index
        for(let j = 0; j < cipher.length; ++j){
          //check when an index value of cipher equals index value of alpha values, when equal, retrieve the letter value from cipher and push to alphaindex container else skip this
          if(index === j){
            alphaIndex.push(cipher[j]);
          }
        }
        //check if the skipped value returns true on testing if it is non-alphabetic characters
      } else if(regEX.test(inputStr[i])){
        // console.log(inputStr[i])
        // push the item of the inputStr that returns true for non-alphabetic characters
        alphaIndex.push(inputStr[i]);
      }
      

    } // end of iteration for inputStr
    //TESTING ALPHAINDEX
    console.log(alphaIndex.join(''));
   
      // console.log(cipher[18]+cipher[4]+cipher[17]+cipher[17]+' '+ cipher[15]+cipher[1]+cipher[16]+cipher[17]+' '+cipher[15]+cipher[13]+cipher[25]+cipher[2])
      //join and return the value of the alphaIndex containers to a string.
      return alphaIndex.join('');
      //WOW!!!!! I did it, couldn't believe I could, I believe there is a better way, I appreciate you all for guiding me on this. Special Thanks to Pjonb, you are great teacher.
    }
    
    // Change the inputs below to test
    rot13("SERR PBQR PNZC");
    rot13("SERR CVMMN!");
1 Like

I believe there is a better way to this problem far better than what I did, I would appreciate if you can give me a clue on that or better still point it out to me. I really need to build solid logical skill as this is my first time learning programming and my first language is JavaScript. Thank you once again.

      if(regEX2.test(inputStr[i])){
        //if it return true, get the index of the letter from alpha values
        let index = alpha.indexOf(inputStr[i]);
        // console.log(index);
        //iterate over the cipher values to acess each value by the index
        for(let j = 0; j < cipher.length; ++j){
          //check when an index value of cipher equals index value of alpha values, when equal, retrieve the letter value from cipher and push to alphaindex container else skip this
          if(index === j){
            alphaIndex.push(cipher[j]);
          }
        }

for example, this part here… what’s that j loop doing? do you really need it?
you have index, you need something from the cipher loop for when j === index. Can’t you directly do cipher[index]?

Hello @ilenia, it is unclear to me on how I can be able to access the values from the cipher without having to iterate over the values. when I get the index of my input letter from my alpha array, then I hold the value and try to compare the index values of cipher that gets equal to the input letter index; when an equal value is found, I copy the letter found at that index from my cipher array and save in my alphaIndex container. I will give a try to your suggestion too to see if I can still trim my code.

Wow!!! I applied your suggestion and it worked perfectly. Thank you for this also. I appreciate you, my mind wasn’t thinking in that manner initially. I looked closely at the bottom of my code and I saw where I was testing your suggestion but doing that one after the other, now your suggestion opened my mind on that automation instead of having to loop over cipher again. I appreciate you
Here it is;

if(regEX2.test(inputStr[i])){
        //if it return true, get the index of the letter from alpha values
        let index = alpha.indexOf(inputStr[i]);
        // console.log(index);
          //check when an index value of cipher equals index value of alpha values, when equal, retrieve the letter value from cipher and push to alphaindex container else skip this
            alphaIndex.push(cipher[index]);
          
        }

complete code

function rot13(str) { // LBH QVQ VG!
    //encode a list of the english alphabets and set it to alpha 
    const alpha = ['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'];
    //encode a list of the caeser's cipher and set it to cipher
    const cipher = ['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'];
    //get the input values in encoded cipher and split to individual items
    const inputStr = str.split('');
    const regEX = /\W+|\s+/;
    const regEX2 = /[A-Z]/;
    //create an empty container to hold the values of found alpha letters and set it to alphaIndex;
    const alphaIndex = [];
    //iterate over the inputStr value to acess each item
    for(let i = 0; i < inputStr.length; ++i){
      //check if an item is a string from english letter alphabets
      if(regEX2.test(inputStr[i])){
        //if it return true, get the index of the letter from alpha values
        let index = alpha.indexOf(inputStr[i]);
        // console.log(index);
        //retrieve the letter value from cipher and push to alphaindex container else skip this
            alphaIndex.push(cipher[index]);
        //check if the skipped value returns true on testing if it is non-alphabetic characters
      } else if(regEX.test(inputStr[i])){
        // console.log(inputStr[i])
        // push the item of the inputStr that returns true for non-alphabetic characters
        alphaIndex.push(inputStr[i]);
      }
      

    } // end of iteration for inputStr
    //TESTING ALPHAINDEX
    console.log(alphaIndex.join(''));
//THIS WAS WHERE I WAS TESTING ONE AFTER THE OTHER WHICH YOU POINTED MY MISTAKE. THANK YOU @ieahleen 
   
      // console.log(cipher[18]+cipher[4]+cipher[17]+cipher[17]+' '+ cipher[15]+cipher[1]+cipher[16]+cipher[17]+' '+cipher[15]+cipher[13]+cipher[25]+cipher[2])
      //join and return the value of the alphaIndex containers to a string.
      return alphaIndex.join('');
      
    }
    
    // Change the inputs below to test
    rot13("SERR PBQR PNZC");
    rot13("SERR CVMMN!");