Ruby 中的凯撒密码
Caesar's cipher in Ruby
我正在研究左移 1 的凯撒密码问题,但开始时遇到困难。提示让我查看 Ruby 文档中的 String 方法#ord 和 Integer 方法#chr。并且字母 'a' 必须转移到 'z'...
下面是我的作品..
def solve_cipher(string, n)
letters = ['a'..'z']
string.map {|x| letters.include?(x.ord + n).chr : x}.join
感谢任何建议...!
首先你应该使用模运算符来保持在 letters
范围内。
其次,您试图以错误的方式使用条件运算符 - 阅读 ternary operator。
将 letters
数组中的字符更改为数字并将其移出函数也是一种改进。另一个问题是String
在Ruby中没有方法map
。您必须使用 chars
方法,其中 returns 字符串中的字符数组。
您的 solve_cipher
函数的修改版本:
LETTERS = ('a'.ord..'z'.ord)
def solve_cipher(string, n)
string.chars.map {|x| LETTERS.include?(x.ord)?((x.ord - LETTERS.min + n) % 26 + LETTERS.min).chr : x}.join
end
如您所见,我将除以 26
后的余数 - LETTERS
数组的长度 - 保留在小写字母范围内。
.
您可能正在寻找这样的东西:
def solve_cipher(string, n)
string.split('').map do |x|
new_index = x.ord + n
while new_index > 'z'.ord
new_index = 'a'.ord + new_index - 'z'.ord - 1
end
if new_index < 'a'.ord
new_index = 'z'.ord - ('a'.ord - new_index) + 1
end
new_index.chr
end.join
end
您需要split
将您的单词转换为单个字符。然后你需要用 ord
将字符转换为整数,这样你就可以做算术了。算术运算是添加相对于 'a' 的偏移量,模 26,以便结果映射到与 'a' 不同的偏移量,这将产生一个新字符。使用 chr
将结果改回字符,并将字符重新组合在一起形成一个字符串。
这是一种可能的实现方式,它同时适用于大写和小写字母:
def shift_char(c, base, offset)
(((c.ord - base) + offset) % 26 + base).chr
end
def cipher(s, offset)
s.chars.map do |c|
case c
when 'a'..'z'
shift_char(c, 'a'.ord, offset)
when 'A'..'Z'
shift_char(c, 'A'.ord, offset)
else
c
end
end.join
end
cipher_text = cipher('Now is the time for all good men...', 13)
p cipher_text # "Abj vf gur gvzr sbe nyy tbbq zra..."
original_text = cipher(cipher_text, 13)
p original_text # "Now is the time for all good men..."
我正在研究左移 1 的凯撒密码问题,但开始时遇到困难。提示让我查看 Ruby 文档中的 String 方法#ord 和 Integer 方法#chr。并且字母 'a' 必须转移到 'z'...
下面是我的作品..
def solve_cipher(string, n)
letters = ['a'..'z']
string.map {|x| letters.include?(x.ord + n).chr : x}.join
感谢任何建议...!
首先你应该使用模运算符来保持在 letters
范围内。
其次,您试图以错误的方式使用条件运算符 - 阅读 ternary operator。
将 letters
数组中的字符更改为数字并将其移出函数也是一种改进。另一个问题是String
在Ruby中没有方法map
。您必须使用 chars
方法,其中 returns 字符串中的字符数组。
您的 solve_cipher
函数的修改版本:
LETTERS = ('a'.ord..'z'.ord)
def solve_cipher(string, n)
string.chars.map {|x| LETTERS.include?(x.ord)?((x.ord - LETTERS.min + n) % 26 + LETTERS.min).chr : x}.join
end
如您所见,我将除以 26
后的余数 - LETTERS
数组的长度 - 保留在小写字母范围内。
.
您可能正在寻找这样的东西:
def solve_cipher(string, n)
string.split('').map do |x|
new_index = x.ord + n
while new_index > 'z'.ord
new_index = 'a'.ord + new_index - 'z'.ord - 1
end
if new_index < 'a'.ord
new_index = 'z'.ord - ('a'.ord - new_index) + 1
end
new_index.chr
end.join
end
您需要split
将您的单词转换为单个字符。然后你需要用 ord
将字符转换为整数,这样你就可以做算术了。算术运算是添加相对于 'a' 的偏移量,模 26,以便结果映射到与 'a' 不同的偏移量,这将产生一个新字符。使用 chr
将结果改回字符,并将字符重新组合在一起形成一个字符串。
这是一种可能的实现方式,它同时适用于大写和小写字母:
def shift_char(c, base, offset)
(((c.ord - base) + offset) % 26 + base).chr
end
def cipher(s, offset)
s.chars.map do |c|
case c
when 'a'..'z'
shift_char(c, 'a'.ord, offset)
when 'A'..'Z'
shift_char(c, 'A'.ord, offset)
else
c
end
end.join
end
cipher_text = cipher('Now is the time for all good men...', 13)
p cipher_text # "Abj vf gur gvzr sbe nyy tbbq zra..."
original_text = cipher(cipher_text, 13)
p original_text # "Now is the time for all good men..."