14 KiB
title | localeTitle |
---|---|
Caesars Cipher | 凯撒密码 |
如果卡住,请记得使用**Read-Search-Ask
** 。尝试配对程序并编写自己的代码
问题说明:
- 您需要编写一个函数,该函数将使用_Caesar密码_编码的字符串作为参数并对其进行解码。
- 这里使用的是ROT13,其中字母的值移动了13位。例如'A' 'N','T' 'G'。
- 你必须将它移回13个位置,这样'N' '一个'。
相关链接
- String.prototype.charCodeAt
- 使用String.fromCharCode
提示:1
使用_String.charCodeAt()_将英文字符转换为ASCII。
现在尝试解决问题
提示:2
使用_String.fromCharCode()_将ASCII转换为英文字符。
现在尝试解决问题
提示:3
保留AZ之间不存在的任何东西。
现在尝试解决问题
扰流警报!
提前解决!
基本代码解决方案
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
}
代码说明:
- 声明并初始化字符串变量
nstr
以存储已解码的字符串。 - for循环用于循环输入字符串的每个字符。
- 如果角色不是大写的英文字母(即它的ascii不在65和91之间),我们将保持原样并继续下一次迭代。
- 如果它是大写的英文字母,我们将从它的ascii代码中减去13。
- 如果ascii代码小于78,当它减去13时它将超出范围,所以我们将为它添加26(英文字母中的字母数),以便在A之后它将返回Z.例如M (77) 77-13 = 64(不是英文字母)+26 = 90 Z(90)。
相关链接
中级代码解决方案:
// 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]
相关链接
高级代码解决方案
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
因此,我们得出结论,使用模运算符,可以将一系列值映射到[ 0
到DIVISOR - 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
- 字母表中的每个大写字母,从A
到Z
,存在于字符串中。- 箭头函数对给定字符串中存在的英文字母的每个大写字母应用
rot13
变换。
相关链接
对贡献者的说明:
- 请勿添加与任何现有解决方案类似的解决方案。如果您认为它**相似但更好** ,那么尝试合并(或替换)现有的类似解决方案。
- 添加解决方案的说明。
- 将解决方案分为以下类别之一 - 基本 , 中级和高级 。
- 如果您添加了任何**相关的主要内容,**请仅添加您的用户名。 ( 不要 删除任何现有的用户名 )