我目前正在学习 Ruby,并尝试过 Simple Cipher 挑战。我现在正在研究以下解决方案,并试图进行逆向工程以了解该解决方案背后的思维过程。以下是解决方案的链接。我将详细说明我对每个代码片段的理解。如果他们不正确,你能纠正我吗?谢谢!
https://exercism.io/tracks/ruby/exercises/simple-cipher/solutions/b200c3d9f10e497bbe2ca0d826df2661
class Cipher
ALPHABET = [*'a'..'z']
attr_reader :key
def initialize(key = nil)
@key = key || 100.times.map { ALPHABET.sample }.join
fail ArgumentError, 'invalid chars in key' unless valid?(@key)
end
def encode(text)
a = 'a'.ord
text.chars.zip(@key.chars).map do |char, key|
ALPHABET[(char.ord - a + key.ord - a) % ALPHABET.length]
end.join
end
def decode(code)
code.chars.zip(@key.chars).map do |char, key|
ALPHABET[char.ord - key.ord]
end.join
end
private
def valid?(key)
!key.empty? && key !~ /[^a-z]/
end
end
第 1 部分
@key = key 是如果 key 匹配。
ALPHABET 是随机的(使用 .sample 方法)并加入。然后将随机连接的字母迭代 100 次并返回一个新数组(使用 map 方法)。
要处理无效键错误,请使用 fail ArgumentError。
def initialize(key = nil)
@key = key || 100.times.map { ALPHABET.sample }.join
fail ArgumentError, 'invalid chars in key' unless valid?(@key)
end
第 2 部分
我了解此代码的目的是将纯文本转换为加密文本。但是,我正在努力解决以下代码的某些部分。
def encode(text)
a = 'a'.ord
text.chars.zip(@key.chars).map do |char, key|
ALPHABET[(char.ord - a + key.ord - a) % ALPHABET.length]
end.join
end
ALPHABET[(char.ord - a + key.ord - a) % ALPHABET.length]
部分。ALPHABET 原始纯文本和加密 key 文本字符通过 .ord 方法转换为 ASCII 值。为什么从这些值中减去一个值?为什么使用 % 运算符和 ALPHABET.length?
第 3 部分
在这部分中,使用解码方法,代码。代码是两方(发送方和接收方)之间共享的 key 。但是为什么
ALPHABET[char.ord - key.ord]
?字符 ascii - key ascii 值将提供解密后的纯文本。我不明白它是如何工作的?def decode(code)
code.chars.zip(@key.chars).map do |char, key|
ALPHABET[char.ord - key.ord]
end.join
end
第 4 部分
私有(private)方法用于将这段代码与其他类分开。有效的方法是验证 key 。有两个条件:key 不能为空或者必须是小写字母。
private
def valid?(key)
!key.empty? && key !~ /[^a-z]/
end
最佳答案
@key = key is if key is matched. ALPHABET is randomized (with .sample method) and joined. Randomised joined alphabets are then iterated 100 times and a new array is returned (with map method).
@key = key
如果 key
不是假的( nil
或 false
);否则,迭代 100
次并从 ALPHABET
中收集一个随机字符;然后将生成的 100 元素数组连接成一个字符串并将该字符串分配给 @key
.什么都没有返回。ord method - convert a character to its ASCII value.
a = 'a'.ord
. Why is this character selected? Not z or other characters?
因为
"a"
以 Unicode 开始字母序列(在 ASCII 中也是如此,但 .ord
在这种情况下在 Unicode 上运行),值为 97
.但我们感兴趣的是字符在字母表中的位置,而不是 Unicode。可以这样想:现在是 20:37,你正在听歌剧。演出开始于19:00
.你听了多久了?你减去 20:37 - 19:00
, 得到答案(1 小时 37 分钟)。同样的,要知道 'c'
是 #2 字符(在英语中我们说是 3rd,但是 Ruby 从 0 开始计数,所以 'a'
是 #0,'c'
是 #2),你减去 'a'
的位置来自'c'
的位置: 99 - 97
.你不会减去 23:00
或来自 20:37
的任何其他时间,因为这对于找出你听了多长时间没有任何意义;我们使用 'a'.ord
的原因相同, 而不是 'z'
或其他角色。.zip method - this method is used to compare original plain text characters and encryption characters.
不,它只是通过将
text.chars
中的每个元素配对来创建一个新数组与 @key.chars
中的对应.没有比较。I have a trouble understanding this ALPHABET[(char.ord - a + key.ord - a) % ALPHABET.length] part. ALPHABET original plain text and encryption key text characters are converted into ASCII values with .ord method. Why a value is subtracted from those values? Why use % operator and ALPHABET.length?
关于为什么
a
见上文.该密码通过将每个字符偏移对应于 key 中适当字符的字母位置的空格数来工作。
%
将环绕,结果始终是 ALPHABET
的有效索引.例如,如果 char.ord - a + key.ord - a
恰好超过 ALPHABET
的长度,然后它会环绕到开始。例如,如果您得到 29
在上面的计算中,你通常会得到 nil
对于 ALPHABET[29]
因为没有字母#29;但是 29 % 26
是 3
, 和 ALPHABET[3]
已验证。Part 3 In this part, decode method, code is used. Code is the secret key shared between two parties (sender and receiver). But why ALPHABET[char.ord - key.ord]? Characters ascii - key ascii value will provide the decrypted plain text. I do not understand how it works?
转移的东西可以不转移;这就是解码的样子。之前我们将两个字符的位置相加 -
(char.ord - a) + (key.ord - a)
— 现在我们减去它们:(char.ord - a) - (key.ord - a)
.做一些数学运算,你会发现这两个 a
在这个减法中会互相抵消,所以 (char.ord - a) - (key.ord - a)
相当于char.ord - key.ord
.之前,我们担心添加可能会超出字母表的大小。在这里,人们可能会担心减法可能会变成负数。但是 Ruby 现在支持我们:
ALPHABET[-3]
在 Ruby 中的意思是“倒数第三个元素”,因此等价于 ALPHABET[23]
;不需要%
.
关于ruby - 简单密码 - 来自 Exercism 的 Ruby,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58907376/