次の関数を実装しようとしていますが、stack level too deep (SystemStackError)
エラーが発生し続けます。
問題が何であるかについてのアイデアはありますか?
def fibonacci( n )
[ n ] if ( 0..1 ).include? n
( fibonacci( n - 1 ) + fibonacci( n - 2 ) ) if n > 1
end
puts fibonacci( 5 )
これを試して
def fibonacci( n )
return n if ( 0..1 ).include? n
( fibonacci( n - 1 ) + fibonacci( n - 2 ) )
end
puts fibonacci( 5 )
# => 5
この投稿もチェックしてくださいフィボナッチワンライナー
その他.. https://web.archive.org/web/20120427224512/http://en.literateprograms.org/Fibonacci_numbers_(Ruby)
あなたは今、多くの解決策で攻撃されています:)
あなたの解決策の問題について
またはn
_ 0
_1
add
最後と次ではない最後の2つの数字
新しい修正版
def fibonacci( n )
return n if n <= 1
fibonacci( n - 1 ) + fibonacci( n - 2 )
end
puts fibonacci( 10 )
# => 55
一発ギャグ
def fibonacci(n)
n <= 1 ? n : fibonacci( n - 1 ) + fibonacci( n - 2 )
end
puts fibonacci( 10 )
# => 55
これが私が思いついたものです。これはより簡単です。
def fib(n)
n.times.each_with_object([0,1]) { |num, obj| obj << obj[-2] + obj[-1] }
end
fib(10)
fib = Hash.new {|hash, key| hash[key] = key < 2 ? key : hash[key-1] + hash[key-2] }
fib[123] # => 22698374052006863956975682
このハッシュの初期化がどのように機能するか疑問に思っている場合は、以下をお読みください。
これはフィボナッチを計算する方法ではありません。比較的小さなn
s では失敗する巨大な再帰ツリーを作成しています。次のようなことをお勧めします。
def fib_r(a, b, n)
n == 0 ? a : fib_r(b, a + b, n - 1)
end
def fib(n)
fib_r(0, 1, n)
end
p (0..100).map{ |n| fib(n) }
再帰は非常に遅いです。これはより高速な方法です
a = []; a[0] = 1; a[1] = 1
i = 1
while i < 1000000
a[i+1] = (a[i] + a[i-1])%1000000007
i += 1
end
puts a[n]
これは O(1) ですが、行列累乗を使用できます。これは私の実装の 1 つですが、Java => http://pastebin.com/DgbekCJMにありますが、行列 exp. の O(8logn) です。高速倍加と呼ばれるアルゴリズム。高速倍増の Java 実装を次に示します。
class FD {
static int mod = 1000000007;
static long fastDoubling(int n) {
if(n <= 2) return 1;
int k = n/2;
long a = fastDoubling(k+1);
long b = fastDoubling(k);
if(n%2 == 1) return (a*a + b*b)%mod;
else return (b*(2*a - b))%mod;
}
しかし、カラツバ乗算を使用すると、両方の行列 exp. 高速倍増ははるかに高速になりますが、高速倍加は行列 exp を打ち負かします。一定の要因により、ここではあまり徹底的になりたくありませんでした。しかし、私は最近、フィボナッチ数について多くの研究を行っており、私の研究が学びたい人に役立つことを願っています;)。
これはかなり簡単だと思います:
def fibo(n) a=0 b=1 for i in 0..n c=a+b print "#{c} " a=b b=c end
end
PHI = 1.6180339887498959
TAU = 0.5004471413430931
def fibonacci(n)
(PHI**n + TAU).to_i
end
再帰は必要ありません。
ライン内で最速かつ最小のソリューション:
fiby = ->(n, prev, i, count, selfy) {
i < count ? (selfy.call n + prev, n, i + 1, count, selfy) : (puts n)
}
fiby.call 0, 1, 0, 1000, fiby
機能的な自撮りパターン:)
ルックアップ テーブルを作成するより簡潔なソリューションを次に示します。
fibonacci = Hash.new do |hash, key|
if key <= 1
hash[key] = key
else
hash[key] = hash[key - 1] + hash[key - 2]
end
end
fibonacci[10]
# => 55
fibonacci
# => {1=>1, 0=>0, 2=>1, 3=>2, 4=>3, 5=>5, 6=>8, 7=>13, 8=>21, 9=>34, 10=>55}
誰かが今日私に似たようなことを尋ねましたが、彼は特定の数値のフィボナッチ数列を含む配列を取得したいと考えていました。例えば、
fibo(5) => [0, 1, 1, 2, 3, 5]
fibo(8) => [0, 1, 1, 2, 3, 5, 8]
fibo(13) => [0, 1, 1, 2, 3, 5, 8, 13]
# And so on...
これが私の解決策です。再帰を使用していません。似たようなものを探しているなら、もう1つの解決策:P
def fibo(n)
seed = [0, 1]
n.zero? ? [0] : seed.each{|i| i + seed[-1] > n ? seed : seed.push(i + seed[-1])}
end
Ruby Fibreの簡単な紹介-
def fibs x, y
Fiber.new do
while true do
Fiber.yield x
x, y = y, x + y
end
end
end
fibs
上記では、非常に効率的な方法で計算された無限の数値ストリームを作成しています。単純puts
な無限ストリームではないため、ストリームから有限量のアイテムを収集する小さな関数を作成する必要がありますtake
。
def take t, n
r = []
while n > 0 do
n -= 1
r << t.resume
end
r
end
100
最後に、シーケンスの最初の数字を見0
てみましょう。1
puts (take (fibs 0, 1), 100)
0
1
1
2
3
5
8
13
21
34
55
.
.
.
31940434634990099905
51680708854858323072
83621143489848422977
135301852344706746049
218922995834555169026