ポーカーハンドの最後のカードを選択する


31

ポーカーハンドは次のように最高から最低までランク付けされます。

  1. ストレートフラッシュ-連続ランクのカード5枚、すべて同じスーツ
  2. Four of a kind-同じランクの4枚のカードと別のランクの1枚のカード
  3. フルハウス-あるランクのカード3枚と別のランクのカード2枚
  4. フラッシュ-同じスーツのカード5枚
  5. ストレート-連続ランクの5枚のカード
  6. 3種類-同じランクの3枚のカードと2つの他のランクの2枚のカード
  7. 2ペア-同じランクの2枚のカード、別のランクの2枚のカード、および第3ランクの1枚のカード
  8. 1ペア-同じランクの2枚のカードと3つの他のランクの3枚のカード
  9. 高カード-連続ランクまたは同じスーツではなく、同じランクではない5枚のカード

  • ランク=カードの番号(A、K、Q、J、10、9、8、7、6、5、4、3、2)。10の代わりにTを使用することもできます。
  • スーツ=ハート(h)、スペード(s)、クラブ(c)、ダイヤモンド(d)。

AceはA、最高と最低の両方の数値(1または14)にできることに注意してください。

カードは、2つの文字As(スペードのエース)、Jc(クラブのジャック)、7h(ハートの7)などで識別できます。


チャレンジ:

ディーラーから4枚のカード(4つの入力文字列)を受け取ります。あなたが得ることができる最高の最後のカードを見つけて出力します。

同様に良いカードがあれば、どれを選ぶか選択できます。

入力および出力形式はオプションですが、個々のカードは上記Jcおよびに示すように識別される必要があります2h


テストケース:

Ah Kh Jh 10h
Qh

7d 8h 10c Jd
9d (or 9h, 9c, 9s)

Js 6c 10s 8h
Jc (or Jh, Jd)

Ac 4c 5d 3d
2h (or 2d, 2c, 2s)

5s 9s Js As
Ks

2h 3h 4h 5h
6h

Js Jc Ac Ah
As (or Ad)  <- Note that AAAJJ is better than AAJJJ because A is higher than J

10d 9d 5h 9c
9h (or 9s)

Ah Ac Ad As
Ks (or Kd, Kh, Kc)

4d 5h 8c Jd
Jc (or Js, Jh)

これはコードゴルフであるため、バイト単位の最短の提出が勝ちです。

回答:


13

Pyth、73バイト

eo_S+*-5l@\AN}SPMJ+NZSM.:+\AT5+-4l{eMJlM.gPkJ-sM*=T+`M}2Tc4"JQKA""hscd"=Zc

これはかなりひどいです。カードの解析、値のソート、...すべてが非常に多くの文字を必要とします。しかし、このアプローチは興味深いものです。

オンラインで試す:デモンストレーションまたはテストスイート

説明:

52枚すべてのカードを生成し、入力の4枚のカードを削除し、各カード(手のスコア)のスコアを生成し、最大スコアでカードを印刷します。

スコアは少し変わっています。2つの完全に異なるハンドのスコアを比較すると、間違った勝者が選択される可能性があります。例えば、ストレートは4エースを打ちます。しかし、最初の4枚のカードが両方の手で同じであれば機能します。そして、私の計算されたスコアは実際には値ではなく、値のリストです:

  • G:まず、ランク別に5枚のカードをグループ化し、長さをとります。 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F:次に、このリストに4マイナス異なるスイートの数を追加します。Flush -> 3追加され、not flush -> 2/1/0追加されます。
  • S:別の番号を追加します。0ストレートではない場合、ストレートである4場合A2345、または5より高いストレートである場合。

これらの4〜7個の数字のリストは降順でソートされ、最大値のリストが選択されます。

なぜこれが機能するのですか?ここでは、すべてのタイプの可能な構成が表示されます。数字の横にある文字は、この数字が生成されたルールを示しています。

  • ストレートフラッシュ:[5S, 3F, 1G, 1G, 1G, 1G, 1G]または[4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • 4つの種類: [4G, 1G, 0F, 0S]
  • フルハウス:[3G, 2G, 1F, 0S]または[3G, 2G, 0F, 0S]
  • 流す: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • ストレート:[5S, 2F, 1G, 1G, 1G, 1G, 1G][5S, 1F, 1G, 1G, 1G, 1G, 1G][5S, 1G, 1G, 1G, 1G, 1G, 0F][4S, 2F, 1G, 1G, 1G, 1G, 1G][4S, 1F, 1G, 1G, 1G, 1G, 1G][4S, 1G, 1G, 1G, 1G, 1G, 0F]
  • 三つの種類:[3G, 1G, 1G, 1F, 0S][3G, 1G, 1G, 0F, 0S]
  • 二つのペア:[2G, 2G, 2F, 1G, 0S][2G, 2G, 1F, 1G, 0S][2G, 2G, 1G, 0F, 0S]
  • ワンペア:[2G, 2F, 1G, 1G, 1G, 0S][2G, 1G, 1G, 1G, 1F, 0S][2G, 1G, 1G, 1G, 0F, 0S]
  • ハイカード:[2F, 1G, 1G, 1G, 1G, 1G, 0S][1F, 1G, 1G, 1G, 1G, 1G, 0S][1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pythはリストを要素ごとに比較します。したがって、ストレートフラッシュは常にフォーオブカインドに勝ることは明らかです。これらのリストでは、典型的なポーカールールのほとんどが明らかです。一部は矛盾しているようです。

  • ストレートはフォーオブカインドまたはフルハウスに勝ちます:問題ありません。リバーカードを使用してフォーオブザカインド/フルハウスを獲得する機会がある場合、同時にストレートに到達することはできません(すでに2つまたは3つの異なるスイートを手にしているため)。
  • ストレートはフラッシュに対して勝ちます。リバーカードでフラッシュとストレートに到達できる場合、ストレートフラッシュに到達することもできます。そして、ストレートフラッシュは、ストレートとフラッシュの両方よりも良いスコアを持っています。
  • 1ペア[2G, 2F, 1G, 1G, 1G, 0S]が2ペアのハンドに対して勝ちます。また、問題ありません。リバーカードで2ペアを獲得した場合、リバーの前に少なくとも1ペアを持っていた。しかし、これは、3種類に改善できることを意味します。したがって、2ペアは実際には決して答えになりません。
  • ハイカード[2F, 1G, 1G, 1G, 1G, 1G, 0S]はいくつかのワンペアハンドに対して勝ちます。これがあなたが到達できる最高のスコアである場合、リバーの前に、1つのスイートの3枚のカードと別のスイートの1枚のカードがあります。しかし、その後、これらの2つのスイートのいずれかと、すでに表示されている値を持つカードを選択することができます[2F, 2G, ...]。これにより、スコアも向上します。

したがって、これは正しいタイプのソリューションを選択します。しかし、最高のワンペア(4つの可能性のうち)を得るにはどうすればよいですか?2つの異なるワンペアソリューションが同じスコアを持つ可能性があるためです。

簡単だ。Pythは、安定したソートを保証します(最大値を取得する場合)。だから私は簡単に順番にカードを生成します2h 2s 2c 2d 3h 3s ... Ad。したがって、最高値のカードが自動的に最大になります。

実装の詳細

=Zc入力文字列を分割し、カードのリストをに保存しZます。 =T+`M}2Tc4"JQKA"ランクのリストを生成し、に['2', ..., '10', 'J', 'Q', 'K', 'A']保存しますT-sM*T..."hscd"Zランクとスイートの各組み合わせを生成し、のカードを削除しますZ

