Ruby 如何在凯撒密码中仅影响字母而不影响标点符号

Ruby 如何在凯撒密码中仅影响字母而不影响标点符号,ruby,caesar-cipher,Ruby,Caesar Cipher,我正试图用Ruby编写一个Caesar密码,但在尝试将字母改为数值而不是标点符号时遇到了一个障碍 以下是我目前的脚本: 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

我正试图用Ruby编写一个Caesar密码,但在尝试将字母改为数值而不是标点符号时遇到了一个障碍

以下是我目前的脚本:

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)
我尝试使用
选择
,但我不知道如何仅选择标点符号或字母。

仅用于匹配要替换的字符。在本例中,它是字母表中的字母,因此您将使用正则表达式
/[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?"
编辑:
%
是最重要的。在这里,如果大于25,则用于将
新建\u pos
“环绕”到字母表的开头

例如,假设
字母
“Y”
为5。字母表中“Y”的位置为24(假设“A”为0),因此
orig_pos+key
将为29,超过字母表的末尾

一种解决办法是:

new_pos = orig_pos + key

if new_pos > 25
  new_pos = new_pos - 26
end
这将使对应于字母“D”的新位置成为正确的结果。但是,我们可以更有效地获得相同的结果,方法是将“29 26”——用Ruby(和许多其他语言)表示为
29%26
——返回操作29÷26的剩余部分。(因为字母表中有26个字母)<代码>29%26为3,结果与上面相同


除了像我们在这里所做的那样将一个数限制在某个范围之外,模算子还经常用于测试一个数是否可以被另一个数整除。例如,您可以通过测试
n%3==0

来检查
n
是否可被3整除,谢谢!gsub肯定在努力省去标点符号!你的解决方案中有几点我不明白,你介意解释一下吗?在%26之前我都能理解,这有什么用?另外,当我运行脚本时,我会得到一个数组,而不是显示“IFZ,XIBU'T VQ?”的字符串。我编辑了我的答案,以解释模(
%
)运算符
gsub
总是返回一个字符串,所以我不确定为什么会得到一个数组。