【问题标题】:Lazy Fibonacci Sequence in RubyRuby 中的惰性斐波那契数列
【发布时间】:2018-07-07 14:31:08
【问题描述】:

如果我想创建一个迭代惰性斐波那契数列,我可以使用 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  

我找到了另一个 SO post,关于如何在 Ruby 中使用记忆来修复递归斐波那契,但我很好奇,惰性序列和生成器在 Ruby 中是一回事吗?

【问题讨论】:

  • Enumerator.new 的文档展示了如何为斐波那契数创建一个枚举器。

标签: ruby generator lazy-sequences


【解决方案1】:

不要使用递归枚举器,而是像在 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 根光纤在运行。

【讨论】:

  • 谢谢,这就是我不懂 Ruby 的结果!
  • 如果不明显,enum = fib #=&gt; #&lt;Enumerator: #&lt;Enumerator::Generator:0x000000011dd4f8&gt;:each&gt;; enum.next #=&gt; 1; enum.next #=&gt; 2; enum.next #=&gt; 3; enum.next #=&gt; 5; enum.next #=&gt; 8 等等。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
  • 2012-08-24
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 2015-06-05
相关资源
最近更新 更多