2012年8月19日日曜日

Project Euler - Probrem 45

Project Euler(プロジェクト オイラー)の問題をpythonでやってみます。

出典: Project Euler(日本語 翻訳サイト)
    ProjectEuler.net(英語サイト)

Problem 45
三角数, 五角数, 六角数は以下のように生成される.
三角数Tn=n(n+1)/2 1, 3, 6, 10, 15, ...
五角数Pn=n(3n-1)/2 1, 5, 12, 22, 35, ...
六角数Hn=n(2n-1) 1, 6, 15, 28, 45, ...
T285 = P165 = H143 = 40755であることが分かる.
次の三角数かつ五角数かつ六角数な数を求めよ.


-----

私の解答例は以下です。畳んでいます。
import math

def h(n): return not (-1+math.sqrt(1+n*8))%2

def g(n): return not (1+math.sqrt(1+n*24))%6

def f(n):
	i = 0
	while True:
		i += 1
		s = i*(2*i-1)
		if s<=n: continue
		if g(s) and h(s): return s

print f(40755)


六角数の進み方が一番早いので、六角数を1つずつ計算してそれが五角数、三角数であるか判定する方法でやります。

3つの関数を使っています。

1.関数h(n)
・return not (-1+math.sqrt(1+n*8))%2
 三角数の判定です。
 定義式から、x(x+1)/2 = nを満たす整数xが存在すればnは三角数です。
 xの二次方程式として、二次方程式の解の公式より、
 x = -1±√(1+8n)/2
 %演算子は割り算の余りです。
 整数xが存在すれば上記の余りがない(論理的にFalse)です。
 このxが整数かどうかは、+か-のどちらで判定しても同じなので、
 ここでは+の方を採用しています。

2.関数g(n)
・五角数の判定です。problem44と同じです。

3.関数f(n)
・nを超える最小の三角数かつ五角数かつ六角数である数を返します。

・i = 0
 初期値としてnを設定します。

・while True:
 無限ループです。

・i += 1
 iは1ずつ増えるカウンターです。

・s = i*(2*i-1)
 sはi番目の六角数です。

・if s<=n: continue
 六角数sがn以下の場合は次の六角数に進みます。

・if g(s) and h(s): return s
 六角数sが五角数かつ三角数の場合、その数sを返します。

3.関数の外
・print f(40755)
 問題に従い、40755を超える範囲で関数f(n)を呼び出します。


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

0 件のコメント:

コメントを投稿