我试图用
ruby以功能方式解决
Project Euler #58.
简而言之,我创建了一个枚举器来返回每个环的角数.然后,我在枚举器上链接功能操作符.当我得到我的结果时,我发现它有不同的类,这取决于我如何使用它.
spiral = Enumerator.new do |yielder|
n = 3
step = 2
loop do
vals = n.step(nil, step).take(4)
yielder.yield vals
step += 2
n = vals.last + step
end
end
primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113]
levels = spiral
.lazy
.map { |ring| ring.count { |n| primes.include? n } }
.with_object({:total=>1.0, :primes=>0})
.take_while do |ring_primes, counts|
counts[:total] += 4
counts[:primes] += ring_primes
(counts[:primes] / counts[:total]) > 0.5
end
级别是一个懒惰的枚举器.我希望它包含每个环中的素数[3,2,3等] – 参见项目欧拉参考.
如果我只是从枚举器打印,我得到我期望的:
levels.each do |level|
puts "#{level}"
end
返回:
3
2
3
1
但是如果我循环.with_index我得到一个数组结果,其中期望值是第一个成员,第二个是我的.with_object参数
levels.each.with_index do |level, ix|
puts "#{ix}: #{level}"
end
返回:
0: [3, {:total=>5.0, :primes=>3}]
1: [2, {:total=>9.0, :primes=>5}]
2: [3, {:total=>13.0, :primes=>8}]
3: [1, {:total=>17.0, :primes=>9}]
为什么懒惰的枚举器以这种方式工作,我将来如何预测呢?
更新
我询问了IRCruby频道,没有人对它有任何想法.他们说他们在一两天前讨论过这个问题并没有得出任何结论.
一般来说,似乎必须处理它并继续前进.
最佳答案 这里发生的是你方便地忽略了返回的结构并拔出了要显示的第一个项目.在这种情况下,第一项是您生成的计数结构.
看看这个:
levels.each do |*level|
puts level.inspect
end
这会向您显示级别结果中的实际内容.当Ruby调用lambda时,它将丢弃任何不符合块接受的参数数量的附加数据.
如果您不需要该元数据,请将其删除:
levels = spiral
.lazy
.map { |ring| ring.count { |n| primes.include? n } }
.with_object({:total=>1.0, :primes=>0})
.take_while do |ring_primes, counts|
counts[:total] += 4
counts[:primes] += ring_primes
(counts[:primes] / counts[:total]) > 0.5
end
.map { |r,_| r }
这消除了结果中的无关元素.
这是一种清理你的枚举器的方法:
class Spiral
include Enumerable
def each
Enumerator.new do |yielder|
n = 3
step = 2
loop do
vals = n.step(nil, step).take(4)
yielder.yield vals
step += 2
n = vals.last + step
end
end
end
end
然后你可以创建一个:
Spiral.new.each ...