「プロジェクトオイラー問54」の編集履歴(バックアップ)一覧に戻る
プロジェクトオイラー問54」を以下のとおり復元します。
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2054

*Problem 54 「ポーカーハンド」 †
ポーカーの勝敗を判定する問題。
詳細はリンク先を参照のこと。


解法
世界中で何回ポーカーの役判定のコードが書かれたのだろうかと思いをはせる問題です。
両者ともに素朴に役を判定して役に対応したスコアと役で使ったカードの数字を返し、
Aのほうがスコアが大きいなら勝利、同じならカードを比べてAの勝利か判定するだけ。
1を14として取り扱うと話が綺麗になる。


 max(A,B,A):-A>B,!.
 max(_,B,B):-!.
 
 min(A,B,A):-A<B,!.
 min(_,B,B):-!.
 
 toNum(84,10):-!.
 toNum(74,11):-!.
 toNum(81,12):-!.
 toNum(75,13):-!.
 toNum(65,14):-!.
 toNum(N,N1):-!,N1 is N-48.
 
 last([X],X):-!.
 last([_|Xs],Result):-
 	!,
 	last(Xs,Result).
 
 count([],Count,Result):-
 	!,
 	sort(Count,Count1),
 	reverse(Count1,Result).
 count([[N,_]|Rest],Count,Result):-
 	select([C,N],Count,Count1),
 	!,
 	C1 is C+1,
 	count(Rest,[[C1,N]|Count1],Result).
 count([[N,_]|Rest],Count,Result):-
 	!,
 	count(Rest,[[1,N]|Count],Result).
 
 
 cards_toNum([],[]):-!.
 cards_toNum([[Y,S]|Rest],[[N,S]|Result]):-
 	!,
 	toNum(Y,N),
 	cards_toNum(Rest,Result).
 
 
 % ロイヤルフラッシュ
 yaku1([[14,X],[10,X],[11,X],[12,X],[13,X]],9000,[14,13,12,11,10]):-!.
 % ストレートフラッシュ
 yaku1([[N1,X],[N2,X],[N3,X],[N4,X],[N5,X]],8000,[N5,N4,N3,N2,N1]):-
 	N2=:=N1+1,
 	N3=:=N2+1,
 	N4=:=N3+1,
 	N5=:=N4+1,
 	!.
 % フラッシュ
 yaku1([[N1,X],[N2,X],[N3,X],[N4,X],[N5,X]],5000,[N5,N4,N3,N2,N1]):-!.
 % ストレート
 yaku1([[N1,_],[N2,_],[N3,_],[N4,_],[N5,_]],4000,[N5,N4,N3,N2,N1]):-
 	N2=:=N1+1,
 	N3=:=N2+1,
 	N4=:=N3+1,
 	N5=:=N4+1,
 	!.
 yaku1([[N1,_],[N2,_],[N3,_],[N4,_],[N5,_]],0,[N5,N4,N3,N2,N1]):-!.
 
 
 
 %4Card
 yaku2([[4,N1]|_],7000,[N1]):-
 	!.
 %fullHouse
 yaku2([[3,N1],[2,N2]],6000,[ReN2,ReN1]):-
       !,
       max(N1,N2,ReN2),
        min(N1,N2,ReN1).
 %3Card
 yaku2([[3,N1]|_],3000,[N1]):-!.
 %2pare
 yaku2([[2,N1],[2,N2]|_],2000,[ReN2,ReN1]):-
 	!,
 	max(N1,N2,ReN2),
 	min(N1,N2,ReN1).
 %1pare
 yaku2([[2,N1]|_],1000,[N1]):-!.
 yaku2(_,0,[0]):-!.
 
 calc_yaku(Cards,[Score,Nums]):-
 	yaku1(Cards,Score,Nums).
 calc_yaku(Cards,[Score,Nums]):-
 	count(Cards,[],Count),
 	yaku2(Count,Score,Nums).
 calc_yaku_w(Cards,Result):-
 	cards_toNum(Cards,Cards1),
 	sort(Cards1,Cards2),
 	findall(Set,calc_yaku(Cards2,Set),Sets),
 	sort(Sets,Sets1),
 	last(Sets1,Result).
 
 is_big([],[]):-!,fail.
 is_big([_|_],[]):-!.
 is_big([X|_],[Y|_]):-X<Y,!,fail.
 is_big([X|_],[Y|_]):-X>Y,!.
 is_big([_|Xs],[_|Ys]):-
 	!,
 	is_big(Xs,Ys).
 
 isV(Cards1,Cards2,V,V1):-
  	calc_yaku_w(Cards1,[Score1,Nums1]),
 	calc_yaku_w(Cards2,[Score2,Nums2]),
 	(Score1>Score2 -> V1 is V+1;
 	((Score1=:=Score2,is_big(Nums1,Nums2))->
 	V1 is V+1;V1 is V)).
 
 
 myread(IS,V):-at_end_of_stream(IS),!,close(IS),write(V).
 myread(IS,V):-
 	read_term(IS,Cards,[]),
  	[A1,A2,A3,A4,A5,B1,B2,B3,B4,B5]=Cards,
 	isV([A1,A2,A3,A4,A5],[B1,B2,B3,B4,B5],V,V1),
 	myread(IS,V1).
 main54:-
 	open('pe54.txt',read,IS),
  	myread(IS,0).

復元してよろしいですか?