Problem 54 「ポーカーハンド」 †
カードゲームのポーカーでは, 手札は5枚のカードからなりランク付けされている. 役を低い方から高い方へ順に並べると以下である.
- 役無し(ハイカード): 一番値が大きいカード
- ワン・ペア: 同じ値のカードが2枚
- ツー・ペア: 2つの異なる値のペア
- スリーカード: 同じ値のカードが3枚
- ストレート: 5枚の連続する値のカード
- フラッシュ: 全てのカードが同じスート (注: スートとはダイヤ・ハート・クラブ/スペードというカードの絵柄のこと)
- フルハウス: スリーカードとペア
- フォーカード: 同じ値のカードが4枚
- ストレートフラッシュ: ストレートかつフラッシュ
- ロイヤルフラッシュ: 同じスートの10, J, Q, K, A
ここでカードの値は小さい方から2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, Aである. (訳注:データ中で10は'T'と表される)
もし2人のプレイヤーが同じ役の場合には, 役を構成する中で値が最も大きいカードによってランクが決まる: 例えば, 8のペアは5のペアより強い (下の例1を見よ). それでも同じランクの場合には (例えば, 両者ともQのペアの場合), 一番値が大きいカードによってランクが決まる (下の例4を見よ). 一番値が大きいカードが同じ場合には, 次に値が大きいカードが比べれられ, 以下同様にランクを決定する.
例:
| 試合 | プレイヤー1 | プレイヤー2 | 勝者 |
| 1 | 5H 5C 6S 7S KD 5のペア | 2C 3S 8S 8D TD 8のペア | プレイヤー2 |
| 2 | 5D 8C 9S JS AC 役無し, A | 2C 5C 7D 8S QH 役無し, Q | プレイヤー1 |
| 3 | 2D 9C AS AH AC Aのスリーカード | 3D 6D 7D TD QD ダイヤのフラッシュ | プレイヤー2 |
| 4 | 4D 6S 9H QH QC Qのペア, 9 | 3D 6D 7H QD QS Qのペア, 7 | プレイヤー1 |
| 5 | 2H 2D 4C 4D 4S 4-2のフルハウス | 3C 3D 3S 9S 9D 3-9のフルハウス | プレイヤー1 |
poker.txtには1000個のランダムな手札の組が含まれている. 各行は10枚のカードからなる (スペースで区切られている): 最初の5枚がプレイヤー1の手札であり, 残りの5枚がプレイヤー2の手札である. 以下のことを仮定してよい
- 全ての手札は正しい (使われない文字が出現しない. 同じカードは繰り返されない)
- 各プレイヤーの手札は特に決まった順に並んでいるわけではない
- 各勝負で勝敗は必ず決まる
1000回中プレイヤー1が勝つのは何回か? (訳注 : この問題に置いてA 2 3 4 5というストレートは考えなくてもよい)
http://odz.sakura.ne.jp/projecteuler/index.php?cmd=read&page=Problem%2054
解法
特に工夫もなく役を判定して役のスコアをだし。
カードを役から大きい順
役以外から大きい順
に並べて判定するだけです。
ファイルはテキストエディタでPrologのリスト形式に直してから読み込んでいる。
toNum(84,10):-!.
toNum(74,11):-!.
toNum(81,12):-!.
toNum(75,13):-!.
toNum(65,14):-!.
toNum(N,N1):-!,N1 is N-48.
yaku([[Y1,X],[Y2,X],[Y3,X],[Y4,X],[Y5,X]],_,[9000,Y5,Y4]):-
Y1+1=:=Y2,
Y2+1=:=Y3,
Y3+1=:=Y4,
Y4+1=:=Y5,
!.
yaku(_,[[4,Y],[1,Y1]],[8000,Y,Y1]):-!.
yaku(_,[[3,Y1]|[2,Y2]],[7000,Y1,Y2]):-!.
yaku([[Y1,X],[Y2,X],[Y3,X],[Y4,X],[Y5,X]],_,[6000,Y5,Y4,Y3,Y2,Y1]):-!.
yaku([[Y1,_],[Y2,_],[Y3,_],[Y4,_],[Y5,_]],_,[5000,Y5,Y4]):-
Y1+1=:=Y2,
Y2+1=:=Y3,
Y3+1=:=Y4,
Y4+1=:=Y5,
!.
yaku(_,[[3,Y],[1,Y1],[1,Y2]],[4000,Y,Y1,Y2]):-!.
yaku(_,[[2,Y1],[2,Y2],[1,Y3]],[3000,Y1,Y2,Y3]):-!.
yaku(_,[[2,Y],[1,Y1],[1,Y2],[1,Y3]],[2000,Y,Y1,Y2,Y3]):-!.
yaku(_,[[1,Y1],[1,Y2],[1,Y3],[1,Y4],[1,Y5]],[1000,Y1,Y2,Y3,Y4,Y5]):-!.
count([],[C,Y],[[C,Y]]):-!.
count([[Y,_]|Rest],[C,Y],Result):-
!,
C1 is C+1,
count(Rest,[C1,Y],Result).
count([[Y1,_]|Rest],[C,Y],[[C,Y]|Result]):-
!,
count(Rest,[1,Y1],Result).
count_w(Cards,Count):-
msort(Cards,[[Y|_]|Cards1]),
count(Cards1,[1,Y],Count).
card_to_num([],[]):-!.
card_to_num([[Y,X]|Rest],[[Y1,X]|Result]):-
!,
toNum(Y,Y1),
card_to_num(Rest,Result).
score(Cards,Score):-
card_to_num(Cards,Cards1),
msort(Cards1,Cards2),
count_w(Cards2,Count2),
msort(Count2,Count3),
reverse(Count3,Count4),
yaku(Cards2,Count4,Score).
is_v(Cards1,Cards2):-
score(Cards1,Score1),
score(Cards2,Score2),
msort([Score1,Score2],[_,Score1]).
v_count(IS,V):-
at_end_of_stream(IS),
!,
write(V).
v_count(IS,V):-
read_term(IS,Cards,[]),
[A1,A2,A3,A4,A5,B1,B2,B3,B4,B5]=Cards,
is_v([A1,A2,A3,A4,A5],[B1,B2,B3,B4,B5]),
!,
V1 is V+1,
v_count(IS,V1)
.
v_count(IS,V):-
!,
v_count(IS,V).
main54:-
open('pe54.txt',read,IS),
v_count(IS,0),
close(IS).
0 件のコメント:
コメントを投稿