Wählen Sie die letzte Karte in einer Pokerhand

31

Pokerhände werden wie folgt vom Besten zum Schlechtesten gewertet:

  1. Straight Flush - fünf aufeinanderfolgende Karten mit derselben Farbe
  2. Vier Gleiche - vier Karten desselben Ranges und eine Karte eines anderen Ranges
  3. Full House - drei Karten eines Ranges und zwei Karten eines anderen Ranges
  4. Flush - fünf Karten mit derselben Farbe
  5. Straight - Fünf aufeinanderfolgende Karten
  6. Drei Gleiche - drei Karten des gleichen Ranges und zwei Karten von zwei anderen Rängen
  7. Zwei Paare - zwei Karten desselben Ranges, zwei Karten eines anderen Ranges und eine Karte eines dritten Ranges
  8. Ein Paar - zwei Karten des gleichen Ranges und drei Karten von drei anderen Rängen
  9. Hohe Karte - fünf Karten, die nicht alle den gleichen Rang oder die gleiche Farbe haben und von denen keine den gleichen Rang haben

  • Rang = Die Nummer auf der Karte (A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2). Sie können T anstelle von 10 verwenden.
  • Farbe = Herz (h), Pik (s), Kreuz (c) und Karo (d).

Beachten Sie, dass das Ass Asowohl die höchste als auch die niedrigste Zahl sein kann (1 oder 14).

Eine Karte kann durch zwei Buchstaben As(Pik-As), Jc( Kreuz- Bube), 7h(Herz-7) usw. identifiziert werden .


Herausforderung:

Sie erhalten vom Geber vier Karten (vier Eingangsstrings). Finde und gib die bestmögliche letzte Karte aus, die du bekommen kannst.

Wenn es Karten gibt, die gleich gut sind, können Sie auswählen, welche Sie auswählen möchten.

Eingabe- und Ausgabeformate sind optional, die einzelnen Karten müssen jedoch wie oben Jcund gezeigt gekennzeichnet sein 2h.


Testfälle:

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)

Dies ist Codegolf, daher gewinnt die kürzeste Einsendung in Bytes.

Stewie Griffin
quelle

Antworten:

13

Pyth, 73 Bytes

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

Das ist ziemlich schrecklich. Karten analysieren, Werte sortieren, ... Alles braucht so viele Zeichen. Aber der Ansatz ist interessant.

Probieren Sie es online aus: Demo oder Test Suite

Erläuterung:

Ich generiere alle 52 Karten, entferne die vier Karten von der Eingabe, generiere eine Punktzahl für jede Karte (Punktzahl der Hand) und drucke die Karte mit der maximalen Punktzahl aus.

Die Partitur ist etwas merkwürdig. Wenn ich die Punktzahl zweier völlig unterschiedlicher Hände vergleiche, kann es sein, dass der falsche Gewinner ausgewählt wird. Zum Beispiel würde eine Straße 4 Asse schlagen. Aber es funktioniert, wenn die ersten 4 Karten in beiden Händen gleich sind. Und meine berechnete Punktzahl ist eigentlich kein Wert, sondern eine Liste von Werten:

  • G: Zuerst gruppiere ich die 5 Karten nach Rang und nehme die Längen: 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F: Dann hänge ich 4 minus der Anzahl der verschiedenen Suiten an diese Liste an. Flush -> 3wird angehängt, not flush -> 2/1/0wird angehängt.
  • S: Fügen Sie eine weitere Nummer hinzu. 0Wenn es keine Gerade ist, 4wenn es die Gerade A2345ist oder 5wenn es eine höhere Gerade ist.

Diese Listen mit 4 bis 7 Zahlen werden in absteigender Reihenfolge sortiert und die Liste mit dem Maximalwert wird ausgewählt.

