freeCodeCamp/guide/chinese/certifications/javascript-algorithms-and-d.../javascript-algorithms-and-d.../caesars-cipher/index.md

14 KiB
Raw Blame History

title localeTitle
Caesars Cipher 凯撒密码

:triangular_flag_on_post:如果卡住,请记得使用**Read-Search-Ask** 。尝试配对程序:busts_in_silhouette:并编写自己的代码:pencil:

:checkered_flag:问题说明:

  • 您需要编写一个函数该函数将使用_Caesar密码_编码的字符串作为参数并对其进行解码。
  • 这里使用的是ROT13其中字母的值移动了13位。例如'A' :left_right_arrow: 'N''T' :left_right_arrow: 'G'。
  • 你必须将它移回13个位置这样'N' :left_right_arrow: '一个'。

相关链接

:speech_balloon:提示1

使用_String.charCodeAt_将英文字符转换为ASCII。

现在尝试解决问题

:speech_balloon:提示2

使用_String.fromCharCode_将ASCII转换为英文字符。

现在尝试解决问题

:speech_balloon:提示3

保留AZ之间不存在的任何东西。

现在尝试解决问题

扰流警报!

警告牌

提前解决!

:beginner:基本代码解决方案

    function rot13(str) { 
      // Split str into a character array 
      return str.split('') 
      // Iterate over each character in the array 
        .map.call(str, function(char) { 
          // Convert char to a character code 
          x = char.charCodeAt(0); 
          // Checks if character lies between AZ 
          if (x < 65 || x > 90) { 
            return String.fromCharCode(x);  // Return un-converted character 
          } 
          //N = ASCII 78, if the character code is less than 78, shift forward 13 places 
          else if (x < 78) { 
            return String.fromCharCode(x + 13); 
          } 
          // Otherwise shift the character 13 places backward 
          return String.fromCharCode(x - 13); 
        }).join('');  // Rejoin the array into a string 
    } 

:rocket: 运行代码

代码说明:

  • 声明并初始化字符串变量nstr以存储已解码的字符串。
  • for循环用于循环输入字符串的每个字符。
  • 如果角色不是大写的英文字母即它的ascii不在65和91之间我们将保持原样并继续下一次迭代。
  • 如果它是大写的英文字母我们将从它的ascii代码中减去13。
  • 如果ascii代码小于78当它减去13时它将超出范围所以我们将为它添加26英文字母中的字母数以便在A之后它将返回Z.例如M 77 :left_right_arrow: 77-13 = 64不是英文字母+26 = 90 :left_right_arrow: Z90

相关链接

:sunflower:中级代码解决方案:

    // Solution with Regular expression and Array of ASCII character codes 
    function rot13(str) { 
      var rotCharArray = []; 
      var regEx = /[AZ]/ ; 
      str = str.split(""); 
      for (var x in str) { 
        if (regEx.test(str[x])) { 
          // A more general approach 
          // possible because of modular arithmetic 
          // and cyclic nature of rot13 transform 
          rotCharArray.push((str[x].charCodeAt() - 65 + 13) % 26 + 65); 
        } else { 
          rotCharArray.push(str[x].charCodeAt()); 
        } 
      } 
      str = String.fromCharCode.apply(String, rotCharArray); 
      return str; 
    } 
 
    // Change the inputs below to test 
    rot13("LBH QVQ VG!"); 

代码说明:

  • 在名为rotCharArray的变量中创建一个空数组来存储字符代码。
  • regEx变量存储从A到Z的所有大写字母的正则表达式。
  • 我们将str拆分为一个字符数组然后使用for循环遍历数组中的每个字符。
  • 使用if语句我们测试以查看字符串是否仅包含从A到Z的大写字母。
  • 如果返回true我们使用charCodeAt()函数和rot13转换返回正确的值否则返回初始值。
  • 然后,我们使用rotCharArray变量中的字符代码返回字符串。

算法说明:

