2012年4月14日土曜日

プロジェクトオイラー 問2

プロジェクトオイラーの問題をpythonでやってみます。
出典:
英語サイトは、Project Euler でネット検索してください。
日本語翻訳サイトは、プロジェクトオイラー日本語 でネット検索してください。



問2
フィボナッチ数列の項は前の2つの項の和である。 最初の2項を 1, 2 とすれば、最初の10項は以下の通りである。
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 数列の項の値が400万を超えない範囲で、偶数値の項の総和を求めよ。


注意!!!
自力で解きたい人へ
以降の記述には解法に関するネタバレが含まれます。






私の解答例は以下のとおりです。
-----
L, t = [1, 2], 0
while L[1]<4000000:
	if not L[1]%2: t += L[1]
	L = [L[1], sum(L)]
print t
-----

リストLは2つの要素を持つ配列で、L[0]に2つ前の値、L[1]に1つ前の値を格納しています。
変数tには合計する対象の値を累積していきます。
1行目でこのリストと変数の初期設定をしています。


%演算子は割り算の余りを返し、
2で割ったあまりが0か1かで奇数か偶数かを判定します。


論理判定では0がFalse、0以外がTrueと判定されます。
偶数の場合、余りは0なので、
L[1]%2がFalseのときに、変数tにL[1]を累積します。


累積し終わったら、次の準備として、
現在の1つ前の値と次のフィボナッチ数を、新たなL[0]、L[1]として格納し処理を続けます。


別解です。フィボナッチ数の計算部分を関数にしてみました。

def p(n):
	L = [1, 2]
	while L[1]<n:
		yield L[1]
		L = [L[1], sum(L)]
	
print sum([i for i in p(4000000) if not i%2])
-----
関数pは、nまでのフィボナッチ数を小さい順に1つずつ返します。
returnでは値を1度返したら終わりですが、
yieldでは値を一つずつ返し、for文の中で値を取り出すことができます。

sum関数の中の配列[]の意味は以下のとおりです。
関数p(4000000)の1つずつの戻り値iのうち、偶数(not i%2)だけを格納した配列

解答はこのすぐ下の行です。文字の色を白にしてます。選択状態にすると見えます。
4613732


(追記)
・20120716 ソースコード部分にSyntaxHighlighterを導入
・20130120 ネタバレ注意の追記など

0 件のコメント:

コメントを投稿