「prolog勉強プロジェクトオイラー41~50」の編集履歴(バックアップ)一覧に戻る

prolog勉強プロジェクトオイラー41~50 - (2013/07/31 (水) 17:36:11) のソース

プロジェクトオイラーの問題を堀江伸一がPrologで解くページ。
なんか私のサイトに対し全問カンニングしてといてるんだろうとか、嘘しか掲載されてないとか言ってる人が一人だけいるようです。
それとは全くべつの話で兵庫県加古川市加古川町南備後在住の森本さんには堀江伸一は小学校の算数までしかできないとかいわれてます。
世の中って厳しいですね。
プロジェクトオイラーは数学の問題が定期的に出題されるサイトで、これをプログラムで解いてくださいという主旨のサイトです。
このページに記載した私なりの答えですが、これがカンニングしてるものかについては。
プロジェクトオイラーのサイトは問題正答者だけが見れる、その問題についてどのように答えを作ったかを提示し合う掲示板があります。
そこでは色々な人が色々なプログラム言語で問題を解いたとの書き込みがありますがPrologで問題を解いたという人を1度も見たことがありません。
つまりPrologでプロジェクトオイラーに挑戦してる人は私以外いないか、いてもネットのどこかで全く違う回答を提示してるだろうとなります。
カンニングしてるというなら直接的なカンニング元を提示する必要があります。
プログラムがきちんと動くかについては実行してみればすぐにきちんと動くことがわかります。
よってこれらは心ない人が何も確認せずはいてる暴言なのでしょう。
リア充や普通のコミュニティのなかにいる人には何の関係もない話ですが、私のような人間関係の底辺にいる人の周辺だと。
ごく稀なことですがこういう心ないことを適当にいう人がでるのです。
世の中は厳しいこともありますね。




*問い41
パンデジタル数の問題。
全部試し割。
全ての桁を足したものが3の倍数になると素数にならないので7桁か4桁しか検討する必要がない。


 sets([7,6,5,4,3,2,1]).
 sets([4,3,2,1]). 
 
 nums([],Result,Result):-!.
 nums(Nums,Num,Result):-select(X,Nums,NumRest),
 	Num1 is Num*10+X,
  	nums(NumRest,Num1,Result).
 
 not_prime(N):-N<2.
 not_prime(N):-
 	sqrt(N,D),
 	D1 is floor(D),
 	between(2,D1,R),
 	0=:=N mod R.
 all_get(N):-
 	sets(A),
 	nums(A,0,N),
 	not(not_prime(N)).
 
 main41:-
 	findall(N,all_get(N),List),sort(List,List1),write(List1).



*問い42
ファイルを読み込み名前を番号に変換して、それが三角数であるかを判定してその個数を数える問題。
コードは難しく見えるがこの問題やってることを考えると小学生みたいな気分になる。


 last(-1).
 spliter(34).
 
 read_name(Names,Name):-
  	get0(C),
 	(spliter(C)->
 	karayomi_read([Name|Names]);
 	Name1 is Name+C-"A"+1,
 	read_name(Names,Name1)).
 
 karayomi_read(Names):-get0(C),karayomi(Names,C).
 karayomi(Names,C):-last(C),!,count(Names,0).
 karayomi(Names,C):-spliter(C),!,read_name(Names,0).
 karayomi(Names,_):-karayomi_read(Names).
 
 isDelta(T,_):-T<0,!,fail.
 isDelta(0,_):-!.
 isDelta(T,Dell):-T1 is T-Dell,Dell1 is Dell+1,isDelta(T1,Dell1).
 
 count([],Ans):-!,write(Ans).
 count([Num|Rest],Ans):-isDelta(Num,1),!,Ans1 is Ans+1,count(Rest,Ans1).
 count([_|Rest],Ans):-count(Rest,Ans).
 
 main42:-seen,see('e42.txt'),karayomi_read([]).



*問い43
枝刈しながら求めるだけ。
行列演算を解くふうみな何かがあるのかも?

 to_num([],Result,Result):-!.
 to_num([D|Rest],N,Result):-N1 is N*10+D,to_num(Rest,N1,Result).
 
 search([D1,D2],_,Ans,[],Result):-Ans1=[D2,D1|Ans],
 	reverse(Ans1,Ans2),
 	to_num(Ans2,0,Result).
 
 search([D1,D2],Nums,Ans,[P|Ps],Result):-
 	select(D3,Nums,Rest),
 	to_num([D1,D2,D3],0,Num),
 	0=:=Num mod P,
 	search([D2,D3],Rest,[D1|Ans],Ps,Result).
 
 search_w(N):-
 	select(D1,[0,1,2,3,4,5,6,7,8,9],Rest),
 	0<D1,
 	select(D2,Rest,Rest1),
 	search([D1,D2],Rest1,[],[1,2,3,5,7,11,13,17],N).
 sum([],0).
 sum([X|Rest],Result):-sum(Rest,Re),Result is Re + X.
 
 main43:-
 	findall(N,search_w(N),List),write(List),sum(List,Ans),write(Ans).




*問い44
http://projecteuler.net/problem=44
条件を見たすPn、Pmを考えた時
m=n-aとし、5角数dを考えると
d=n(3n-1)/2-(n-a)(3(n-a)-1)/2
を展開して整理して
2d=6an-3a^2-a
a=(6n-1 (+ of -)sqrt((6n-1)^-24d))/6
a=6n-1とすると
a^2-24d=b^2
a^2-b^2=24d
(a+b)(a-b)=24d
ここで
1からint(sqrt(24d))=cで24dを割って余りが出なければ
a-b=cここからa+bがでてくるので。
とやるとまあまあの計算量。
でもまだ少し計算量が多い。
これは高校生が思いつきそうな素朴な方法。
この先どうしようかな?