ALPHA    KEY BASE             ROTATED    ROT13 
 ------------------------------------------------------------- 
 [A]     65  <=>   0 + 13  =>  13 % 26  <=>  13 + 65 = 78 [N] 
 [B]     66  <=>   1 + 13  =>  14 % 26  <=>  14 + 65 = 79 [O] 
 [C]     67  <=>   2 + 13  =>  15 % 26  <=>  15 + 65 = 80 [P] 
 [D]     68  <=>   3 + 13  =>  16 % 26  <=>  16 + 65 = 81 [Q] 
 [E]     69  <=>   4 + 13  =>  17 % 26  <=>  17 + 65 = 82 [R] 
 [F]     70  <=>   5 + 13  =>  18 % 26  <=>  18 + 65 = 83 [S] 
 [G]     71  <=>   6 + 13  =>  19 % 26  <=>  19 + 65 = 84 [T] 
 [H]     72  <=>   7 + 13  =>  20 % 26  <=>  20 + 65 = 85 [U] 
 [I]     73  <=>   8 + 13  =>  21 % 26  <=>  21 + 65 = 86 [V] 
 [J]     74  <=>   9 + 13  =>  22 % 26  <=>  22 + 65 = 87 [W] 
 [K]     75  <=>  10 + 13  =>  23 % 26  <=>  23 + 65 = 88 [X] 
 [L]     76  <=>  11 + 13  =>  24 % 26  <=>  24 + 65 = 89 [Y] 
 [M]     77  <=>  12 + 13  =>  25 % 26  <=>  25 + 65 = 90 [Z] 
 [N]     78  <=>  13 + 13  =>  26 % 26  <=>   0 + 65 = 65 [A] 
 [O]     79  <=>  14 + 13  =>  27 % 26  <=>   1 + 65 = 66 [B] 
 [P]     80  <=>  15 + 13  =>  28 % 26  <=>   2 + 65 = 67 [C] 
 [Q]     81  <=>  16 + 13  =>  29 % 26  <=>   3 + 65 = 68 [D] 
 [R]     82  <=>  17 + 13  =>  30 % 26  <=>   4 + 65 = 69 [E] 
 [S]     83  <=>  18 + 13  =>  31 % 26  <=>   5 + 65 = 70 [F] 
 [T]     84  <=>  19 + 13  =>  32 % 26  <=>   6 + 65 = 71 [G] 
 [U]     85  <=>  20 + 13  =>  33 % 26  <=>   7 + 65 = 72 [H] 
 [V]     86  <=>  21 + 13  =>  34 % 26  <=>   8 + 65 = 73 [I] 
 [W]     87  <=>  22 + 13  =>  35 % 26  <=>   9 + 65 = 74 [J] 
 [X]     88  <=>  23 + 13  =>  36 % 26  <=>  10 + 65 = 75 [K] 
 [Y]     89  <=>  24 + 13  =>  37 % 26  <=>  11 + 65 = 76 [L] 
 [Z]     90  <=>  25 + 13  =>  38 % 26  <=>  12 + 65 = 77 [M] 

相关链接

:rocket: 运行代码

:rotating_light:高级代码解决方案

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

算法说明:

理解在JavaScript中象征性地表示为%模运算符( 有时称为模运算符 )是理解算法的关键。
这是一个有趣的运算符,它出现在工程的各个地方,例如密码学。

基本上,对数字进行操作,它将数字除以给定的除数,并给出除法的余数。
例如,

  • 0 % 5 = 0因为0 / 5 = 0且余数为0

  • 2 % 5 = 2因为2 / 5 = 0 ,余数为2

  • 4 % 5 = 4因为4 / 5 = 0 ,余数为4

  • 5 % 5 = 0因为5 / 5 = 1且余数为0

  • 7 % 5 = 2因为7 / 5 = 1 ,余数为2

  • 9 % 5 = 4因为9 / 5 = 1而余数为4

  • 10 % 5 = 0因为10 / 5 = 2且余数为0

但你必须注意到这里的模式。
您可能已经注意到当它刚刚达到RHS值的倍数时惊人的模运算符会覆盖LHS值。
例如,在我们的例子中,当LHS = 5 ,它被包裹到0
要么
LHS = 10 ,它再次LHS = 10 0

因此,我们看到出现以下模式

 0 ⇔ 0 
 1 ⇔ 1 
 2 ⇔ 2 
 3 ⇔ 3 
 4 ⇔ 4 
 5 ⇔ 0 
 6 ⇔ 1 
 7 ⇔ 2 
 8 ⇔ 3 
 9 ⇔ 4 
 10 ⇔ 0 

因此,我们得出结论,使用模运算符,可以将一系列值映射到[ 0DIVISOR - 1 ]之间的范围。在我们的情况下,我们映射[ 5 - 9之间] [ 0 - 4 ]或映射[ 6 - 10 ]之间[ 0 - 4 ]。

你知道吗?

现在让我们考虑映射26数字的范围,即在[ 65 - 90 ]之间,它表示Unicode字符集中的大写[ 英文字母 ]到[ 0 - 25 ]之间的数字范围。

