Hold'em oder Fold'em?

17

Ihr Freund hat Sie in letzter Minute zu einem Pokerspiel mit hohen Einsätzen eingeladen. Als Informatiker haben Sie sich dazu entschlossen, Ihre Fähigkeiten einzusetzen, um einen Vorsprung gegenüber dem Spiel zu erlangen. Ihre Aufgabe wird es sein, gegeben 2 cards(Ihre Hand) und 0, 3, 4 or 5 cards(die ausgeteilt Karten), Sie müssen entscheiden, was die bestmögliche Hand sein wird, die Sie bekommen können. Wenn alle 7 Karten als Argumente angegeben werden, ist die Antwort ziemlich klar. Wenn weniger gegeben wird, wird das Problem komplexer. Dies reicht jedoch nicht aus, um den gewünschten Vorteil zu erzielen. Sie müssen auch die bestmögliche Hand aus den verbleibenden Karten berechnen, um zu verstehen, was Ihre Gegner ebenfalls haben könnten.


Hold'em Refresher

Wenn Sie sich mit Hold'em nicht auskennen, beginnt jeder Spieler im Spiel mit 2 Karten als "Hand". In 3 Spielzügen werden zusätzliche Karten aufgedeckt, die von allen Spielern geteilt werden. In der ersten Runde werden 3 Karten aufgedeckt. Das zweite, ein weiteres und das dritte Mal wird eine letzte Karte aufgedeckt. Die zwei Karten, die zuerst gegeben werden, stellen Ihre Hand dar, während die letzteren 0, 3, 4 oder 5 Karten darstellen, die durch die aufeinander folgenden Züge gegeben werden.


Mögliche Nummern:

[2,3,4,5,6,7,8,9,T(10),J,Q,K,A]

Mögliche Anzüge:

[S,C,H,D]

Volles Deck:

[2S,3S,4S,5S,6S,7S,8S,9S,TS,JS,QS,KS,AS, # Spades.
 2C,3C,4C,5C,6C,7C,8C,9C,TC,JC,QC,KC,AC, # Clubs.
 2H,3H,4H,5H,6H,7H,8H,9H,TH,JH,QH,KH,AH, # Hearts.
 2D,3D,4D,5D,6D,7D,8D,9D,TD,JD,QD,KD,AD] # Diamonds.

Hand-Ranglisten:

1:Royal Flush    (A-K-Q-J-10, all from the same suit).
2:Straight Flush (Sequential cards, all from the same suit).
3:Four-of-a-Kind (Self explanatory).
4:Full House     (3-of-a-kind and a 2-of-a-kind).
5:Flush          (All cards are from the same suit).
6:Straight       (Sequential Cards, any suits).
7:3-of-a-Kind    (Self explanatory).
8:2-Pair         (Double 2-of-a-Kind).
9:Pair           (2-of-a-Kind).
10:High Card     (You have absolutely nothing except a single card).

Nehmen wir ein oder zwei Beispiele und gehen wir sie durch:

Das einfache Beispiel:

[AS, AC],[AH,AD,9S,9C,9H]-> 3(Four-of-a-Kind), 3(Four-of-a-Kind)

Die bestmögliche Hand, die Sie in diesem Setup haben, ist der Vierling. Die bestmögliche Hand, die Ihre Gegner haben könnten, ist ebenfalls ein 4-of-a-Kind, da Sie keinen KQJ10 in ihren 2-Karten-Händen haben können.


[5C,2C],[6C,4C,JH,JD]-> 2(Straight Flush), 3(4-of-a-Kind)

Sie riskieren einen Straight Flush, aber weil Sie das 2 / 5C auf der Hand haben, liegt es nicht daran, dass Sie beide Mittelkarten halten. Das Beste, auf das sie hoffen können, ist, 2 Pocket Jacks zu haben und einen Jack am Flop zu bekommen.


[JS,JC],[]-> 1(Royal Flush), 1(Royal Flush)

Es wurden keine Informationen angegeben, die Sie gegen sie verwenden können. Im Moment können Sie nur sagen, dass sie nur einen Royal Flush in Diamanten / Herzen haben können. Es ist jedoch genauso möglich, dass Sie den Royal Flush erhalten wie sie. Tatsächlich sollten alle Eingaben, bei denen der Flop noch nicht erfolgt ist, zu einer 1: 1-Antwort führen.


[2C,4S],[3C,7S,9D,AH,JD]-> 10(High Card), 7(3-of-a-Kind)

Dies ist ein Beispiel dafür, wo man absolut durchgeknallt ist, und es gibt keine Möglichkeit, dass der Fluss eine Straße oder einen Flush bekommt. Das heißt, die beste Hand hier sind Pocket-Asse, die zu einem 3-of-a-Kind führen.


E / A-Anforderungen

  • Die Eingabe muss zwischen dem, was in Ihrer Hand ist, und dem, was öffentlich bekannt ist, getrennt werden. Dies ist wahrscheinlich einfacher, unabhängig von der Implementierung.
    • Karten können nach Belieben Tupel oder Strings sein.
    • Die Hand und das Spielfeld können Arrays oder begrenzte Zeichenfolgen sein.
  • Es müssen zwei Indizes aus der Liste der Hände ausgegeben werden, die ich bereitgestellt habe (EG [2,1]).
    • Es kann als Teil einer Funktion zurückgegeben, auf die Konsole gedruckt oder auf geeignete Weise ausgegeben werden.
    • Es muss zwei unterschiedliche Werte geben, einen für Ihre beste Hand, einen anderen für die bestmögliche.
  • 10 kann als Toder als dargestellt werden 10, je nachdem, was für Sie sinnvoll ist.
  • Standardlücken sind nicht zulässig.

