Wybierz ostatnią kartę w pokerze

31

Ręce pokerowe są uszeregowane od najlepszego do najgorszego w następujący sposób:

  1. Straight flush - pięć kart o kolejności rangowej, wszystkie w tym samym kolorze
  2. Kareta - cztery karty o tej samej wartości i jedna karta o innej wartości
  3. Full house - trzy karty jednej rangi i dwie karty innej rangi
  4. Kolor - pięć kart tego samego koloru
  5. Prosto - pięć kart o kolejności rangowej
  6. Trójka - trzy karty o tej samej wartości i dwie karty dwóch innych stopni
  7. Dwie pary - dwie karty o tej samej wartości, dwie karty o innej wartości i jedna karta o trzeciej wartości
  8. Jedna para - dwie karty o tej samej wartości i trzy karty z trzech innych stopni
  9. Wysoka karta - pięć kart nie wszystkie o kolejności sekwencyjnej lub o tym samym kolorze i żadna z nich nie ma tej samej wartości

  • Ranga = liczba na karcie (A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2). Możesz wybrać T zamiast 10.
  • Kolor = kier (h), pik (y), trefl (c) i diamenty (d).

Zauważ, że As,, Amoże być zarówno najwyższą, jak i najniższą liczbą (1 lub 14).

Kartę można rozpoznać po dwóch literach As(as pik), Jc(walet trefl), 7h(7 kier) i tak dalej.


Wyzwanie:

Dostajesz cztery karty od rozdającego (cztery ciągi wejściowe). Znajdź i wydrukuj najlepszą możliwą ostatnią kartę, jaką możesz uzyskać.

Jeśli są karty, które są równie dobre, możesz wybrać, które wybrać.

Formaty wejściowe i wyjściowe są opcjonalne, ale poszczególne karty muszą być identyfikowane jak pokazano powyżej Jci 2h.


Przypadki testowe:

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)

To jest kod golfowy, więc wygrywa najkrótsza przesyłka w bajtach.

Stewie Griffin
źródło

Odpowiedzi:

13

Pyth, 73 bajty

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

To jest okropne. Analizowanie kart, sortowanie wartości, ... Wszystko wymaga tak wielu znaków. Ale podejście jest interesujące.

Wypróbuj online: pakiet demonstracyjny lub testowy

Wyjaśnienie:

Generuję wszystkie 52 karty, usuwam cztery karty wejściowe, generuję wynik dla każdej karty (wynik ręki) i drukuję kartę z maksymalnym wynikiem.

Wynik jest trochę dziwny. Jeśli porównam wynik dwóch całkowicie różnych rąk, może wybrać niewłaściwego zwycięzcę. Np. Strit pokonałby 4 asy. Ale to działa, jeśli pierwsze 4 karty są takie same w obu rękach. A mój obliczony wynik w rzeczywistości nie jest wartością, ale listą wartości:

  • G: Najpierw grupuję 5 kart według rangi i przyjmuję długości: 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F: Następnie dołączam 4 minus liczbę różnych pakietów do tej listy. Flush -> 3dołącza się,not flush -> 2/1/0 dołącza się.
  • S: Dodaj kolejny numer. 0jeśli nie jest to prosta, 4jeśli jest to prosta A2345lub 5jeśli jest to prosta wyższa.

Te listy 4-7 liczb są sortowane w malejącej kolejności i wybierana jest lista o maksymalnej wartości.

