Problem 54 「ポーカーハンド」 †
ポーカーの勝敗を判定する問題。
詳細はリンク先を参照のこと。
解法
世界中で何回ポーカーの役判定のコードが書かれたのだろうかと思いをはせる問題です。
両者ともに素朴に役を判定して役に対応したスコアと役で使ったカードの数字を返し、
Aのほうがスコアが大きいなら勝利、同じならカードを比べてAの勝利か判定するだけ。
1を14として取り扱うと話が綺麗になります。
判定には巧みな手法があるそうなのでそれを調べるのもいいかもしれませんね。
ファイルは一行ごと10枚のカードを現すリストと変換しています。
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).
最終更新:2014年02月20日 03:00