您可能知道,.times
循环调用块指定的次数,向每次迭代传递一个递增的值。
如果我们说26.times {|i| puts i}
它将打印从 0 到 25 的值。最多,但不包括最后一个值。
现在让我们来看看循环。在第一次迭代时,i
是 0。所以我们打印字符串的第 14 个字符"N"
(在索引 13,从零开始)。我们不进入条件,因为 0 不大于 13。在第二次迭代中,我们打印第 15 个字符,"O"
。并继续这样做,直到我们到达i=14
.
至此,“魔法”开始了。首先,我们尝试打印字符串的第 27 个字符。没有这样的字符,所以我们实际上什么也没有打印。然后条件被触发,我们进入。
i % 14
等于 0,所以我们打印第零个字符"A"
. 下一次迭代,我们在索引 1 ( ) 处打印字符,15 % 14
依此类推,直到.times
完成迭代并停止调用该块。现在,要使这个逻辑起作用, for 的最后一个值i
必须是 26,这样我们就可以得到 12i % 14
和 print "M"
。
整个字符串的长度是 26。记住,.times
最多计数但不包括数字?这就是为什么我们将长度加一,使其从 0 计数到 26。这就是奥秘。
改进此代码的方法有很多,您将及时了解它们。:)
更新
我知道代码看起来有些奇怪。当然,还有一个错误。什么时候是 13 ,i
我们第一次不打印,也不进入条件。我们浪费了一次迭代。这是“off by 1”类错误的经典示例。这是不浪费迭代且不包含任何秘密的代码的固定版本:
a.length.times do |i|
print a[i + 13]
if i > 12
print a[i % 13]
end
end