Ruby中的方法用字母+索引13中的字符替换字符串

时间:2016-04-06 10:29:40

标签: ruby string

从一个字符串中,我试图用另一个字符替换每个字符,字母表前面有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

6 个答案:

答案 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