Gewinnkriterien

  • Dies ist , die niedrigste Byte-Anzahl mit einem Tie-Breaker nach dem Datum.
Magische Kraken-Urne
quelle
2
Sollte nicht nur einer der folgenden sein Aund 1in den möglichen erlaubt Karten? Auch ich glaube nicht, dass es wirklich einen zwingenden Grund gibt, die Gesichtsabkürzungen über numerischen Werten wie zu verlangen 11.
FryAmTheEggman
9
Ich habe noch nie ein Deck mit einem Aund einem gesehen 1. Alles andere sieht gut aus.
Isaacg
1
Für uns Nicht-Pokerspieler erklären Sie bitte in der Frage, dass die zweite Kartengruppe zwischen Ihnen und Ihrem Gegner geteilt wird, während sie ihre eigenen zwei Karten haben, die Sie nicht sehen können. Ein kurzes Glossar mit den Begriffen pocket , flop und river wäre hilfreich.
DLosc
1
Ebenfalls hilfreich: Erklären des gesamten Ablaufs einer Runde. (Jeder Spieler beginnt mit zwei Karten, die nur ihm bekannt sind, dann werden drei Karten offen ausgeteilt, dann eine vierte und dann eine fünfte. Zu diesem Zeitpunkt bildet jeder Spieler eine "Hand" aus fünf der sieben Karten, die für ihn sichtbar sind .) Jemandem ist vielleicht nicht klar, warum es sieben Karten gibt, aber eine Hand besteht aus fünf.
DLosc

Antworten:

3

Haskell , 433 430 425 Bytes

-5 Bytes dank @Laikoni

import Data.List
q="23456789TJQKA"
e=elem
l=length
b=map
r p|z,elem 'A'u,elem 'K'u=1|z=2|e 4t=3|v<3=4|w=5|y=6|e 3t=7|v<4=8|v<5=9|1>0=10where u=[n!!0|n<-p];v=l$nub u;t=b(\n->l[x |x<-u,x==n])q;w=all(==(last$p!!0))[last s|s<-p];y=elem""[u\\s|s<-b(take 5.flip drop('A':q))[0..10]];z=y&&w
0%_=[[]]
n%(x:y)=b(x:)((n-1)%y)++n%y
_%_=[]
h#t|let p=h++t;c i=minimum$b r$concat$b(5%)$b(++i)((7-l i)%([n:[s]|n<-q,s<-"SCHD"]\\p))=(c p,c t)

Probieren Sie es online!

Ungolfed (gleiche Idee, etwas andere Struktur):

import Data.List -- for (\\)
numbers = "23456789TJQKA"

e=elem

rank_hand hand
    |royal_flush=1
    |straight_flush=2
    |four_of_a_kind=3
    |full_house=4
    |flush=5
    |straight=6
    |three_kind=7
    |two_pair=8
    |pair=9
    |1>0=10
    where nums = [head n | n<-hand]
          unique = length $ nub nums
          counts = map (\n->length [x | x<-nums, x==n]) numbers
          pair = unique < 5
          two_pair = unique < 4 -- could also be 3 of a kind, but that's ok
          three_kind = e 3 counts
          flush = all (==(last$hand!!0)) [last s|s<-hand]
          straight = elem "" [nums\\s | s <- map (take 5.flip drop ('A':numbers))[0..10]]
          full_house = unique < 3
          four_of_a_kind = e 4 counts
          straight_flush = straight && flush
          royal_flush = straight_flush && elem 'A' nums && elem 'K' nums

-- taken from /codegolf//a/34496/66460
-- k%l finds combinations of size k from a list l
0%_=[[]]
n%(x:y)=map(x:)((n-1)%y)++n%y
_%_=[]

-- find every combination available to each player, and rank each one. 
-- could be golfed a lot more.
h#t=let p=h++t
        a=[n:[s]|n<-numbers,s<-"SCHD"]\\p
        c i=minimum $ map rank_hand $ concat $ map (5%) $ map (++i) ((7-length i)%a)
    in(c p,c t)

Sehr langsam, da es überhaupt kein spezielles Gehäuse gibt (z. B. wenn keine Karten gezeigt wurden, ist ein Royal Flush immer möglich.) Der größte Teil meines Golfaufwands ging in die rank_handFunktion; #kann viel mehr golfen werden, indem man karten und so kombiniert.

hand#tableberechnet die optimalen Werte für Sie und Ihren Gegner. Führt keine Fehlerprüfung durch.

vroomfondel
quelle
Ich denke, Sie haben s/elem/e/gnach der Definition vergessen e=elem, so dass Sie 9ish Bytes sparen sollten. Ich denke, Sie können auch einige Leerzeichen entfernen, insbesondere wenn Bezeichner direkt auf Zahlen folgen
Julian Wolf
@JulianWolf Ich bin noch neu in Haskell, aber aus irgendeinem Grund sieht es so aus e=elem, als würde der Typ Int-> Bool abgeleitet, sodass er nicht kompiliert wurde, als ich e für nicht ganzzahlige elem-Aufrufe verwendete. Ich versuche herauszufinden, warum was war. Danke für den Tipp auf den Plätzen!
Vroomfondel
Ah, du hast recht. Haskell hat manchmal Probleme, polymorphe Typen abzuleiten - ich bin mir nicht sicher, ob es eine einfache Lösung gibt, abgesehen vom Hinzufügen der Flagge für flexible Typen
Julian Wolf
1
h#t=let[...]in[...]kann auf gekürzt werden h#t|let[...]=[...]. Auch head nist n!!0. Bei einer Wache &&kann das einfach sein ,.
Laikoni