在Ruby中创建密码

时间:2017-09-20 20:48:26

标签: ruby-on-rails ruby

我的任务是为我正在进行的项目创建一个凯撒密码。凯撒密码将每个字母放在一串文本中,并将其替换为远离它的固定数量的字母(由密钥指示)。例如,如果我的文字是" cat"我的密钥是3,我的新词是" fdw" (我假设正数将字母向右移动)。我已经能够让我的代码正确解决大多数文本字符串,但我发现如果我的字符串包含> ?或@它不起作用。如果有帮助,他们的ASCii代码是62,63和64。任何意见都表示赞赏!

def caesar_cipher(str, num)
strArray = str.split('')

cipherArray = strArray.collect do |letter|
 letter = letter.ord

  if (65...90).include?(letter + num) || (97...122).include?(letter + num)
    letter = letter + num
  elsif (91...96).include?(letter + num) || (123...148).include?(letter + num)
    letter = (letter - 26) + num
  else
    letter
  end

end

 cipherArray = cipherArray.collect {|x| x.chr}
 cipher = cipherArray.join('')

end


caesar_cipher("Am I ill-prepared for this challenge?", 3)
#ord 62-64 DON'T work >, ?, @

2 个答案:

答案 0 :(得分:1)

你应该创建一个字母变量,只要考虑一下你是否使用两端,那么你将遇到两个问题:负数和不存在的ASCii数。您可以使用模块运算符%或单个减法来处理此问题。

alphabet = "abcde"

text_to_cipher= "aaee" => 0044 #number based in his position at aphabet var
key = 3

结果将是3377 => dd¡?或者任何其他符号,因为7超出字符串长度“abcde”,ASCii的结尾也是如此。 使用模块运算符,您可以限制它。

size_of_your_alphabet = 5 # For this case
7%size_of_your_alphabet = 2

答案 1 :(得分:1)

Ruby内置tr是实现替换密码的理想选择。

第1步:汇总您想要转换的字符。

chars = ["A".."Z", "a".."z", ">".."@"].flat_map(&:to_a)

第2步:创建转换后字符的1:1数组

transformed = chars.map{|c| (c.ord + 3).chr}

第3步:应用tr转换字符串。

str.tr(chars.join, transformed.join)

完整的工作示例:

def caesar_cipher(str, num)
  chars = ["A".."Z", "a".."z", ">".."@"].flat_map(&:to_a)
  transformed = chars.map{|c| (c.ord + num).chr}
  str.tr(chars.join, transformed.join)
end

输出:

> caesar_cipher("Am I ill-prepared for this challenge?", 3)
#=> "Dq L mpp-tvitevih jsv xlmw gleppirkiC"

备注:

  • 大多数替换密码实际上依赖于字母旋转,而不是ASCII值。我的初步假设是你想要一个轮换,例如("a".."z").to_a.rotate(num)。有关该工作示例,请参阅先前的编辑。
  • 您可以使用tr()中的范围来创建一个非常简单的凯撒密码:str.tr('A-Za-z','B-ZAb-za')
  • 编辑:此外,由于范围指定功能,\是一个转义字符,因此您可以使用-之类的文字。有关详细信息,请参阅this SO answer。我认为以上内容会出现错误,因为它包含一个\,应由另一个\转义。