「プロジェクトオイラー問44」の編集履歴(バックアップ)一覧はこちら
「プロジェクトオイラー問44」(2014/02/17 (月) 13:31:45) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
Problem 44 「五角数」 †
五角数は Pn = n(3n-1)/2 で生成される. 最初の10項は
1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ...
である.
P4 + P7 = 22 + 70 = 92 = P8 である. しかし差 70 - 22 = 48 は五角数ではない.
五角数のペア Pj と Pk について, 差と和が五角数になるものを考える. 差を D = |Pk - Pj| と書く. 差 D の最小値を求めよ.
解法
http://d.hatena.ne.jp/inamori/20100214/p2
三平方の定理と結びつける解法を攻めてみたけれど効率が悪かった。
効率的な解法を思いつかなかったのでリンク先の解説を参考にコードを記述。
リンク先の考え方は非常にわかりやすい。
is_penta(P):-
T is floor(sqrt(1+24*P)),
T*T=:=(1+24*P),
(T+1) mod 6=:=0.
penta(N,Result):-!,
Result is (N*(3*N-1))//2.
divs(N,P,N,0):-N mod P>0,!.
divs(N,P,ResultN,ResultC):-
N1 is N//P,
divs(N1,P,ResultN,ReC),
ResultC is ReC+1.
count_fact(N,P,[[N,1]]):-
N<P*P,
N>1,
!.
count_fact(N,P,[]):-
N<P*P,
!.
count_fact(N,P,[[P,C]|Result]):-
N mod P=:=0,
!,
divs(N,P,N1,C),
P1 is P+1,
count_fact(N1,P1,Result).
count_fact(N,P,Result):-
!,
P1 is P+1,
count_fact(N,P1,Result).
union_sum([],[],[]):-!.
union_sum(Xs,[],Xs):-!.
union_sum([],Ys,Ys):-!.
union_sum([[P,C1]|Xs],[[P,C2]|Ys],[[P,C3]|Result]):-
!,
C3 is C1+C2,
union_sum(Xs,Ys,Result).
union_sum([[P1,C1]|Xs],[[P2,C2]|Ys],[[P1,C1]|Result]):-
P1<P2,
!,
union_sum(Xs,[[P2,C2]|Ys],Result).
union_sum(Xs,[[P2,C2]|Ys],[[P2,C2]|Result]):-
!,
union_sum(Xs,Ys,Result).
yakusu([],Num,Num):-!.
yakusu([[P,C]|Rest],Num,Result):-
between(0,C,R),
Num1 is Num*(P^R),
yakusu(Rest,Num1,Result).
search2(P,[Pj,Pk]):-
count_fact(P,2,Fact1),
P1 is 3*P-1,
count_fact(P1,2,Fact2),
union_sum(Fact1,Fact2,Fact3),
yakusu(Fact3,1,Y1),
Y2 is (P*(3*P-1))//Y1,
T1 is 3*Y1+Y2+1,
T1 mod 6=:=0,
J is T1//6,
J>0,
S1 is -3*Y1+Y2+1,
S1 mod 6=:=0,
K is S1 //6,
K>0,
J>K,
penta(J,Pj),
penta(K,Pk).
search(P,Result):-
search2(P,[Pj,Pk]),
PA is Pj+Pk,
is_penta(PA),
penta(P,Result),
!.
search(P,Result):-
P1 is P+1,
search(P1,Result).
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2044
Problem 44 「五角数」 †
五角数は Pn = n(3n-1)/2 で生成される. 最初の10項は
1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ...
である.
P4 + P7 = 22 + 70 = 92 = P8 である. しかし差 70 - 22 = 48 は五角数ではない.
五角数のペア Pj と Pk について, 差と和が五角数になるものを考える. 差を D = |Pk - Pj| と書く. 差 D の最小値を求めよ.
解法
http://d.hatena.ne.jp/inamori/20100214/p2
三平方の定理と結びつける解法を攻めてみたけれど効率が悪かった。
効率的な解法を思いつかなかったのでリンク先の解説を参考にコードを記述。
リンク先の考え方は非常にわかりやすい。
is_penta(P):-
T is floor(sqrt(1+24*P)),
T*T=:=(1+24*P),
(T+1) mod 6=:=0.
penta(N,Result):-!,
Result is (N*(3*N-1))//2.
divs(N,P,N,0):-N mod P>0,!.
divs(N,P,ResultN,ResultC):-
N1 is N//P,
divs(N1,P,ResultN,ReC),
ResultC is ReC+1.
count_fact(N,P,[[N,1]]):-
N<P*P,
N>1,
!.
count_fact(N,P,[]):-
N<P*P,
!.
count_fact(N,P,[[P,C]|Result]):-
N mod P=:=0,
!,
divs(N,P,N1,C),
P1 is P+1,
count_fact(N1,P1,Result).
count_fact(N,P,Result):-
!,
P1 is P+1,
count_fact(N,P1,Result).
union_sum([],[],[]):-!.
union_sum(Xs,[],Xs):-!.
union_sum([],Ys,Ys):-!.
union_sum([[P,C1]|Xs],[[P,C2]|Ys],[[P,C3]|Result]):-
!,
C3 is C1+C2,
union_sum(Xs,Ys,Result).
union_sum([[P1,C1]|Xs],[[P2,C2]|Ys],[[P1,C1]|Result]):-
P1<P2,
!,
union_sum(Xs,[[P2,C2]|Ys],Result).
union_sum(Xs,[[P2,C2]|Ys],[[P2,C2]|Result]):-
!,
union_sum(Xs,Ys,Result).
yakusu([],Num,Num):-!.
yakusu([[P,C]|Rest],Num,Result):-
between(0,C,R),
Num1 is Num*(P^R),
yakusu(Rest,Num1,Result).
search2(P,[Pj,Pk]):-
count_fact(P,2,Fact1),
P1 is 3*P-1,
count_fact(P1,2,Fact2),
union_sum(Fact1,Fact2,Fact3),
yakusu(Fact3,1,Y1),
Y2 is (P*(3*P-1))//Y1,
T1 is 3*Y1+Y2+1,
T1 mod 6=:=0,
J is T1//6,
J>0,
S1 is -3*Y1+Y2+1,
S1 mod 6=:=0,
K is S1 //6,
K>0,
J>K,
penta(J,Pj),
penta(K,Pk).
search(P,Result):-
search2(P,[Pj,Pk]),
PA is Pj+Pk,
is_penta(PA),
penta(P,Result),
!.
search(P,Result):-
P1 is P+1,
search(P1,Result).