Lazy Fibonacci Sequence in Ruby

梦想与她 提交于 2020-01-06 12:49:11

问题


Coming from Python if I wanted to create an iterative lazy Fibonacci sequence, I could do something like this:

def fib():
    a = 1
    b = 2
    yield a
    yield b
    while True:
        yield a + b
        tmp = a
        a = b
        b = tmp + b

Grabbing next(fib) will give me the next element in the sequence by simply adding the previous two elements, so if I want to get the first 1000 Fibonacci elements, I can do that quickly:

fib = fib()
for i in range(0,1000):
    print(next(fib))  

If I try to reproduce that in Ruby with an Enumerator, it quickly chokes, recalculating the entire sequence each time we call 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  

I found another SO post on how to fix a recursive fibonacci with memoization in Ruby, but I am curious, are lazy sequences and generators a thing in Ruby?


回答1:


Don't use recursive enumerators but do it like in Python? With a loop?

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  

What you did there in Ruby looks in Python like this:

def fib():
    yield from (1, 2)
    for a, b in zip(fib(), islice(fib(), 1, None)):
        yield a + b

That's slow as well.

Btw, worse than the exponential time is the exponential amount of memory. That recursive Python version crashes for me when trying to compute the 32nd Fibonacci number. At that point I already have almost 4 million generators running. And your Ruby version crashes for me when trying to compute the 20th Fibonacci number, with error can't create fiber (FiberError). At that point I have almost 12000 fibers running.



来源:https://stackoverflow.com/questions/48492051/lazy-fibonacci-sequence-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!