Elige la última carta en una mano de póker


31

Las manos de póker se clasifican de mejor a peor de la siguiente manera:

  1. Escalera de color: cinco cartas de rango secuencial, todas del mismo palo
  2. Cuatro de un tipo: cuatro cartas del mismo rango y una carta de otro rango
  3. Casa llena: tres cartas de un rango y dos cartas de otro rango
  4. Flush: cinco cartas del mismo palo
  5. Recto: cinco cartas de rango secuencial
  6. Tres de un tipo: tres cartas del mismo rango y dos cartas de otros dos rangos
  7. Dos pares: dos cartas del mismo rango, dos cartas de otro rango y una carta de un tercer rango
  8. Un par: dos cartas del mismo rango y tres cartas de otros tres rangos
  9. Carta alta: cinco cartas no todas de rango secuencial o del mismo palo, y ninguna de las cuales es del mismo rango

  • Rango = El número en la tarjeta (A, K, Q, J, 10, 9, 8, 7, 6, 5, 4, 3, 2). Puedes elegir usar T en lugar de 10.
  • Traje = corazones (h), picas (s), tréboles (c) y diamantes (d).

Tenga en cuenta que el As, Apuede ser el número más alto y el más bajo (1 o 14).

Una tarjeta se puede identificar con dos letras As(As de picas), Jc(Jota de garrotes), 7h(7 de corazones) y así sucesivamente.


Reto:

Obtienes cuatro cartas del crupier (cuatro cadenas de entrada). Encuentre y envíe la mejor última carta posible que pueda obtener.

Si hay cartas que son igualmente buenas, entonces puedes elegir cuál elegir.

Los formatos de entrada y salida son opcionales, pero las tarjetas individuales deben identificarse como se muestra arriba Jcy 2h.


Casos de prueba:

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)

Este es el código de golf, por lo que gana el envío más corto en bytes.

Respuestas:


13

Pyth, 73 bytes

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

Esto es bastante terrible. Analizando tarjetas, ordenando los valores, ... Todo toma tantos caracteres. Pero el enfoque es interesante.

Pruébelo en línea: Demostración o conjunto de pruebas

Explicación:

Genero las 52 cartas, elimino las cuatro cartas de la entrada, genero un puntaje para cada carta (puntaje de la mano) e imprimo la carta con el puntaje máximo.

El puntaje es un poco extraño. Si comparo el puntaje de dos manos completamente diferentes, puede elegir al ganador equivocado. Por ejemplo, una escalera vencería a 4 ases. Pero funciona, si las primeras 4 cartas son iguales en ambas manos. Y mi puntaje calculado no es en realidad un valor, sino una lista de valores:

  • G: Primero, agrupo las 5 cartas por rango y tomo las longitudes: 5h 5d 6c 5s Jd -> [3, 1, 1]
  • F: Luego agrego 4 menos el número de suites diferentes a esta lista. Flush -> 3se agrega, not flush -> 2/1/0se agrega.
  • S: agrega otro número. 0si no es una recta, 4si es la recta A2345o 5si es una recta más alta.

Estas listas de 4 a 7 números se ordenan en orden decreciente y se elige la lista con el valor máximo.

¿Por qué funciona esto? Aquí puede ver las configuraciones posibles para todos los tipos. La letra junto a los números le indica con qué regla se generó este número.

  • Escalera de color: [5S, 3F, 1G, 1G, 1G, 1G, 1G]o[4S, 3F, 1G, 1G, 1G, 1G, 1G]
  • Cuatro de un tipo: [4G, 1G, 0F, 0S]
  • Casa llena: [3G, 2G, 1F, 0S]o[3G, 2G, 0F, 0S]
  • Rubor: [3F, 1G, 1G, 1G, 1G, 1G, 0S]
  • Recto: [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]
  • Tres de una clase: [3G, 1G, 1G, 1F, 0S],[3G, 1G, 1G, 0F, 0S]
  • Dos pares: [2G, 2G, 2F, 1G, 0S], [2G, 2G, 1F, 1G, 0S],[2G, 2G, 1G, 0F, 0S]
  • Un par: [2G, 2F, 1G, 1G, 1G, 0S], [2G, 1G, 1G, 1G, 1F, 0S],[2G, 1G, 1G, 1G, 0F, 0S]
  • Carta alta: [2F, 1G, 1G, 1G, 1G, 1G, 0S], [1F, 1G, 1G, 1G, 1G, 1G, 0S],[1G, 1G, 1G, 1G, 1G, 0S, 0F]