Warum funktioniert das? Hier sehen Sie die möglichen Konfigurationen für alle Typen. Der Buchstabe neben den Zahlen gibt an, mit welcher Regel diese Nummer generiert wurde.

  • Straight Flush: [5S, 3F, 1G, 1G, 1G, 1G, 1G]oder[4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • Vier von einer Sorte: [4G, 1G, 0F, 0S]
  • Volles Haus: [3G, 2G, 1F, 0S]oder[3G, 2G, 0F, 0S]
  • Spülen: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • Straight: [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]
  • Drei einer Art: [3G, 1G, 1G, 1F, 0S],[3G, 1G, 1G, 0F, 0S]
  • Zwei Paare: [2G, 2G, 2F, 1G, 0S], [2G, 2G, 1F, 1G, 0S],[2G, 2G, 1G, 0F, 0S]
  • Ein Paar: [2G, 2F, 1G, 1G, 1G, 0S], [2G, 1G, 1G, 1G, 1F, 0S],[2G, 1G, 1G, 1G, 0F, 0S]
  • Hohe Karte: [2F, 1G, 1G, 1G, 1G, 1G, 0S], [1F, 1G, 1G, 1G, 1G, 1G, 0S],[1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pyth vergleicht Listen elementweise. Es ist also klar, dass ein Straight Flush immer einen Vierling schlagen wird. Die meisten typischen Pokerregeln sind bei diesen Listen offensichtlich. Einige scheinen widersprüchlich.

  • Eine Straße gewinnt gegen einen Vierling oder ein Full House: Kein Problem. Wenn Sie die Chance haben, ein Vierling / Full House mit der River Card zu erhalten, können Sie nicht gleichzeitig eine Straße erreichen (da Sie bereits 2 oder 3 verschiedene Suiten auf der Hand haben).
  • Ein Straight gewinnt gegen einen Flush. Wenn Sie einen Flush und eine Straße mit der River-Karte erreichen können, können Sie auch einen geraden Flush erreichen. Und der Straight Flush hat eine bessere Punktzahl als der Straight und der Flush.
  • Ein Paar [2G, 2F, 1G, 1G, 1G, 0S]gewinnt gegen zwei Paarhände. Auch kein problem. Wenn Sie mit der River-Karte ein Paar mit zwei Karten erhalten, hatten Sie mindestens ein Paar vor dem River. Das bedeutet aber, dass Sie sich zu einem Dreier verbessern können, was besser ist. Ein Zwei-Paar wird also niemals die Antwort sein.
  • Hohe Karte [2F, 1G, 1G, 1G, 1G, 1G, 0S]gewinnt gegen ein Paar Hände. Wenn dies die beste Punktzahl ist, die Sie erreichen können, haben Sie vor dem Fluss 3 Karten einer Suite und eine Karte einer anderen Suite. Aber dann können Sie die Karte mit einer dieser beiden Suiten und mit einem Wert auswählen, der bereits angezeigt wird, und am Ende erhalten Sie die Punktzahl [2F, 2G, ...], die auch besser ist.

Dies wählt also den richtigen Lösungstyp. Aber wie bekomme ich das beste Paar (aus 4 Möglichkeiten), wie wähle ich die beste Straße, ...? Weil zwei verschiedene Ein-Paar-Lösungen die gleiche Punktzahl haben können.

Das ist einfach. Pyth garantiert eine stabile Sortierung (bei maximaler Ausnutzung). Also erstelle ich einfach die Karten in der Reihenfolge 2h 2s 2c 2d 3h 3s ... Ad. Die Karte mit dem höchsten Wert ist also automatisch das Maximum.

Implementierungsdetails

=ZcTeilt die Eingabezeichenfolge und speichert die Kartenliste in Z. =T+`M}2Tc4"JQKA"generiert die Rangliste ['2', ..., '10', 'J', 'Q', 'K', 'A']und speichert sie in T. -sM*T..."hscd"Zgeneriert jede Rangkombination mit den Suiten und entfernt die Karten von Z.

o...ordnet diese verbleibenden Karten nach: lM.gPkJder Länge der Gruppen der Ränge, +-4l{eMJlMhängt 4 - Länge ( Reihen ) an, +*-5l@\AN}SPMJ+NZSM.:+\AT5hängt 0/4/5 an, abhängig von der Reihe (erzeugt jede Teilfolge der Länge 5 von "A" + T, prüft, ob die Hand Einer von ihnen (Sortierung der Hand und Sortierung aller Teilmengen erforderlich), multipliziert mit 5 (Anzahl der "A" auf der Karte), _Ssortiert die Liste in absteigender Reihenfolge.

e wähle das Maximum und drucke.

Jakube
quelle
2
Sehr kreativ und tolle Erklärung!
Greg Martin
4

JavaScript (ES6), 329 324 317 312 309 Bytes

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

Wie es funktioniert

Für jede verbleibende Karte im Stapel berechnen wir eine Handwertung S. Je niedriger die Punktzahl, desto besser die Hand.

Variablen, die zur Berechnung der Punktzahl verwendet werden

  • F: falsch, wenn die Hand ein Flush ist
  • c: Bitmaske von Clubs
  • d: Bitmaske von Diamanten
  • h: Bitmaske der Herzen
  • s: Pik-Bitmaske
  • x = c | d: Bitmaske von Clubs oder Diamanten
  • y = h | s: Bitmaske der Herzen ODER Pik
  • a: Bitmaske aller Kombianzüge
  • p = c & d | x & y | h & s: Paarbitmaske (1)
  • t = c & d & y | h & s & x: Dreierbitmaske (1)

(1) Ich habe diese Formeln vor einigen Jahren geschrieben und sie in mehreren Poker-Engines verwendet. Sie arbeiten. :-)

Andere Formeln

  • c & d & h & s: Vier einer Art Bitmaske
  • a == 7681: Test für die Sondergerade "A, 2, 3, 4, 5" (0b1111000000001)
  • ((j = a / 31) & -j) == j: Test für alle anderen Geraden

Score-Diagramm

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: Wir müssen uns nicht um Zwei-Paare kümmern, was möglicherweise nicht unsere beste Option sein kann. (Wenn wir bereits ein Paar haben, können wir daraus einen Dreier machen. Und wenn wir bereits zwei Paare haben, können wir sie in ein Full House verwandeln.)

Testfälle

Arnauld
quelle
3

JavaScript (ES6), 307 349

Das ist ziemlich sperrig und ich bin mir nicht sicher, ob es der beste Ansatz ist. Vielleicht noch ein bisschen Golf.

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)

Weniger golfen

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
)

Prüfung

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>

edc65
quelle
Es ist lustig zu sehen, dass unsere beiden Ansätze sich sehr ähnlichen Größen anzunähern scheinen. :-) Was die Leistung angeht, bist du definitiv schneller.
Arnauld
@Arnauld Ich habe es geschafft, noch 4 Bytes zu rasieren. Sie sind dran
edc65