フィボナッチ数列

id:pyletさんのフィボナッチ数列(fib2)をRubyにて。
Pythonのrange(n)の意味は(0...n)でよいのかしらん。

def fib(n)
  a, b = 1, 1
  for i in (0...n)
    a, b = b, a + b
  end
  a
end

for i in (0...20)
  print fib(i), " "
end
#=> 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

Danさんの問題への解答は以下でよいのでしょうかね。

def fib(n)
  fib_iterator(n, 0, 1)
end

def fib_iterator(n, a, b)
  if n == 0
    b
  else
    fib_iterator(n - 1, b, a + b)
  end
end

(0...20).each do |n|
  print fib(n), " "
end
#=> 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

よくわからないけれど、ぐにゅぐにゅ。

def fib(n)
  ff = lambda {|f, n, a, b|
    if n == 0
      b
    else
      f.call(f, n - 1, b, a + b)
    end
  }
  ff.call(ff, n, 0, 1)
end

(0...20).each do |n|
  print fib(n), " "
end
#=> 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

代入がまずいって?二回繰り返しちゃえ。

def fib(n)
  lambda {|f, n, a, b|
    if n == 0
      b
    else
      f.call(f, n - 1, b, a + b)
    end
  }.call(
    lambda {|f, n, a, b|
      if n == 0
        b
      else
        f.call(f, n - 1, b, a + b)
      end
    }, n, 0, 1
  )
end

(0...20).each do |n|
  print fib(n), " "
end
#=> 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

二回繰り返す部分を高階関数にすればいいのね。

def ff(f, *args)
  f.call(f, *args)
end

def fib(n)
  ff(lambda {|f, n, a, b|
    if n == 0
      b
    else
      f.call(f, n - 1, b, a + b)
    end
  }, n, 0, 1)
end

(0...20).each do |n|
  print fib(n), " "
end
#=> 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

もう少しコンパクトなほうがわかりやすい。

def ff(f, n, a, b)
  f.call(f, n, a, b)
end

def fib(n)
  ff(lambda {|f, n, a, b| n == 0 ? b : f.call(f, n - 1, b, a + b)}, n, 0, 1)
end

(0...20).each do |n|
  print fib(n), " "
end
#=> 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765