我的任务是提出一种编码字符串的方法。除其他外,我需要将每个字母移动一个给定的数字,但转换后的字母必须是一个字母(循环移位)。
到目前为止,我已经获得了以下代码:
def play_pass(str, n)
letters = ('a'..'z').to_a
str.chars.map {|x| letters.include?(x.downcase) ? (x.ord + n).chr : x}.join
end
这适用于大多数字母
我的问题是,如果我尝试将y
转移2位,我应该a
,但我得到的字符为[
我哪里错了?
答案 0 :(得分:3)
你的错误在于你只是盲目地移动角色而不是使用你的letters
数组来包裹。
def play_pass(str, n)
letters = ('a'..'z').to_a
str.chars.map do |x|
if letters.include?(x.downcase)
idx = letters.index(x)
new_idx = (idx + n) % letters.length
letters[new_idx]
else
x
end
end.join
end
play_pass('ay1', 2) # => "ca1"
这里成功的关键是modulo operator (%)。我们用来从letters
数组中获取替换字符的索引。它保证索引始终在数组的范围内。它没有超越结束,而是包裹着。
阅读它。它在许多地方都很有用。
答案 1 :(得分:3)
试试这个:
def play_pass(str, n)
letters = ('a'..'z').to_a
str.chars.map {|x| letters.include?(x.downcase) ?
letters[letters.find_index(x.down_case) + n - letters.size] : x}.join
end
p play_pass("abcdefghijklmnopqrstuvwxyz", 2)
<强>输出强>
"cdefghijklmnopqrstuvwxyzab"
[Finished in 0.3s]
工作原理
letters
是一个字符a
到z
的数组,就像OP在代码中的方式一样。
我们迭代str
中的所有字符,并在letters
数组中找到它的索引。然后我们将n
添加到该索引以获取移位的字符。为了避免从数组中删除,我们减去letters.size
(在本例中为26
),以便我们使用letters
和{{1}之间的值完成对0
的查找}}。
例如:在OP指出的场景中,如果要移动的角色是25
,那么在y
中为其索引添加2会给我们移位索引letters
(26
是24
数组中y
的索引,letters
是我们在测试用例中移位的数字字符) - 使2
表现得像圆形数组,并且没有遇到索引超出绑定类型的异常,我们从letters
移位索引中减去letters.size
。因此,我们得到索引26
,它代表我们感兴趣的char 0
。
另一个例子是a
的情况 - 这里移位的索引将是a
。当我们从中减去0 + 2 = 2
时,我们得到letters.size
。 Ruby允许负数索引,其中数组元素的查找是从反向完成的,它将解析为纠正元素。索引-24
与索引-1
相同,同样,(size-1)
的索引值等于索引-size
。
答案 2 :(得分:3)
数组采用rotate
方法:
def play_pass(str,n)
abc = ("a".."z").to_a.join
abc_rot = abc.chars.rotate(n).join
str.tr(abc, abc_rot)
end
p play_pass("abcdefghijklmnopqrstuvwxyz", 2)
# => "cdefghijklmnopqrstuvwxyzab"
否定n
以另一种方式旋转。
答案 3 :(得分:2)
如果您的代码出错,那么当移位的字母的字符代码比原始代码更小时,您的代码总是会添加一个正值来进行移位。您首先需要检测您何时处于这种情况(例如,如果移位的字母大于z
),然后进行适当的修复(提示:考虑您想要的字符代码与你现在要来了。)