简体   繁体   中英

Need help solving a javascript Caesar Cipher problem

I'm stuck doing the Caesar cipher problem. For those of you familiar with the problem, I'm not able to wrap around the alphabet, for example if I want to shift the string 'z' by 1, instead of getting 'a', i'll get '['. I know the reason this happens but I'm not able to come up with the proper code. Any help will be appreciated.

Here's my code:

const caesar = function(word, num) {
  let solved = ""
  num = num % 26;
  for (let i = 0; i < word.length ; i++) {
    let ascii = word[i].charCodeAt();
    if ((ascii >= 65 && ascii <= 90) || (ascii >= 97 && ascii <= 122)) {
      solved += String.fromCharCode(ascii + num) ;
    } else {
        solved += word[i]
      }
 }
 return solved;
}

You need to take the modulus under 26 after subtracting the char code of the first letter of the alphabet and add it back afterward to allow the cipher to wrap around. You will need to handle capital and lowercase letters separately.

 const caesar = function(word, num) { let solved = "" num = (num%26 + 26) % 26; for (let i = 0; i < word.length; i++) { let ascii = word[i].charCodeAt(); if ((ascii >= 65 && ascii <= 90)) { solved += String.fromCharCode((ascii - 'A'.charCodeAt(0) + num)%26 + 'A'.charCodeAt(0)); } else if(ascii >= 97 && ascii <= 122){ solved += String.fromCharCode((ascii-'a'.charCodeAt(0) + num) % 26 + 'a'.charCodeAt(0)); } else { solved += word[i] } } return solved; } console.log(caesar("abcdefghijklmnopqrstuvwxyzABCDEFGHI", 7));

Do the modulus when you add num to your ascii value. This way you don't scroll past the end of the range (and loop around if you are through the modulus (remainder)).

solved += String.fromCharCode((ascii + num)%26);

Out of interest, the ASCII codes for 'A` and 'a' are 0x41 and 0x61 respectively: upper and lower case letters differ by whether bit 0x20 is set (lower case) or not set (upper case).

Hence a bit-bashing algorithm to circular shift ASCII letters and maintain case would be strip the lower case bit, perform the shift, and re-insert the case bit:

 "use strict"; function caesarShiftLetter( letter, num) { let code = letter.charCodeAt(0); let lowerCaseBit = code & 0x20; // 0 or 0x20 let upperCaseCode = code - lowerCaseBit; if( upperCaseCode < 0x41 || upperCaseCode >= 0x41 + 26) { return letter; } num = 26 + num%26; // handle large negative shift values upperCaseCode = ((upperCaseCode - 0x41) + num) % 26 + 0x41; return String.fromCharCode( upperCaseCode | lowerCaseBit); } // to test: function caesarShiftString( str, num) { return Array.from(str).map(char => caesarShiftLetter( char, num)).join(''); } console.log( caesarShiftString( "abc... xyz, ABC... XYZ, I, II, III, IV, V, VI, VII, VIII, IX, X - 1,3,4,5,6,7,9, 10",-22 ) );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM