フィボナッチ数列は、前の2項目を足したものを、付け加える数列です。再帰でも出来るはずですが、その前に単純な関数でやってみました。
一応再帰になってると思います。
ランキングに参加中。クリックして応援お願いします!
コメント利用規約に同意する
フォロー中フォローするフォローする
コードで
listlen(fib)
ってやってて、これで長さから・・・ってやってる事が多いんですが、Pythonだと実は次のように書けます。
def MakeFib(fib):
return fib[-2] + fib[-1]
リストのケツの方の要素は[-1]で指定出来て、逆順に-1、-2....と言うカタチで指定可能です。
そっちの方がPythonらしいですね。
isamさんの発想を活かすのなら、多分、
def MakeFib(fib):
return fib + [fib[-2] + fib[-1]]
fib = [1, 2]
for i in range(1, 10):
fib = MakeFib(fib)
print(fib)
の方がイイんじゃないかなぁ。
appendは関数型言語的発想で言うと、ちょっと危険で、元データを変更 -> 意図しないところで場合によっては変更されてバグの原因になる、って事があり得ます。
こういうのを「破壊的変更」と言って、C言語辺りだとスピードを重視して良くやりますが、最近の手だと、「なるたけ元データを直接加工しない」のが最善だ、と言われています。
実際は上のコードも破壊的変更してるんで良くないんですが(fib = MakeFib(fib))、いずれにせよ、リストに対するappendは避けられるなら避けた方が良いです。
関数型言語の読者はvalの方が普通の変数で、varは禁断の果実のように感じるかもしれない。
appendは元のデータを変えてしまうので、いけない、ということですか?
そういう事ですね。Pascal/C言語みたいな手続き型言語だとデータの破壊的変更は良くやる手ではあったんですが昨今のモダンな言語ではあまり推奨されていません。
正確な事を言うと、元々UNIXにおけるC言語なんかのプログラミングでも推奨されてなかったんです。
「プログラムはフィルタのようであるべきだ」
ってのはUNIX世界、つまりC言語でもそういう発想だったんです。データを与える、でもデータを直接改変する事なく結果を出す、って方法ですね。
ただ、過去は、現実がそれを許さなかった。平たく言うとメモリ量の問題なんですよ。
例えば配列Aがあって、それを使ったプログラムを書くとして。「フィルタのようなプログラム」とは配列Aとは別に配列Bを作って返す事を示唆してる。
当然メモリ量を圧迫するわけです。
これは黎明期のパソコン、例えば90年代辺りに入ってさえもクリティカルな方法論だったのです。配列Aがあるのに配列Bを「必ず」生成するのならコンピュータに搭載されているメモリを圧迫するのは確実です。なんせ当時のパソコンなんて今のUSBメモリが持ってる記憶量を大幅に下回ってましたからね。
だから「理想通りにプログラム出来なかった」のです。となるとオリジナルのデータを「変更」せざるを得なかった。そうすれば記憶容量が節約出来る。
昔のプログラミングテクニックと言うのはこの「記憶容量の節約」が主な主眼でした。
一方、現代のパソコンはかつてじゃ信じられないくらい大量のメモリが搭載されています。「富豪の時代」とはそういう意味ですよね。
つまり、かつては「バグ覚悟でメモリの節約をしなければならなかった」のが「潤沢なメモリを利用してかつて理想としたプログラムを書けるようになった」と言う事です。
ScalaもPythonもそういう背景が揃って登場してきた言語だ、って事です。
例えば
>>> lis = [1, 2, 3]
>>> lis + [4]
[1, 2, 3, 4]
>>> lis
[1, 2, 3]
と+なら元データlisは変更されませんが、
>>> lis.append(4)
>>> lis
[1, 2, 3, 4]
>>>
と、appendは元データを変更してしまいます。
基本的には「なるべくなら使わない方が良い」ですね。ただ、効率の問題で使わなきゃならない時もあるでしょうが、最初は「なるべくデータそのものを改変しない」ようにプログラムするべきだとは思います。
その方が現代的だと思います。
isam氏はフィボナッチを最終的にリストにしたくてappendとかしてますが、そうじゃなくって、直接フィボナッチ数列のリストを返す事も可能ですよ。
例えば次のように書きます。
def MakeFib(n):
if n == 1:
return [1]
elif n == 2:
return [1, 2]
else:
rv = MakeFib(n-1)
return rv + [rv[-2] + rv[-1]]
こうすれば大域変数的に空リストを用意して、appendしなくてもそのままフィボナッチ数列のリストを返します。
で、一応これも再帰ですね。
古い人間ですので、なかなか理解できないのですが、直接添削してくれて、ベターな答えをわかった気になってます。