如何只影响字母,而不是Caesar Cipher代码中的标点符号

时间:2015-12-14 16:54:54

标签: ruby caesar-cipher

我正在尝试用Ruby写一个Caesar Cipher,当我试图只将字母改为数值而不是标点符号时,我遇到了麻烦。

到目前为止,这是我的脚本:

def caesar_cipher(phrase, key)
    array = phrase.split("")        
    number = array.map {|n| n.upcase.ord - (64-key)}
    puts number
end

puts "Script running"
caesar_cipher("Hey what's up", 1)

我尝试使用select,但我无法弄清楚如何只选择标点符号或仅选择字母。

1 个答案:

答案 0 :(得分:3)

使用String#gsub仅匹配要替换的字符。在这种情况下,它是字母表中的字母,因此您将使用正则表达式/[a-z]/i

您可以将一个块传递给gsub,它将为字符串中的每个匹配调用,并且该块的返回值将用作替换。例如:

"Hello, world!".gsub(/[a-z]/i) {|chr| (chr.ord + 1).chr }
# => Ifmmp, xpsme!"

以下是您的Caesar密码方法的一个版本,该方法非常有效:

BASE_ORD = 'A'.ord

def caesar_cipher(phrase, key)
  phrase.gsub(/[a-z]/i) do |letter|
    orig_pos = letter.upcase.ord - BASE_ORD
    new_pos = (orig_pos + key) % 26
    (new_pos + BASE_ORD).chr
  end
end

caesar_cipher("Hey, what's up?", 1) # => "IFZ, XIBU'T VQ?"

编辑:

%modulo operator。这里它用于使new_pos“环绕”到字母表的开头,如果它大于25。

例如,假设letter"Y"key为5.字母表中“Y”的位置为24(假设“A”为0),因此{{ 1}}将是29,超过字母表的结尾。

一个解决方案就是:

orig_pos + key

这将使new_pos = orig_pos + key if new_pos > 25 new_pos = new_pos - 26 end 3对应于字母“D”,这是正确的结果。然而,我们可以更有效地获得相同的结果,将“29 modulo 26” - 在Ruby(和许多其他语言)中表示为new_pos - 它返回操作的剩余部分29÷26。 (因为字母表中有26个字母)。 29 % 26为3,结果与上述相同。

除了将数字约束到某个范围之外,正如我们在这里所做的那样,模运算符也经常用于测试数字是否可以被另一个数字整除。例如,您可以通过测试29 % 26来检查n是否可以被3整除。