Scegli l'ultima carta in una mano di poker


31

Le mani di poker sono classificate dalla migliore alla peggiore come segue:

  1. Scala reale - cinque carte di valore sequenziale, tutte dello stesso seme
  2. Quadrato: quattro carte dello stesso valore e una carta di un altro valore
  3. Full: tre carte di un valore e due di un altro valore
  4. Colore: cinque carte dello stesso seme
  5. Scala - cinque carte di valore sequenziale
  6. Tris: tre carte dello stesso valore e due carte di altri due gradi
  7. Due coppie: due carte dello stesso valore, due carte di un altro valore e una carta di un terzo valore
  8. Una coppia: due carte dello stesso valore e tre carte di altri tre gradi
  9. Carta alta - cinque carte non tutte di valore sequenziale o dello stesso seme e nessuna delle quali ha lo stesso valore

  • Rango = il numero sulla carta (A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2). Puoi scegliere di usare T invece di 10.
  • Suit = cuori (h), picche (s), fiori (c) e quadri (d).

Nota che l'asso Apuò essere sia il numero più alto che il numero più basso (1 o 14).

Una carta può essere identificata da due lettere As(Asso di picche), Jc(Jack di fiori), 7h(7 di cuori) e così via.


Sfida:

Ottieni quattro carte dal banco (quattro stringhe di input). Trova ed emetti l'ultima carta migliore che puoi ottenere.

Se ci sono carte ugualmente valide, puoi scegliere quale scegliere.

I formati di input e output sono opzionali, ma le singole schede devono essere identificate come mostrato sopra Jce 2h.


Casi test:

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)

Questo è il golf del codice, quindi vince l'invio più breve in byte.

Risposte:


13

Pyth, 73 byte

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

Questo è piuttosto terribile. Analizzare le carte, ordinare i valori, ... Tutto richiede così tanti caratteri. Ma l'approccio è interessante.

Provalo online: Dimostrazione o Test Suite

Spiegazione:

Genero tutte le 52 carte, rimuovo le quattro carte dell'input, generi un punteggio per ogni carta (punteggio della mano) e stampo la carta con il punteggio massimo.

Il punteggio è un po 'strano. Se metto a confronto il punteggio di due mani completamente diverse, potrebbe scegliere il vincitore sbagliato. Ad esempio una scala avrebbe battuto 4 assi. Ma funziona, se le prime 4 carte sono uguali in entrambe le mani. E il mio punteggio calcolato non è in realtà un valore, ma un elenco di valori:

  • G: Per prima cosa raggruppo le 5 carte per valore e prendo le lunghezze: 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F: Quindi aggiungo 4 meno il numero di diverse suite a questo elenco. Flush -> 3viene aggiunto, not flush -> 2/1/0viene aggiunto.
  • S: Aggiungi un altro numero. 0se non è una scala, 4se è la scala A2345o 5se è una scala più alta.

Questi elenchi di 4-7 numeri vengono ordinati in ordine decrescente e viene selezionato l'elenco con il valore massimo.

