我正在尝试用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
,但我无法弄清楚如何只选择标点符号或仅选择字母。
答案 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整除。