[A]  65 % 26 ⇔ 13 
 [B]  66 % 26 ⇔ 14 
 [C]  67 % 26 ⇔ 15 
 [D]  68 % 26 ⇔ 16 
 [E]  69 % 26 ⇔ 17 
 [F]  70 % 26 ⇔ 18 
 [G]  71 % 26 ⇔ 19 
 [H]  72 % 26 ⇔ 20 
 [I]  73 % 26 ⇔ 21 
 [J]  74 % 26 ⇔ 22 
 [K]  75 % 26 ⇔ 23 
 [L]  76 % 26 ⇔ 24 
 [M]  77 % 26 ⇔ 25 
 [N]  78 % 26 ⇔  0 
 [O]  79 % 26 ⇔  1 
 [P]  80 % 26 ⇔  2 
 [Q]  81 % 26 ⇔  3 
 [R]  82 % 26 ⇔  4 
 [S]  83 % 26 ⇔  5 
 [T]  84 % 26 ⇔  6 
 [U]  85 % 26 ⇔  7 
 [V]  86 % 26 ⇔  8 
 [W]  87 % 26 ⇔  9 
 [X]  88 % 26 ⇔ 10 
 [Y]  89 % 26 ⇔ 11 
 [Z]  90 % 26 ⇔ 12 

您可以注意到,[ 65 - 90 ]范围内的每个数字都映射到[ 0 - 25 ]之间的唯一数字。
您可能还注意到,每个给定数字(例如65 )映射到另一个数字(例如13 ),该数字可用作偏移值(即65 + OFFSET 以获得给定数字的ROT13。

例如65映射到13 ,可以作为偏移值,并添加到65 ,得到78

[A]  65 % 26 ⇔ 13 + 65 =  78 [N] 
 [B]  66 % 26 ⇔ 14 + 65 =  79 [O] 
 [C]  67 % 26 ⇔ 15 + 65 =  80 [P] 
 [D]  68 % 26 ⇔ 16 + 65 =  81 [Q] 
 [E]  69 % 26 ⇔ 17 + 65 =  82 [R] 
 [F]  70 % 26 ⇔ 18 + 65 =  83 [S] 
 [G]  71 % 26 ⇔ 19 + 65 =  84 [T] 
 [H]  72 % 26 ⇔ 20 + 65 =  85 [U] 
 [I]  73 % 26 ⇔ 21 + 65 =  86 [V] 
 [J]  74 % 26 ⇔ 22 + 65 =  87 [W] 
 [K]  75 % 26 ⇔ 23 + 65 =  88 [X] 
 [L]  76 % 26 ⇔ 24 + 65 =  89 [Y] 
 [M]  77 % 26 ⇔ 25 + 65 =  90 [Z] 
 [N]  78 % 26 ⇔  0 + 65 =  65 [A] 
 [O]  79 % 26 ⇔  1 + 65 =  66 [B] 
 [P]  80 % 26 ⇔  2 + 65 =  67 [C] 
 [Q]  81 % 26 ⇔  3 + 65 =  68 [D] 
 [R]  82 % 26 ⇔  4 + 65 =  69 [E] 
 [S]  83 % 26 ⇔  5 + 65 =  70 [F] 
 [T]  84 % 26 ⇔  6 + 65 =  71 [G] 
 [U]  85 % 26 ⇔  7 + 65 =  72 [H] 
 [V]  86 % 26 ⇔  8 + 65 =  73 [I] 
 [W]  87 % 26 ⇔  9 + 65 =  74 [J] 
 [X]  88 % 26 ⇔ 10 + 65 =  75 [K] 
 [Y]  89 % 26 ⇔ 11 + 65 =  76 [L] 
 [Z]  90 % 26 ⇔ 12 + 65 =  77 [M] 

代码说明:

  • String.prototype.replace 函数允许您基于某些模式匹配(由正则表达式定义)和转换函数 (应用于每个模式匹配)来转换String
  • 箭头函数语法用于将函数参数写入replace()
  • L表示单个单位,从每个模式匹配/[AZ]/g - 字母表中的每个大写字母,从AZ ,存在于字符串中。
  • 箭头函数对给定字符串中存在的英文字母的每个大写字母应用rot13变换。

相关链接

:clipboard:对贡献者的说明:

  • :warning: 请勿添加与任何现有解决方案类似的解决方案。如果您认为它**相似但更好** ,那么尝试合并(或替换)现有的类似解决方案。
  • 添加解决方案的说明。
  • 将解决方案分为以下类别之一 - 基本 中级高级:traffic_light:
  • 如果您添加了任何**相关的主要内容,**请仅添加您的用户名。 :warning: 不要 删除任何现有的用户名

看到:point_right: Wiki Challenge Solution Template供参考。