次の関数を実装しようとしていますが、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
この投稿もチェック Fibonacci One-Liner
その他.. https://web.archive.org/web/20120427224512/http://en.literateprograms.org/Fibonacci_numbers_(Ruby)
これで、多くのソリューションが攻撃されました:)
urソリューションの問題について
0
または1
の場合、n
を返す必要があります
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)
これはフィボナッチの計算方法ではなく、比較的小さな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) }
線形
_module Fib
def self.compute(index)
first, second = 0, 1
index.times do
first, second = second, first + second
end
first
end
end
_
再帰的キャッシングあり
_module Fib
@@mem = {}
def self.compute(index)
return index if index <= 1
@@mem[index] ||= compute(index-1) + compute(index-2)
end
end
_
閉鎖
_module Fib
def self.compute(index)
f = fibonacci
index.times { f.call }
f.call
end
def self.fibonacci
first, second = 1, 0
Proc.new {
first, second = second, first + second
first
}
end
end
_
Fib.compute(256)
を呼び出しても、これらのソリューションはシステムをクラッシュさせません。
fib = Hash.new {|hash, key| hash[key] = key < 2 ? key : hash[key-1] + hash[key-2] }
fib[123] # => 22698374052006863956975682
このハッシュの初期化がどのように機能するのか疑問に思われる場合は、こちらをお読みください:
PHI = 1.6180339887498959
TAU = 0.5004471413430931
def fibonacci(n)
(PHI**n + TAU).to_i
end
再帰は必要ありません。
再帰は非常に遅いですが、これはより速い方法です
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 fib_upto(max)
i1, i2 = 1, 1
while i1 <= max
yield i1
i1, i2 = i2, i1+i2
end
end
fib_upto(5) {|f| print f, " "}
このワンライナーをお試しください
def fib (n)
n == 0 || n == 1 ? n : fib(n-2) + fib(n-1)
end
print fib(16)
出力:987
これはかなり簡単だと思います:
def fibo(n) a=0 b=1 for i in 0..n c=a+b print "#{c} " a=b b=c end
end
以下のアルゴリズムを使用してリストfiboシリーズを実行できます
def fibo(n)
n <= 2 ? 1 : fibo(n-1) + fibo(n-2)
end
以下のようなシリーズを生成できます
p (1..10).map{|x| fibo(x)}
以下はこれの出力です
=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
最速かつ最小のインラインソリューション:
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
機能的な自撮りパターン:)
a = [1, 1]
while(a.length < max) do a << a.last(2).inject(:+) end
これにより、a
にシリーズが入力されます。 (max <2の場合を考慮する必要があります)
N番目の要素のみが必要な場合、 Hash.new を使用できます
fib = Hash.new {|hsh, i| hsh[i] = fib[i-2] + fib[i-1]}.update(0 => 0, 1 => 1)
fib[10]
# => 55
以下は、ルックアップテーブルを作成するより簡潔なソリューションです。
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}
メモ化を利用してフィボナッチ数を計算する別のアプローチ:
$FIB_ARRAY = [0,1]
def fib(n)
return n if $FIB_ARRAY.include? n
($FIB_ARRAY[n-1] ||= fib(n-1)) + ($FIB_ARRAY[n-2] ||= fib(n-2))
end
これにより、各フィボナッチ数が一度だけ計算され、fibメソッドの呼び出し回数が大幅に削減されます。
以下はScalaの1つです。
object Fib {
def fib(n: Int) {
var a = 1: Int
var b = 0: Int
var i = 0: Int
var f = 0: Int
while(i < n) {
println(s"f(${i+1}) -> $f")
f = a+b
a = b
b = f
i += 1
}
}
def main(args: Array[String]) {
fib(10)
}
}
Fibの最速関数アルゴリズムを記述したい場合、再帰的ではありません。これは、ソリューションを作成するための機能的な方法が遅い数回のうちの1つです。あなたが何かを使う場合、スタックは自己を繰り返すので
fibonacci( n - 1 ) + fibonacci( n - 2 )
最終的にn-1とn-2は同じ数を作成するため、計算で繰り返しが行われます。これへの最速の方法は、繰り返しです
def fib(num)
# first 5 in the sequence 0,1,1,2,3
fib1 = 1 #3
fib2 = 2 #4
i = 5 #start at 5 or 4 depending on wheather you want to include 0 as the first number
while i <= num
temp = fib2
fib2 = fib2 + fib1
fib1 = temp
i += 1
end
p fib2
end
fib(500)
これは、URIオンラインジャッジでプログラミングの課題を解決するために使用したスニペットです。
def fib(n)
if n == 1
puts 0
else
fib = [0,1]
(n-2).times do
fib << fib[-1] + fib[-2]
end
puts fib.join(' ')
end
end
fib(45)
出力する
# => 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169 63245986 102334155 165580141 267914296 433494437 701408733
久しぶりですが、かなりエレガントでシンプルな1行の関数を記述できます。
def fib(n)
n > 1 ? fib(n-1) + fib(n-2) : n
end
今日誰かが私に似たようなことを尋ねましたが、彼は与えられた数のフィボナッチ数列を持つ配列を得たいと思っていました。例えば、
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
さらに別の;)
def fib(n)
f = Math.sqrt(5)
((((1+f)/2)**n - ((1-f)/2)**n)/f).to_i
end
キャッシュも追加すると便利です
def fibonacci
@fibonacci ||= Hash.new {|h,k| h[k] = fib k }
end
だから私たちはそれを得ることができるでしょう
fibonacci[3] #=> 2
fibonacci[10] #=> 55
fibonacci[40] #=> 102334155
fibonacci #=> {3=>2, 10=>55, 40=>102334155}
1)例、最大要素<100
def fibonachi_to(max_value)
fib = [0, 1]
loop do
value = fib[-1] + fib[-2]
break if value >= max_value
fib << value
end
fib
end
puts fibonachi_to(100)
出力:
0
1
1
2
3
5
8
13
21
34
55
89
2)例、10要素
def fibonachi_of(numbers)
fib = [0, 1]
(2..numbers-1).each { fib << fib[-1] + fib[-2] }
fib
end
puts fibonachi_of(10)
出力:
0
1
1
2
3
5
8
13
21
34
私は これが最良の答えです だと思います。これは、別のSO投稿からの同様の質問をした投稿からの応答でした。
ここでPriteshJ
から受け入れられた答えは、単純なフィボナッチ再帰を使用していますが、これは問題ありませんが、40番目の要素を超えると非常に遅くなります。以前の値をキャッシュ/メモして、再帰的に反復しながら渡すと、はるかに高速になります。
フィボナッチ列車に参加する:
レギュラー:
def fib(num)
return num if (num < 2) else fib(num-1) + fib(num-2)
end
キャッシングあり:
module Fib
@fibs = [0,1]
def self.calc(num)
return num if (num < 2) else @fibs[num] ||= self.calc(num-1) + self.calc(num-2)
end
end