ruby - 简单密码 - 来自 Exercism 的 Ruby

标签 ruby string encryption caesar-cipher

我目前正在学习 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
  • .ord 方法 - 将字符转换为其 ASCII 值。 a = 'a'.ord 。为什么选择这个角色?不是 z 或其他字符?
  • .chars 方法 - 使用 .chars 方法将文本字符串分隔为每个单独的字符。 .chars 比 .split 更有效,因为它解析底层字节以返回字符串的字符(我已经阅读了 stackover 流上的 .chars 与 .split 的区别)。
  • .zip 方法 - 此方法用于比较原始纯文本字符和加密字符。
  • .map方法 - 使用 block 调用此方法并返回加密文本。
  • 内部 .map 方法 block ,有两个参数:char和key。 char 表示原始纯文本中的字符,key 表示加密的 key 字符。
  • 我无法理解这个 ALPHABET[(char.ord - a + key.ord - a) % ALPHABET.length]部分。
    ALPHABET 原始纯文本和加密 key 文本字符通过 .ord 方法转换为 ASCII 值。为什么从这些值中减去一个值?为什么使用 % 运算符和 ALPHABET.length?
  • .join方法 - 我猜 .join 用于加入转换后的加密字符。我的理解正确吗?

  • 第 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不是假的( nilfalse );否则,迭代 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 % 263 , 和 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/

    相关文章:

    Ruby - 更新哈希键以去除空格

    python - 使用 Python 的字符串的子字符串

    python - 我正在尝试从 python 正则表达式解析字符串 - 当字符串包含 ":"时无法解析

    algorithm - 如何在文本文件中找到 N 最长的行并将它们打印到标准输出?

    encryption - 引导节点时 Chef Cookbook 编译错误

    ruby-on-rails - 使用 ruby​​ on Rails 进行定时服务器事件

    ruby-on-rails - ruby on rails 知道你什么时候来自 redirect_back

    c# - 快速安全的密码算法C#

    javascript - 具有 AES 默认 key 扩展的 Crypto.JS - 在 Java 中解密

    ruby-on-rails - 按当天的 Active Record 顺序