从一个字符串中,我试图用另一个字符替换每个字符,字母表前面有13个字母。例如," ABC"将返回" NOP"。
然而,当我到达字母表的末尾时,我找不到循环索引的方法,因此它会再次从索引[-1]转到[0]。例如 - 当我输入" XYZ"它返回"",但它应该返回" KLM"
有人能想到解决方案吗?
谢谢!
def rot13(string)
alphabet = ("a".."z").to_a
big_alphabet = ("A".."Z").to_a
result = []
split_string = string.chars
alphabet.each_with_index do |item,index|
if string.include?(alphabet[index])
result << alphabet[index+13]
elsif string.include?(big_alphabet[index])
result << big_alphabet[index+13]
end
end
return result.join
end
答案 0 :(得分:2)
我不了解您的整个代码,但如果这对于字母表的开头有用,那么您应该将所有index + 13
更改为(index + 13) % 26
,它应该可以正常工作。
答案 1 :(得分:2)
这是最简单的方法(利用很少使用的String#tr
)。优雅地处理非字母。
def rot13(str)
alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
replacements = 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
str.tr(alphabet, replacements)
end
rot13('abc') # => "nop"
rot13('nOp 123') # => "aBc 123"
答案 2 :(得分:2)
基于您的“来源”字母:
alphabet = ('a'..'z').to_a
#=> ["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"]
您可以使用Array#rotate
创建“目标”字母:
alphabet13 = alphabet.rotate(13)
#=> ["n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
# "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m"]
通过zip
构建替换哈希 - 两个数组:
replacement = alphabet.zip(alphabet13).to_h
#=> {"a"=>"n", "b"=>"o", "c"=>"p", "d"=>"q", "e"=>"r", "f"=>"s", "g"=>"t",
# "h"=>"u", "i"=>"v", "j"=>"w", "k"=>"x", "l"=>"y", "m"=>"z",
# "n"=>"a", "o"=>"b", "p"=>"c", "q"=>"d", "r"=>"e", "s"=>"f", "t"=>"g",
# "u"=>"h", "v"=>"i", "w"=>"j", "x"=>"k", "y"=>"l", "z"=>"m"}
并使用gsub
执行替换:
'abc xyz'.gsub(/[a-z]/, replacement)
#=> "nop klm"
您也可以使用Regexp.union(replacement.keys)
代替硬编码/[a-z]/
。
替换大写字符可以在单独的步骤中完成,也可以将它们合并到替换哈希中。我把它留给你。
答案 3 :(得分:1)
您可以先构建哈希,将a
映射到n
,将n
映射到a
,将A
映射到N
,{{1转到N
等等。
然后,您只需使用此哈希重新映射您的字母。
A
如果没有该字母的映射(例如空格,标点符号,数字),您只需使用原始字母。
def remap input
a1 = ("a".."m").to_a
a2 = ("n".."z").to_a
a3 = ("A".."M").to_a
a4 = ("N".."Z").to_a
letter_map = (a1 + a2 + a3 + a4).zip(a2 + a1 + a4 + a3).to_h
input.split('').map {|x| letter_map[x] || x}.join
end
答案 4 :(得分:0)
你可以这样做
def rot13(string)
string.each_codepoint.map { |c|
new_c = c + 13 # Increment in alphabets
if ((c.between?('a'.ord, 'z'.ord) && new_c > 'z'.ord) || (c.between?('A'.ord, 'Z'.ord) && new_c > 'Z'.ord))
new_c -= 26 # This would keep the character within desired range
end
new_c.chr
}.join('')
end
答案 5 :(得分:0)
def rot13(str)
str.map{|x| x.tr('a-zA-Z', 'n-za-mN-ZA-M')}
end