2014年3月21日金曜日

プロジェクトオイラー Problem 54 「ポーカーハンド」 †

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勝者
15H 5C 6S 7S KD
5のペア
2C 3S 8S 8D TD
8のペア
プレイヤー2
25D 8C 9S JS AC
役無し, A
2C 5C 7D 8S QH
役無し, Q
プレイヤー1
32D 9C AS AH AC
Aのスリーカード
3D 6D 7D TD QD
ダイヤのフラッシュ
プレイヤー2
44D 6S 9H QH QC
Qのペア, 9
3D 6D 7H QD QS
Qのペア, 7
プレイヤー1
52H 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 件のコメント:

コメントを投稿