Dlaczego to działa? Tutaj możesz zobaczyć możliwe konfiguracje dla wszystkich typów. Litera obok cyfr informuje, z jaką zasadą wygenerowano ten numer.

  • Poker: [5S, 3F, 1G, 1G, 1G, 1G, 1G] lub[4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • Czterech z gatunku: [4G, 1G, 0F, 0S]
  • Pełen dom: [3G, 2G, 1F, 0S] lub[3G, 2G, 0F, 0S]
  • Spłukać: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • Prosto: [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]
  • Trzy z rodzaju: [3G, 1G, 1G, 1F, 0S] ,[3G, 1G, 1G, 0F, 0S]
  • Dwie pary: [2G, 2G, 2F, 1G, 0S],[2G, 2G, 1F, 1G, 0S] ,[2G, 2G, 1G, 0F, 0S]
  • Jedna para: [2G, 2F, 1G, 1G, 1G, 0S],[2G, 1G, 1G, 1G, 1F, 0S] ,[2G, 1G, 1G, 1G, 0F, 0S]
  • Wysoka karta: [2F, 1G, 1G, 1G, 1G, 1G, 0S], [1F, 1G, 1G, 1G, 1G, 1G, 0S],[1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pyth porównuje listy pod względem elementów. Jest więc oczywiste, że strit zawsze pokona Kareta. Większość typowych zasad pokera jest oczywistych w przypadku tych list. Niektóre wydają się sprzeczne.

  • Straight wygra z Czwórką lub Fletem: żaden problem. Jeśli masz szansę na uzyskanie Karety / Fula z kartą na riverze, to nie możesz jednocześnie osiągnąć strita (ponieważ masz już 2 lub 3 różne zestawy na ręce).
  • Straight wygra przeciwko kolorowi. Jeśli możesz uzyskać kolor i strita z kartą na riverze, to możesz także osiągnąć kolor. A strit ma lepszy wynik niż strit i kolor.
  • Jedna para [2G, 2F, 1G, 1G, 1G, 0S]wygra przeciwko dwóm parom rąk. Również nie ma problemu. Jeśli otrzymujesz dwie pary z kartą na riverze, to zanim miałeś przynajmniej jedną parę na riverze. Ale to oznacza, że ​​możesz poprawić do trójki, co jest lepsze. Tak więc dwie pary nigdy nie będą odpowiedzią.
  • Wysoka karta [2F, 1G, 1G, 1G, 1G, 1G, 0S]wygrywa z jedną parą rąk. Jeśli jest to najlepszy wynik, jaki możesz osiągnąć, przed rzeką będziesz mieć 3 karty jednego zestawu i jedną kartę innego zestawu. Ale wtedy możesz wybrać kartę z jednym z tych dwóch pakietów i wartością, która już się pojawi, a skończysz na wyniku [2F, 2G, ...], który również jest lepszy.

To wybiera odpowiedni rodzaj rozwiązania. Ale jak uzyskać najlepszą jedną parę (spośród 4 możliwości), jak wybrać najlepszą strit, ...? Ponieważ dwa różne rozwiązania z jedną parą mogą mieć ten sam wynik.

To łatwe. Pyth gwarantuje stabilne sortowanie (przy maksimum). Więc po prostu generuję karty w kolejności 2h 2s 2c 2d 3h 3s ... Ad. Karta o najwyższej wartości automatycznie będzie więc wartością maksymalną.

Szczegóły dotyczące wdrożenia

=Zcdzieli ciąg wejściowy i przechowuje listę kart Z. =T+`M}2Tc4"JQKA"generuje listę rang ['2', ..., '10', 'J', 'Q', 'K', 'A']i przechowuje je w T. -sM*T..."hscd"Zgeneruje każdą kombinację rangi z pakietami i usuwa karty Z.

o...porządkuje pozostałe karty według: lM.gPkJdługości grup rang, +-4l{eMJlMdołącza 4 - długości (zestawy), +*-5l@\AN}SPMJ+NZSM.:+\AT5dodaje 0/4/5 w zależności od zestawu (generuj każdy podciąg o długości 5 „A” + T, sprawdź, czy ręka jeden z nich (wymaga sortowania ręki i wszystkich podzbiorów), pomnóż przez 5 - liczbę „A” na karcie), _Ssortowanie listy maleje.

e wybierz maksimum i wydrukuj.

Jakube
źródło
2
Bardzo kreatywne i świetne wyjaśnienie!
Greg Martin
4

JavaScript (ES6), 329 324 317 312 309 bajtów

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

Jak to działa

Dla każdej pozostałej karty w talii obliczamy wynik rozdania S. Im niższy wynik, tym lepsza ręka.

Zmienne używane do obliczania wyniku

  • F: fałsz, jeśli ręka jest koloru
  • c: maska ​​bitowa klubów
  • d: maska ​​bitowa diamentów
  • h: maska ​​bitowa Kier
  • s: maska ​​bitowa pik
  • x = c | d: maska ​​bitowa trefl lub karo
  • y = h | s: maska ​​bitowa kier lub pik
  • a: maska ​​bitowa wszystkich połączonych kolorów
  • p = c & d | x & y | h & s: parowanie maski bitowej (1)
  • t = c & d & y | h & s & x: trzyosobowa maska ​​bitowa (1)

(1) Napisałem te formuły kilka lat temu i użyłem ich w kilku silnikach pokerowych. Oni pracują. :-)

Inne formuły

  • c & d & h & s: czteroosobowa maska ​​bitowa
  • a == 7681: test na specjalną prostą „A, 2, 3, 4, 5” (0b1111000000001)
  • ((j = a / 31) & -j) == j: test na wszystkie inne proste

Tabela wyników

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

Uwaga: nie musimy przejmować się dwiema parami, które nie mogą być naszą najlepszą opcją. (Jeśli mamy już jedną parę, możemy zamienić ją w trójkę. A jeśli mamy już dwie pary, możemy zamienić je w Full House.)

Przypadki testowe

Arnauld
źródło
3

JavaScript (ES6), 307 349

Jest to dość nieporęczne i nie jestem pewien, czy to najlepsze podejście. Może jeszcze trochę golfa.

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)

Mniej golfa

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
)

Test

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
źródło
Zabawne, że nasze oba podejścia wydają się zbliżać do bardzo podobnych rozmiarów. :-) Jeśli chodzi o wydajność, jesteś zdecydowanie szybszy.
Arnauld,
@Arnauld Udało mi się ogolić jeszcze 4 bajty. Twoja kolej
edc65