我一直在做a kata on CodeWars,其摘要是取一个数字,如果数字彼此之间在1之内,则返回"Jumping!!"
(例如2345
,4323
,7898
)和其他"Not!!"
。所有单个数字(例如5
,7
,9
)都是跳数。
这是最佳解决方案之一:
def jumping_number(n)
n.to_s.chars.map(&:to_i).each_cons(2).all? { |x, y| (x - y).abs == 1 } ? "Jumping!!" : "Not!!"
end
这是我自己的代码:
def jumping_number(n)
n.to_s.chars.map(&:to_i).each_cons(2) { |x, y| return "Not!!" if (x - y).abs != 1 }
return "Jumping!!"
end
我不明白each_con
[原文如此]的工作方式。当true
是个数字时,这些方法的条件如何(正确)返回n
?连续的是nil
或0
,当在计算中使用时,它们不应返回true
,但确实会返回。
答案 0 :(得分:5)
这是您的误会:
连续数为nil或0,在计算中使用时不应返回true(但确实是!)
它既不是nil
也不是0
。它根本不存在。枚举器为空。
很遗憾,the documentation of Enumerable#each_cons
中没有记录。解决难题的方法是,如果您要求的缺点的大小小于可枚举的大小,则不会有缺点:
[5, 6, 7].each_cons(2).to_a
#=> [[5, 6], [6, 7]]
[5, 6, 7].each_cons(3).to_a
#=> [5, 6, 7]
[5, 6, 7].each_cons(4).to_a
#=> []
换句话说:永远不会执行该块,因此,永远不会有错误。
答案 1 :(得分:1)
Jörg回答了您的问题,但这是进行测试的另一种方法。
def jumping_number(n)
enum = n.digits.to_enum
loop { return "Not!!" unless (enum.next - enum.peek).abs == 1 }
"Jumping!!"
end
jumping_number 5 #=> "Jumping!!"
jumping_number 12321 #=> "Jumping!!"
jumping_number 1243 #=> "Not!!"
请注意,我使用Integer#digits而非Integer#to_s来分割数字:
123.digits #=> [3, 2, 1]
123.to_s.chars.map(&:to_i) #=> [1, 2, 3]
产生的数组元素的顺序不同,但这与这个问题无关。
Enumerator#peek在Enumerator#next导致生成枚举器的最后一个元素之后执行时引发StopInteration
异常。 Kernel#loop然后通过打破循环来处理异常。
答案 2 :(得分:0)
另一种可能的解决方案是使用Enumerable#chunk_while
然后测量返回数组的大小。
运作方式:
[1,2,3].chunk_while{ |x, y| (x-y).abs == 1 }.to_a #=> [[1, 2, 3]]
[1].chunk_while{ |x, y| (x-y).abs == 1 }.to_a #=> [[1]]
[1,2,4].chunk_while{ |x, y| (x-y).abs == 1 }.to_a #=> [[1, 2], [4]]
因此,在一种方法中使用它:
def jumping_number(n)
n.digits.chunk_while{ |x, y| (x-y).abs == 1 }.to_a.size == 1 ? "Jumping!!" : "Not!!"
end
(感谢@Cary Swoveland记住Integer#digits
确实存在。)