Pyth compara listas de elementos sabios. Por lo tanto, es obvio que una escalera de color siempre superará a Cuatro de un tipo. La mayoría de las reglas típicas de póker son obvias con estas listas. Algunos parecen conflictivos.

  • Un Straight ganará contra Four of a kind o Full house: no hay problema. Si tienes la oportunidad de obtener Cuatro de un tipo / Casa completa con la carta de river, entonces no puedes alcanzar una escalera al mismo tiempo (ya que ya tienes 2 o 3 suites diferentes en tu mano).
  • Un Straight ganará contra un color. Si puedes alcanzar un color y una escalera con la carta de river, entonces también puedes alcanzar un color directo. Y la escalera de color tiene una mejor puntuación que la escalera y el color.
  • Un par [2G, 2F, 1G, 1G, 1G, 0S]ganará contra unas manos de dos pares. Además no hay problema. Si obtienes un par de dos con la carta de river, tienes al menos un par antes del river. Pero esto significa que puede mejorar a tres de un tipo, lo cual es mejor. Entonces, un par de dos nunca será la respuesta.
  • La carta alta [2F, 1G, 1G, 1G, 1G, 1G, 0S]ganará contra un par de manos. Si este es el mejor puntaje que puedes alcanzar, antes del river tendrás 3 cartas de una suite y una carta de una suite diferente. Pero luego puede elegir la tarjeta con una de estas dos suites y con un valor que ya aparece, y terminará con la puntuación [2F, 2G, ...], que también es mejor.

Entonces esto elige el tipo correcto de solución. Pero, ¿cómo obtengo el mejor par (de 4 posibilidades), cómo elijo la mejor escalera, ...? Porque dos soluciones diferentes de un par pueden tener el mismo puntaje.

Eso es fácil. Pyth garantiza una clasificación estable (cuando se toma el máximo). Así que simplemente genero las tarjetas en el orden 2h 2s 2c 2d 3h 3s ... Ad. Entonces la tarjeta con el valor más alto será automáticamente el máximo.

Detalles de implementacion

=Zcdivide la cadena de entrada y almacena la lista de tarjetas en Z. =T+`M}2Tc4"JQKA"genera la lista de rangos ['2', ..., '10', 'J', 'Q', 'K', 'A']y los almacena T. -sM*T..."hscd"Zgenera cada combinación de rango con las suites y elimina las cartas de Z.

o...ordena estas cartas restantes por: lM.gPkJla longitud de los grupos de los rangos, +-4l{eMJlMagrega 4 - longitud (suites), +*-5l@\AN}SPMJ+NZSM.:+\AT5agrega 0/4/5 dependiendo de la suite (genera cada subcadena de longitud 5 de "A" + T, verifica si la mano uno de ellos (requiere ordenar la mano y ordenar todos los subconjuntos), multiplicar por 5 - número de "A" en la tarjeta), _Sordena que la lista disminuya.

e elija el máximo e imprima.


2
Muy creativo, y una gran explicación!
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

Cómo funciona

Para cada carta restante en el mazo, calculamos una puntuación de mano S. Cuanto más bajo sea el puntaje, mejor será la mano.

Variables utilizadas para calcular la puntuación

  • F: falso si la mano está al ras
  • c: máscara de bits de clubes
  • d: máscara de bits de diamantes
  • h: máscara de bits de corazones
  • s: máscara de bits de espadas
  • x = c | d: máscara de bits de clubes o diamantes
  • y = h | s: máscara de bits de corazones o espadas
  • a: máscara de bits de todos los trajes combinados
  • p = c & d | x & y | h & s: par de máscara de bits (1)
  • t = c & d & y | h & s & x: tres de una especie de máscara de bits (1)

(1) Escribí estas fórmulas hace algunos años y las usé en varios motores de póker. Ellos trabajan :-)

Otras fórmulas

  • c & d & h & s: cuatro de una especie de máscara de bits
  • a == 7681: prueba para la recta especial "A, 2, 3, 4, 5" (0b1111000000001)
  • ((j = a / 31) & -j) == j: prueba para todas las demás rectas

Tabla de puntuación

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: No tenemos que preocuparnos por Two-Pair que posiblemente no sea nuestra mejor opción. (Si ya tenemos un par, podemos convertirlo en un Three of a Kind. Y si ya tenemos dos pares, podemos convertirlos en Full House).

Casos de prueba


3

JavaScript (ES6), 307349

Esto es bastante voluminoso y no estoy seguro de que sea el mejor enfoque. Todavía un poco golfable quizás.

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)

Menos 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
)

Prueba

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>


Es divertido ver que nuestros dos enfoques parecen converger hacia tamaños muy similares. :-) En cuanto al rendimiento, definitivamente eres más rápido.
Arnauld

@Arnauld Me las arreglé para afeitar unos 4 bytes más. Tu turno
edc65
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.