Perché funziona? Qui puoi vedere le possibili configurazioni per tutti i tipi. La lettera accanto ai numeri ti dice con quale regola è stato generato questo numero.

  • Scala reale: [5S, 3F, 1G, 1G, 1G, 1G, 1G]o[4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • Quattro nel suo genere: [4G, 1G, 0F, 0S]
  • Full: [3G, 2G, 1F, 0S]o[3G, 2G, 0F, 0S]
  • Flush: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • Scala: [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]
  • Tris: [3G, 1G, 1G, 1F, 0S],[3G, 1G, 1G, 0F, 0S]
  • Doppia coppia: [2G, 2G, 2F, 1G, 0S], [2G, 2G, 1F, 1G, 0S],[2G, 2G, 1G, 0F, 0S]
  • Una coppia: [2G, 2F, 1G, 1G, 1G, 0S], [2G, 1G, 1G, 1G, 1F, 0S],[2G, 1G, 1G, 1G, 0F, 0S]
  • Alta carta: [2F, 1G, 1G, 1G, 1G, 1G, 0S], [1F, 1G, 1G, 1G, 1G, 1G, 0S],[1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pyth confronta gli elenchi in termini di elementi. Quindi è ovvio che una scala reale sconfigge sempre Four of a kind. La maggior parte delle regole tipiche del poker sono ovvie con queste liste. Alcuni sembrano contrastanti.

  • Una scala vincerà contro il quattro di un tipo o un full: nessun problema. Se hai la possibilità di ottenere Four of a kind / Full con la carta river, allora non puoi raggiungere una scala allo stesso tempo (dato che hai già 2 o 3 suite diverse in mano).
  • Una scala vincerà contro una scala. Se riesci a raggiungere una scala e una scala con la carta river, allora puoi anche raggiungere una scala reale. E la scala reale ha un punteggio migliore sia della scala che della scala.
  • Una coppia [2G, 2F, 1G, 1G, 1G, 0S]vincerà contro alcune mani di due coppie. Inoltre nessun problema. Se ottieni una doppia coppia con la carta river, allora hai avuto almeno una coppia prima del river. Ma questo significa che puoi migliorare a tre nel suo genere, il che è meglio. Quindi una doppia coppia non sarà mai la risposta.
  • La carta alta [2F, 1G, 1G, 1G, 1G, 1G, 0S]vincerà contro alcune mani di una coppia. Se questo è il miglior punteggio che puoi raggiungere, prima del river avrai 3 carte di una suite e una di un'altra suite. Ma poi puoi scegliere la carta con una di queste due suite e con un valore che appare già, e finirai con il punteggio [2F, 2G, ...], che è anche migliore.

Quindi questo sceglie il tipo corretto di soluzione. Ma come posso ottenere la migliore coppia (su 4 possibilità), come posso scegliere la scala migliore, ...? Perché due diverse soluzioni a una coppia possono avere lo stesso punteggio.

Questo è facile. Pyth garantisce un ordinamento stabile (quando si prende il massimo). Quindi ho semplicemente generato le carte nell'ordine 2h 2s 2c 2d 3h 3s ... Ad. Quindi la carta con il valore più alto sarà automaticamente il massimo.

Dettagli di implementazione

=Zcdivide la stringa di input e memorizza l'elenco delle carte Z. =T+`M}2Tc4"JQKA"genera l'elenco dei ranghi ['2', ..., '10', 'J', 'Q', 'K', 'A']e li memorizza in T. -sM*T..."hscd"Zgenera ogni combinazione di rango con le suite e rimuove le carte di Z.

o...ordina queste carte rimanenti per: lM.gPkJla lunghezza dei gruppi dei ranghi, +-4l{eMJlMaggiunge 4 - lunghezza (suite), +*-5l@\AN}SPMJ+NZSM.:+\AT5aggiunge 0/4/5 a seconda della suite (genera ogni sottostringa di lunghezza 5 di "A" + T, controlla se la mano uno di questi (richiede l'ordinamento della mano e l'ordinamento di tutti i sottoinsiemi), moltiplicato per 5 - numero di "A" nella carta), _Sordina l'elenco in ordine decrescente.

e scegli il massimo e stampa.


2
Spiegazione molto creativa e fantastica!
Greg Martin,

4

JavaScript (ES6), 329 324 317 312 309 byte

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

Come funziona

Per ogni carta rimanente nel mazzo, calcoliamo un punteggio di mano S. Più basso è il punteggio, migliore è la mano.

Variabili utilizzate per calcolare il punteggio

  • F: falsa se la mano è a filo
  • c: maschera di bit di fiori
  • d: maschera di bit di diamanti
  • h: maschera di bit di Hearts
  • s: maschera di bit di picche
  • x = c | d: maschera di bit di fiori o quadri
  • y = h | s: maschera di bit di Hearts O Spades
  • a: maschera di bit di tutti i semi combinati
  • p = c & d | x & y | h & s: pair bitmask (1)
  • t = c & d & y | h & s & x: maschera a tre bit (1)

(1) Ho scritto queste formule alcuni anni fa e le ho usate in diversi motori di poker. Funzionano. :-)

Altre formule

  • c & d & h & s: una maschera di bit quattro
  • a == 7681: test per il rettilineo speciale "A, 2, 3, 4, 5" (0b1111000000001)
  • ((j = a / 31) & -j) == j: test per tutti gli altri rettilinei

Tabella dei punteggi

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: Non dobbiamo preoccuparci della doppia coppia che non può essere la nostra migliore opzione. (Se abbiamo già una coppia, possiamo trasformarlo in un tris. E se abbiamo già due coppie, possiamo trasformarli in un full).

Casi test


3

JavaScript (ES6), 307 349

Questo è piuttosto voluminoso e non sono sicuro che sia l'approccio migliore. Forse ancora un po 'golfabile.

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)

Meno golf

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>


È divertente vedere che entrambi i nostri approcci sembrano convergere verso dimensioni molto simili. :-) Per quanto riguarda le prestazioni, sei decisamente più veloce, però.
Arnauld,

@Arnauld Sono riuscito a radere altri 4 byte. Il tuo turno
edc65
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.