用ruby方法保留字符和空格

时间:2016-03-02 15:44:09

标签: ruby

构建一个Rot方法来解决加密问题。我有一些工作,但取出空格和任何包含的字符。打算使用bytes代替chars,然后在我有字节代码后将其转回字符串,但我似乎无法使其正常工作。您将如何从这段代码中保留这些内容:

def rot(x, string, encrypt=true)
  alphabet = Array("A".."Z") + Array("a".."z")
  results = []

  if encrypt == true
    key = Hash[alphabet.zip(alphabet.rotate(x))]
    string.chars.each do |i|
      if ('a'..'z').include? i
        results << key.fetch(i).downcase
      elsif ('A'..'Z').include? i
        results << key.fetch(i).upcase
      end
    end
    return results.join
  else
    key_false = Hash[alphabet.zip(alphabet.rotate(26 - x))]
    string.chars.each do |i|
      if ('a'..'z').include? i
        results << key_false.fetch(i).downcase
      elsif ('A'..'Z').include? i
        results << key_false.fetch(i).upcase
      end
    end
    return results.join
  end
end

puts rot(10, "Hello, World")
=> RovvyGybvn
puts rot(10, "Rovvy, Gybvn", false)
=> HelloWorld

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

只需添加if阻止else这样的条件:

  if ('a'..'z').include? i
    # ...
  elsif ('A'..'Z').include? i
    # ...
  else
    results << i
  end

将所有非A-z字符添加到输出中。

答案 1 :(得分:0)

我注意到您的代码存在一些问题:

破坏的替换哈希

这是最大的问题 - 您的替换哈希被破坏了。我使用较小的字母表进行演示,但这也适用于26个字符:

uppercase = Array("A".."C")
lowercase = Array("a".."c")
alphabet = uppercase + lowercase
#=> ["A", "B", "C", "a", "b", "c"]

您可以通过以下方式构建替换哈希:

x = 1
key = Hash[alphabet.zip(alphabet.rotate(x))]
#=> {"A"=>"B", "B"=>"C", "C"=>"a", "a"=>"b", "b"=>"c", "c"=>"A"}

"C"=>"a""c"=>"A"指的是错误的字符大小写。这是因为您一次旋转整个字母表:

alphabet            #=> ["A", "B", "C", "a", "b", "c"]
alphabet.rotate(x)  #=> ["B", "C", "a", "b", "c", "A"]

相反。你必须分别旋转大写和小写字母

uppercase           #=> ["A", "B", "C"]
uppercase.rotate(x) #=> ["B", "C", "A"]

lowercase           #=> ["a", "b", "c"]
lowercase.rotate(x) #=> ["B", "C", "A"]

然后连接旋转的部分。之一:

key = Hash[uppercase.zip(uppercase.rotate(x)) + lowercase.zip(lowercase.rotate(x))]
#=> {"A"=>"B", "B"=>"C", "C"=>"A", "a"=>"b", "b"=>"c", "c"=>"a"}

或:

key = Hash[(uppercase + lowercase).zip(uppercase.rotate(x) + lowercase.rotate(x))]
#=> {"A"=>"B", "B"=>"C", "C"=>"A", "a"=>"b", "b"=>"c", "c"=>"a"}

替换字符

回到完整的字母:

uppercase = Array("A".."Z")
lowercase = Array("a".."z")
x = 10
key = Hash[uppercase.zip(uppercase.rotate(x)) + lowercase.zip(lowercase.rotate(x))]

有一个可用的替换哈希使得替换字符几乎是微不足道的:

string = "Hello, World!"
result = ""
string.each_char { |char| result << key.fetch(char, char) }
result
#=> "Rovvy, Gybvn!"

我已将result从数组更改为字符串。它还有<<方法,之后您不必join

Hash#fetch的工作方式几乎与Hash#[]类似,但如果在哈希中找不到密钥,则可以传递返回的默认值:

 key.fetch("H", "H") #=> "R" (replacement value)
 key.fetch("!", "!") #=> "!" (default value)

处理加密/解密

您正在复制大量代码来处理解密部分。但是有一种更简单的方法 - 只需改变方向:

rot(10, "Hello")        #=> "Rovvy"
rot(10, "Rovvy", false) #=> "Hello"
rot(-10, "Rovvy")       #=> "Hello"

所以在你的代码中,你可以写:

x = -x unless encrypt

全部放在一起

def rot(x, string, encrypt = true)
  uppercase = Array("A".."Z")
  lowercase = Array("a".."z")
  x = -x unless encrypt
  key = Hash[uppercase.zip(uppercase.rotate(x)) + lowercase.zip(lowercase.rotate(x))]
  result = ""
  string.each_char { |char| result << key.fetch(char, char) }
  result
end

rot(10, "Hello, World!")        #=> "Rovvy, Gybvn!"
rot(10, "Rovvy, Gybvn!", false) #=> "Hello, World!"