Ruby 中的惰性斐波那契数列
Lazy Fibonacci Sequence in Ruby
来自 Python 如果我想创建一个迭代的惰性斐波那契数列,我可以这样做:
def fib():
a = 1
b = 2
yield a
yield b
while True:
yield a + b
tmp = a
a = b
b = tmp + b
抓取 next(fib)
将通过简单地添加前两个元素得到序列中的下一个元素,所以如果我想获得前 1000 个斐波那契元素,我可以很快做到:
fib = fib()
for i in range(0,1000):
print(next(fib))
If I try to reproduce that in Ruby with an Enumerator,它很快就卡住了,每次我们调用 fib.next() 时都会重新计算整个序列:
def fib()
Enumerator.new do |yielder|
yielder << 1 << 2
fib.lazy.zip(fib.lazy.drop(1)).each do |a,b|
yielder << a + b
end
end
end
我在 Ruby 中发现了另一个关于如何通过记忆修复递归斐波那契的 SO post,但我很好奇,惰性序列和生成器在 Ruby 中是一回事吗?
不要使用递归枚举器,而是像 Python 那样使用?有循环吗?
def fib()
Enumerator.new do |yielder|
a, b = 1, 2
yielder << a << b
loop do
a, b = b, a + b
yielder << b
end
end
end
你在 Ruby 中所做的在 Python 中看起来像这样:
def fib():
yield from (1, 2)
for a, b in zip(fib(), islice(fib(), 1, None)):
yield a + b
这也很慢。
顺便说一句,比指数时间更糟糕的是内存的指数数量。当我试图计算第 32 个斐波那契数时,递归 Python 版本 崩溃 。那时我已经有将近 400 万台发电机 运行。当我试图计算第 20 个斐波那契数时,你的 Ruby 版本崩溃了,错误 can't create fiber (FiberError)
。那时我有将近 12000 根纤维 运行.
来自 Python 如果我想创建一个迭代的惰性斐波那契数列,我可以这样做:
def fib():
a = 1
b = 2
yield a
yield b
while True:
yield a + b
tmp = a
a = b
b = tmp + b
抓取 next(fib)
将通过简单地添加前两个元素得到序列中的下一个元素,所以如果我想获得前 1000 个斐波那契元素,我可以很快做到:
fib = fib()
for i in range(0,1000):
print(next(fib))
If I try to reproduce that in Ruby with an Enumerator,它很快就卡住了,每次我们调用 fib.next() 时都会重新计算整个序列:
def fib()
Enumerator.new do |yielder|
yielder << 1 << 2
fib.lazy.zip(fib.lazy.drop(1)).each do |a,b|
yielder << a + b
end
end
end
我在 Ruby 中发现了另一个关于如何通过记忆修复递归斐波那契的 SO post,但我很好奇,惰性序列和生成器在 Ruby 中是一回事吗?
不要使用递归枚举器,而是像 Python 那样使用?有循环吗?
def fib()
Enumerator.new do |yielder|
a, b = 1, 2
yielder << a << b
loop do
a, b = b, a + b
yielder << b
end
end
end
你在 Ruby 中所做的在 Python 中看起来像这样:
def fib():
yield from (1, 2)
for a, b in zip(fib(), islice(fib(), 1, None)):
yield a + b
这也很慢。
顺便说一句,比指数时间更糟糕的是内存的指数数量。当我试图计算第 32 个斐波那契数时,递归 Python 版本 崩溃 。那时我已经有将近 400 万台发电机 运行。当我试图计算第 20 个斐波那契数时,你的 Ruby 版本崩溃了,错误 can't create fiber (FiberError)
。那时我有将近 12000 根纤维 运行.