我的任务是为我正在进行的项目创建一个凯撒密码。凯撒密码将每个字母放在一串文本中,并将其替换为远离它的固定数量的字母(由密钥指示)。例如,如果我的文字是" 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 >, ?, @
答案 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"
备注:强>
("a".."z").to_a.rotate(num)
。有关该工作示例,请参阅先前的编辑。tr()
中的范围来创建一个非常简单的凯撒密码:str.tr('A-Za-z','B-ZAb-za')
\
是一个转义字符,因此您可以使用-
之类的文字。有关详细信息,请参阅this SO answer。我认为以上内容会出现错误,因为它包含一个\
,应由另一个\
转义。