【问题标题】:Caesar's cipher in Ruby凯撒的红宝石密码
【发布时间】:2015-08-04 03:49:41
【问题描述】:

我正在处理左移 1 的凯撒密码问题,但开始有困难。提示要求我查看 Ruby 文档中的 String 方法 #ord 和 Integer 方法 #chr。并且字母 'a' 必须转移到 'z'...

下面是我的作品..

def solve_cipher(string, n)
letters = ['a'..'z']
string.map {|x| letters.include?(x.ord + n).chr : x}.join

感谢您的建议...!

【问题讨论】:

  • 你的问题太宽泛了。请包括您的工作结果和问题所在(您实际上具体需要什么帮助?)。例如,您可以声明您将“ABC”发送到您的函数并输出“!$%”,这不是您所期望的 - 但您不确定原因。
  • 欢迎来到 Stack Overflow。在寻求调试帮助时,您需要提供示例输入、预期输出以及演示您在问题本身中遇到的问题所需的最少代码。您的示例方法不完整,也没有我们可以使用的数据。请帮助我们帮助您并提供数据并使该方法至少在语法上正确。

标签: ruby caesar-cipher


【解决方案1】:

你需要将split你的话变成单个字符。然后您需要使用ord 将字符转换为整数,以便进行算术运算。算术运算是相对于“a”添加一个偏移量,以 26 为模,以便结果映射到与“a”不同的偏移量,这将产生一个新字符。将结果改回带有chr 的字符,并将这些字符重新连接在一起形成一个字符串。

这是一种可能的实现,它可以同时容纳大小写字母:

def shift_char(c, base, offset)
  (((c.ord - base) + offset) % 26 + base).chr
end

def cipher(s, offset)
  s.chars.map do |c|
    case c
    when 'a'..'z'
      shift_char(c, 'a'.ord, offset)
    when 'A'..'Z'
      shift_char(c, 'A'.ord, offset)
    else
      c
    end
  end.join
end

cipher_text = cipher('Now is the time for all good men...', 13)
p cipher_text       # "Abj vf gur gvzr sbe nyy tbbq zra..."
original_text = cipher(cipher_text, 13)
p original_text     # "Now is the time for all good men..."

【讨论】:

  • 这里的“c”和“base”指的是什么?
  • c 是单个字符,base 是字母 a-z 或 A-Z 范围的数字起点,即前者为'a'.ord,后者为'A'.ord .例如,字母“e”最初会被计算为从“a”偏移 4。您可以将偏移量设为任何您喜欢的值,但我使用了相对常见的值 13。因此,将 13 的偏移量添加到“e”现在将使其远离“a”17,这会将其转换为“r”密码。模 26 将任何超过 'z' 的值包装回字母表的开头。
  • 感谢您的进一步解释。我设法得到了一个简短的单词转换,但是当我输入一个长句子时,我的命令提示符返回'm'?
  • 当我通过上面的代码运行您的测试字符串"pb uhdo qdph lv grqdog gxfn" 时,它会生成"my real name is donald duck"。我完全不清楚您试图与您的代码填充评论交流什么,这对我来说正常工作。
  • 哦,我只是想找出一种方法将我的代码插入此处的块中。当我使用该代码时,我没有得到那个......但你做到了......?所以我试图弄清楚我做错了什么......
【解决方案2】:

首先你应该使用模运算符来保持在letters 范围内。 其次,您试图以错误的方式使用条件运算符 - 请阅读 ternary operator。 将letters 数组中的字符更改为数字并将其移出函数也将是一种改进。另一个问题是String 在Ruby 中没有map 方法。你必须使用chars 方法,它会在你的字符串中返回一个字符数组。

solve_cipher 函数的修改版本:

LETTERS = ('a'.ord..'z'.ord)

def solve_cipher(string, n)
  string.chars.map {|x| LETTERS.include?(x.ord)?((x.ord - LETTERS.min + n) % 26 + LETTERS.min).chr  : x}.join
end

如您所见,我将除以 26 后的余数 - LETTERS 数组的长度 - 保持在小写字母的范围内。 .

【讨论】:

  • 那行不通。根据定义 cipher('z', 1) 必须等于 'a'。而且,很明显,cipher('a', -1) 必须等于 'z'。
  • 它有效。你可以自己试试。 solve_cipher('a', -1) 返回 'z' 和 solve_cipher('z', 1) 返回 'a'。
【解决方案3】:

您可能正在寻找这样的东西:

def solve_cipher(string, n)
  string.split('').map do |x|
    new_index = x.ord + n
    while new_index > 'z'.ord
      new_index = 'a'.ord + new_index - 'z'.ord - 1
    end
    if new_index < 'a'.ord
      new_index = 'z'.ord - ('a'.ord - new_index) + 1
    end
    new_index.chr
  end.join
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 2020-05-31
    • 2014-02-06
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 2013-03-13
    相关资源
    最近更新 更多