o...これらの残りのカードの順序:lM.gPkJランクのグループの+-4l{eMJlM長さ、4-長さ(スイート)を+*-5l@\AN}SPMJ+NZSM.:+\AT5追加、スイートに応じて0/4/5を追加(長さ5の「A」+ Tの各部分文字列を生成し、手をチェックするそれらの1つ(ハンドのソートとすべてのサブセットのソートが必要)、5倍-カード内の「A」の数)、_Sリストを降順でソートします。

e 最大値を選択して印刷します。


2
非常に創造的で、素晴らしい説明です!
グレッグマーティン

4

JavaScript(ES6)、329 324 317 312 309バイト

H=>[..."cdhs"].map(Y=>[...L="AKQJT98765432"].map(X=>~H.indexOf(X+=Y)||([...H,X].map(([R,S])=>a|=eval(S+'|=1<<L.search(R)',F|=S!=H[0][1]),F=a=c=d=h=s=0),x=c|d,y=h|s,c&=d,h&=s,p=c|x&y|h,t=c&y|h&x,(S=a-7681?((j=a/31)&-j)-j?F?c&h?2e4+a:t?t^p?3e4+t:7e4:p?8e4+p:M:4e4+a:F?5e4+a:a:F?6e4:1e4)<M&&(R=X,M=S))),M=1/0)&&R

使い方

デッキの残りのカードごとに、ハンドスコアを計算しSます。スコアが低いほど、ハンドは良くなります。

スコアの計算に使用される変数

  • F:手がフラッシュの場合は偽
  • c:クラブのビットマスク
  • d:ダイヤモンドのビットマスク
  • h:ハートのビットマスク
  • s:スペードのビットマスク
  • x = c | d:クラブORダイヤモンドのビットマスク
  • y = h | s:ハートORスペードのビットマスク
  • a:すべての組み合わされたスーツのビットマスク
  • p = c & d | x & y | h & s:ペアビットマスク(1)
  • t = c & d & y | h & s & x:3種類のビットマスク(1)

(1) 私はこれらのフォーミュラを数年前に書き、いくつかのポーカーエンジンで使用しました。彼らは働きます。:-)

その他の式

  • c & d & h & s:4種類のビットマスク
  • a == 7681:特別なストレート「A、2、3、4、5」のテスト(0b1111000000001)
  • ((j = a / 31) & -j) == j:他のすべてのストレートのテスト

スコアチャート

