我正在编写一种加密方法。我正在处理RewriteRule ^/wiki/Main_Page$ /wiki/Welcome_to_Our_Site [R]
的代码。我写的代码如下:
caesar_cipher
当我传递一个由多个单词组成的字符串时,我收到此错误:
def caesar(string, shift = 0)
alphabet = ("a".."z").to_a
letters = string.split("")
blank = []
letters.map do |letter|
blank << alphabet[(alphabet.index(letter) + shift) % alphabet.length]
end
puts blank.join
end
我理解block in `caesar_cipher': undefined method `+' for nil:NilClass (NoMethodError)
可以解决我的问题,如果我要创建一个类。我有一个独立的方法,除句子外,在tr
的每个角度都有效。我无法将这些词分开,迭代,然后加入。任何输入都可以帮助我避免这种情况。
答案 0 :(得分:2)
在使用回复中的建议后,我能够将我的代码调整为以下内容,使其适用于句子而不只是一个单词:
def caesar(string, shift=0)
alphabet = ("a".."z").to_a
blank = string.each_char.map do |letter|
alphabet.include?(letter) ? alphabet[(alphabet.index(letter) + shift) % alphabet.length] : letter
end
puts blank.join
end
答案 1 :(得分:1)
错误是由于以下原因:
(alphabet.index(letter) + shift)
对于每个空格letter = " "
,多个单词的情况。现在你正在做alphabet.index(letter)
。由于数组alphabet
没有" "
元素,因此会返回nil
,之后您会添加并获得apt错误:
未定义的方法`+'代表nil:NilClass(NoMethodError)
了解错误来源后,解决方法取决于您的算法。
答案 2 :(得分:1)
不要分手/加入单词。只需跳过加密字母表中不包含的字符:
blank = letters.map do |letter|
if alphabet.include?(letter)
alphabet[(alphabet.index(letter) + shift) % alphabet.length]
else
letter
end
end
您会注意到上述代码没有blank << ...
。这适用于each
,但不适用于map
。 map
返回一个新数组,其中一个项目对应于原始数组中的每个项目,因此此代码只将结果数组分配给blank
(这意味着无需执行{{1}首先)。
P.S。而不是使用blank = []
,而是使用letters = string.split("")
或更好地完全摆脱letters = string.chars
并执行letters
。
答案 3 :(得分:1)
当您的问题已经确定时,让我建议另一种方法来进行加密,这将说明使用各种具有广泛应用的Ruby方法。我将假设要加密的字符串不包含大写字母,只有字母可以移位。
<强>代码强>
def caesar(str, shift = 0)
arr = [*'a'..'z']
mapping = arr.zip(arr.rotate(shift)).to_h
mapping.default_proc = proc { |h,k| h[k] = k }
str.gsub(/./, mapping)
end
示例强>
caesar "the die is cast.", 3
#=> "wkh glh lv fdvw."
<强>解释强>
首先,对于shift = 3
,
arr = [*'a'..'z']
#=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
# "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
mapping = arr.zip(arr.rotate(shift)).to_h
#=> {"a"=>"d", "b"=>"e", "c"=>"f", "d"=>"g", "e"=>"h", "f"=>"i", "g"=>"j",
# "h"=>"k", "i"=>"l", "j"=>"m", "k"=>"n", "l"=>"o", "m"=>"p", "n"=>"q",
# "o"=>"r", "p"=>"s", "q"=>"t", "r"=>"u", "s"=>"v", "t"=>"w", "u"=>"x",
# "v"=>"y", "w"=>"z", "x"=>"a", "y"=>"b", "z"=>"c"}
接下来,我们使用Hash#default_proc=:
为此哈希添加默认procmapping.default_proc = proc { |h,k| h[k] = k }
# => #<Proc:0x007f8ec8b132b8@(irb):1241>
如果mapping[k]
没有密钥k
,这会导致mapping
返回k
。 (没有更多。)例如,
mapping['a'] #=> 'd'
mapping['4'] #=> '4'
mapping['$'] #=> '$'
mapping[' '] #=> ' '
我认为未编码的信息是凯撒最喜欢的表达方式之一:
str = "the die is cast."
我们使用String#gsub的形式,使用哈希来获取替换值。我们希望考虑替换每个字符,我们需要匹配正则表达式/./
:
str.gsub(/./, mapping)
#=> "wkh glh lv fdvw."
如果我们没有将默认proc附加到哈希,我们就会得到
"wkhglhlvfdvw"
。