Value    | Hand
---------+--------------------------------------------
0   + a  | Standard Straight Flush
1e4      | Special Straight Flush "A, 2, 3, 4, 5"
2e4 + a  | Four of a Kind
3e4 + t  | Full House
4e4 + a  | Flush
5e4 + a  | Standard Straight
6e4      | Special Straight "A, 2, 3, 4, 5"
7e4      | Three of a Kind
8e4 + p  | Pair
Max.     | Everything else

NB: 2ペアを気にする必要はありません。2ペアは最良の選択肢ではありません。(すでに1つのペアがある場合、それをスリーオブカインドに変えることができます。すでに2つのペアがある場合、それらをフルハウスに変えることができます。)

テストケース


3

JavaScript(ES6)、307 349

これは非常にかさばり、最善のアプローチであるかどうかはわかりません。おそらくまだ少しゴルフ可能。

h=>(r='_23456789TJQKAT',R=x=>r.search(x[0]),M=i=>[...'hcds'].some(s=>h.indexOf(j=h[i][0]+s)<0)&&j,[u,v,w,y]=h.sort((a,b)=>R(a)-R(b)).map(x=>R(x)),[,,d,e,f,g,k]=[...new Set(h+h)].sort(),q=10-u-v-w,s=(z=y>12)&q>0?q:y-u<5&&u*5+q-y,d>r?z?'Kh':'Ah':f>r?M((e>r?v<w:u<v)+1):s?r[s]+g:k?M(3):r[13-z-(w>11)-(v>10)]+g)

少ないゴルフ

h=>(
  // card rank, 1 to 13, 0 unused
  // fake rank 14 is T, to complete a straight JQKA?
  // as I always try to complete a straight going up
  r = '_23456789TJQKAT', 

  // R: rank a card
  R = x => r.search(x[0]),  

  // M: find a missing card (to complete a same-rank set like a poker)
  // look for a card with the same rank of the card at position i
  // but with a suit not present in the hand
  M = i => [...'hcds'].some(s => h.indexOf(j=h[i][0]+s) < 0) && j,
  h.sort((a, b) => R(a)-R(b) ), // sort hand by rank
  [u,v,w,y] = h.map(x=>R(x)),   // rank of cards 0..3 in u,v,w,y

  // Purpose: look for duplicate rank and/or duplicate suits
  // Put values and suits in d,e,f,g,k, with no duplicates and sorted
  // suits are lowercase and will be at right end
  [,,d,e,f,g,k] = [...new Set(h+h)].sort(),

  // Only if all ranks are different: find the missing value to get a straight
  // or 0 if a straight cannot be obtained
  // The first part manages the A before a 2
  q = 10-u-v-w, s = y>12&q>0 ? q : y - u < 5 && u * 5 + q - y,

  d > r // d is lowercase -> all cards have the same rank
    ? u < 13 ? 'Ah' : 'Kh' // add a K to a poker of A, else add an A
    : e > r // e is lowercase -> 2 distinct ranks
      ? M(v<w ? 2 : 1) // go for a poker or a full house
      : f > r // f is lowercase -> 3 distinct ranks, we have a pair
        ? M(u<v ? 2 : 1) // find the pair and go for 3 of a kind
        : s // all different ranks, could it become a straight?
          ? r[s] + g // if there is only a suit, it will be a flush straight too
          : k // if there are 2 or more different suits
            ? M(3) // go for a pair with the max rank
            : r[13-(y>12)-(w>11)-(v>10)]+g // flush, find the max missing card
)

テスト

F=
h=>(r='_23456789TJQKAT',R=x=>r.search(x[0]),M=i=>[...'hcds'].some(s=>h.indexOf(j=h[i][0]+s)<0)&&j,[u,v,w,y]=h.sort((a,b)=>R(a)-R(b)).map(x=>R(x)),[,,d,e,f,g,k]=[...new Set(h+h)].sort(),q=10-u-v-w,s=(z=y>12)&q>0?q:y-u<5&&u*5+q-y,d>r?z?'Kh':'Ah':f>r?M((e>r?v<w:u<v)+1):s?r[s]+g:k?M(3):r[13-z-(w>11)-(v>10)]+g)

output=x=>O.textContent+=x+'\n'

;`Ah Kh Jh Th -> Qh
7d 8h Tc Jd -> 9d 9h 9c 9s
Js 6c Ts 8h -> Jc Jh Jd
Ac 4c 5d 3d -> 2h 2d 2c 2s
5s 9s Js As -> Ks
2h 3h 4h 5h -> 6h
Js Jc Ac Ah -> As Ad
Td 9d 5h 9c -> 9h 9s
Ah Ac Ad As -> Ks Kd Kh Kc
4d 5h 8c Jd -> Jc Js Jh`
.split('\n')
.forEach(s=>{
  var o = s.match(/\w+/g) // input and output
  var h = o.splice(0,4) // input in h, output in o
  var hs = h+''
  var r = F(h)
  var ok = o.some(x => x==r)
  
  output((ok?'OK ':'KO ')+ hs + ' -> ' + r)
})
<pre id=O></pre>


私たちの両方のアプローチが非常に類似したサイズに収束するように見えることを見るのは面白い。:-)パフォーマンスの面では、間違いなく高速です。
アーナウルド

@Arnauldなんとか4バイト削りました。あなたの番
edc65
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.