Nada como un buen juego antiguo de ModTen

27

Descargo de responsabilidad: ModTen es un juego de cartas de ficción creado con el único propósito de este desafío.

Las reglas de ModTen

ModTen se juega con una baraja estándar de 52 cartas. Debido a que las reglas completas aún no se han inventado, nos vamos a centrar exclusivamente en la clasificación de manos.

Jack & Three, adecuado

Una mano ganadora en ModTen. Gráficos de Wikipedia .

Valores de la tarjeta

Las tarjetas tienen los siguientes valores:

  • 2 a 9 : vale su valor nominal
  • Diez : 0 puntos
  • Jack : 3 puntos
  • Reina o Rey : 8 puntos
  • As : 9 puntos

Valores de la mano

  • Una mano ModTen está hecha de dos cartas . El valor base de una mano se obtiene multiplicando el valor de ambas cartas y manteniendo solo el último dígito (es decir, aplicando un módulo 10).

    6(7×8)mod10=6 .

  • La única otra regla en ModTen es que las cartas adecuadas valen más que las no adecuadas. Por convención, vamos a agregar una "s" al valor si ambas cartas son del mismo palo.

    Por ejemplo, el valor de 9 ♠ - 5 ♠ se anotará como " 5s ", porque (9×5)mod10=5 y las cartas son adecuadas.

Clasificación de manos y ganador

Las reglas anteriores dan como resultado 18 rangos de mano distintos que se resumen en la siguiente tabla, desde la más fuerte a la más baja (o la más rara a la más común). Las probabilidades se dan solo para información.

Con dos manos, gana la mano con el rango más bajo. Si ambas manos son del mismo rango, entonces es un empate (no hay desempate).

 hand rank | hand value(s) | deal probability
-----------+---------------+------------------
     1     | 9s            | 0.30%
     2     | 3s            | 0.60%
     3     | 1s            | 0.90%
     4     | 7s            | 1.21%
     5     | 5s            | 1.51%
     6     | 3             | 1.81%
     7     | 9             | 2.26%
     8     | 8s            | 2.71%
     9     | 6s            | 3.02%
    10     | 1 or 7        | 3.62% each
    11     | 2s or 4s      | 3.92% each
    12     | 5             | 4.98%
    13     | 0s            | 5.43%
    14     | 8             | 8.14%
    15     | 6             | 9.95%
    16     | 2             | 11.76%
    17     | 4             | 13.57%
    18     | 0             | 16.74%

El reto

Dadas dos manos ModTen , genere uno de los tres valores consistentes de su elección para saber si:

  • el primer jugador gana
  • el segundo jugador gana
  • es un empate

Se aplican las siguientes reglas:

  • Una tarjeta debe ser descrito por su rango en mayúsculas ( 2, 3, ..., 9, T, J, Q, Ko A), seguido de su demanda en minúsculas ( c, d, ho s, para los tréboles, diamantes, corazones y picas).
  • Puede usar en "10"lugar de, "T"pero cualquier otra sustitución está prohibida.
  • Siempre y cuando se sigan las reglas anteriores, puede tomar las manos en cualquier formato razonable y sin ambigüedades. Se le permite tomar el rango y el palo como dos personajes distintos en lugar de una sola cadena.

    Algunos formatos de entrada válidos son:

    • "7c Qh 8s Ks"
    • [["7c","Qh"], ["8s","Ks"]]
    • [[['7','c'], ['Q','h']], [['8','s'], ['K','s']]]
    • etc.
  • En lugar de usar 3 valores distintos consistentes, su salida también puede ser negativa , positiva o cero . Por favor, especifique el formato de salida utilizado en su respuesta.

  • Este es el .

Casos de prueba

El jugador 1 gana

["Js","3s"], ["Ks","Kh"]
["7h","9h"], ["9s","7c"]
["Ah","5s"], ["Ts","8s"]
["Ts","8s"], ["Jh","2s"]
["4h","8s"], ["Qh","Ks"]

El jugador 2 gana

["Th","8d"], ["6s","Kd"]
["Jc","5c"], ["3s","9s"]
["Jc","Jd"], ["9h","Ah"]
["2d","4d"], ["3h","3s"]
["5c","4c"], ["3c","2c"]

Dibujar

["Js","3s"], ["3d","Jd"]
["Ah","Ac"], ["3d","9s"]
["Qc","Kc"], ["6d","4d"]
["2d","3d"], ["3s","2s"]
["Ts","9c"], ["4h","5d"]
Arnauld
fuente
¿Qué hay de tomar las enumeraciones como entrada? Haskell tiene un sistema de tipos bastante poderoso ; Estoy bastante seguro de que algo así podría hacerse directamente en él.
wizzwizz4
Esto no es Haskell, pero ¿ {{J, s}, {3, s}}estaría bien?
wizzwizz4
1
@ wizzwizz4 Sí, está bien.
Arnauld
2
Esto podría ser más claro con "manos de cartas con palos a juego" en lugar de "cartas del mismo palo".
Chrylis -en huelga-

Respuestas:

13

Python 3 , 114 110 bytes

lambda m,n:p(*n)-p(*m)
R=b"T 2J45UNK9RL<3SLM;QAK:O>=/678"
v=R.find
p=lambda i,s,j,t:R[s==t::2][v(j)*v(i)%10+3]

Pruébalo en línea!

@Arnauld propuso la idea de fusionar el valor de la tarjeta y las cadenas de la tabla de clasificación. Después de algunos intentos, logré crear una cadena combinada R="T 2J45UNK9RL<3SLM;QAK:O>=/678", que tiene la misma longitud que la cadena de valor de la tarjeta original. La subcadena R[6:25]="UNK9RL<3SLM;QAK:O>=/"sirve como mesa de rango, así como una tabla de consulta de valor de la tarjeta de 3, 9, A, K, y Q. La decodificación de valor ASCII de la nueva tabla de clasificación tiene el mismo efecto de clasificación que la tabla de clasificación anterior.

El uso de cadenas de bytes como entrada ahorra 4 bytes.

El uso cmpen Python 2 puede reducir la solución a 102 bytes, como se muestra en la solución de @ xnor .


Python 3 , 165 142 130 129 bytes

lambda m,n:p(*n)-p(*m)
v="T 23456789   J    QA        K".find
p=lambda i,s,j,t:ord("HC92FA51GAB4E893D760"[s==t::2][v(j)*v(i)%10])

Pruébalo en línea!

-23 bytes gracias a @Jonathan Allan

-2 bytes gracias a @ovs

-1 byte gracias a @mypetlion

Sin golf:

f = lambda hand1, hand2: get_rank(*hand2) - get_rank(*hand1)
def get_rank(v1, suit1, v2, suit2):
    get_card_value = "T 23456789   J    QA        K".find
    # rank_table = [[17,9,15,5,16,11,14,9,13,6],[12,2,10,1,10,4,8,3,7,0]]
    # rank_table = ("H9F5GBE9D6","C2A1A48370") # Base-18 encoding of ranks
    rank_table = "HC92FA51GAB4E893D760" # Interleaved base-18 encoding

    # ASCII-value decoding has the same ranking effect as base-18 decoding
    return ord(rank_table[suit1 == suit2::2][get_card_value(v2) * get_card_value(v1) % 10])

La función ftoma dos argumentos que representan la mano del jugador 1 y el jugador 2. Devuelve un valor positivo, negativo o cero en el caso de que un jugador 1 gane, un jugador 2 gane o un empate, correspondientemente. Cada mano está codificada como una sola cadena, por ejemplo, "7cQh".

Joel
fuente
3
Hola Joel, ¡bienvenido a CGCC! ¡Una idea muy inteligente que divide la matriz de rango de manos en dos! ¡Sigan viniendo!
640 KB
1
@ Jonathan Allan Gracias. He incorporado su idea usando enfoques ligeramente diferentes.
Joel
1
Puede guardar 2 bytes mediante el almacenamiento de la tabla de clasificación en una sola cadena:"HC92FA51GAB4E893D760"[s==t::2]
ovs
1
Y otro 4 bytes más corto si usted está dispuesto a cambiar a Python 2. ( cmpno está disponible en Python 3)
ovs
1
Puede usar en str.findlugar de str.indexguardar un byte. La única diferencia de comportamiento entre los dos métodos es que indexarroja un error cuando no se encuentra el elemento, mientras que findregresa -1. Por lo tanto, no será un problema para su código.
mypetlion
11

Asamblea x86-16, 87 83 bytes

Binario:

00000000: e807 0050 e803 005a 3ac2 ad2c 3092 ad2c  ...P...Z:..,0..,
00000010: 30bb 3501 3af4 7503 bb3f 01e8 0a00 92e8  0.5.:.u..?......
00000020: 0600 f6e2 d40a d7c3 b106 bf49 01f2 aee3  ...........I....
00000030: 038a 4504 c312 0a10 0611 0c0f 0a0e 070d  ..E.............
00000040: 030b 020b 0509 0408 0124 1a21 1b11 0003  .........$.!....
00000050: 0808 09                                  ...

Desmontado:

E8 010A         CALL GET_HAND           ; score first hand, ranked score into AL 
50              PUSH AX                 ; save score
E8 010A         CALL GET_HAND           ; score second hand 
5A              POP  DX                 ; restore first hand into DL 
3A C2           CMP  AL, DL             ; compare scores - result in CF, OF and ZF

            GET_HAND PROC               ; 4 char string to ranked score ("9s7c" -> 6)
AD              LODSW                   ; load first card string 
2C 30           SUB  AL, '0'            ; ASCII convert 
92              XCHG DX, AX             ; store in DX 
AD              LODSW                   ; load second card string 
2C 30           SUB  AL, '0'            ; ASCII convert 
BB 0139         MOV  BX, OFFSET R       ; first, point to non-suited table 
3A F4           CMP  DH, AH             ; is it suited?
75 03           JNZ  NO_SUIT 
BB 0143         MOV  BX, OFFSET RS      ; point to suited table 
            NO_SUIT: 
E8 012C         CALL GET_VALUE          ; get face card value in AL 
92              XCHG DX, AX             ; swap first and second cards 
E8 012C         CALL GET_VALUE          ; get face card value in AL 
F6 E2           MUL  DL                 ; multiply values of two cards 
D4 A0           AAM                     ; AL = AL mod 10
D7              XLAT                    ; lookup value in rank score table 
C3              RET 
            GET_HAND ENDP

            GET_VALUE PROC              ; get value of a card (2 -> 2, J -> 3, A -> 9)
B1 06           MOV  CL, 6              ; loop counter for scan
BF 014D         MOV  DI, OFFSET V       ; load lookup table 
F2/ AE          REPNZ SCASB             ; scan until match is found 
E3 03           JCXZ NOT_FOUND          ; if not found, keep original numeric value
8A 45 04        MOV  AL, BYTE PTR[DI+4] ; if found, get corresponding value 
            NOT_FOUND:
C3              RET                     ; return to program 
            GET_VALUE ENDP

R   DB 18, 10, 16, 6, 17, 12, 15, 10, 14, 7     ; unsuited score table
RS  DB 13, 3, 11, 2, 11, 5, 9, 4, 8, 1          ; suited score table
V   DB 'J'-'0','Q'-'0','K'-'0','A'-'0','T'-'0'  ; face card score table
    DB 3, 8, 8, 9, 0

La entrada es como una cadena como Js3sKsKh, en el puntero en SI. La salida es ZF = 0 and SF = OF(prueba con JG) si el jugador 1 gana, SF ≠ OF(prueba con JL) si el jugador 2 gana o ZF(prueba con JE) si un empate.

Salida usando el programa de prueba DOS:

ingrese la descripción de la imagen aquí

Descargue y pruebe MODTEN.COM para DOS.

640 KB
fuente
7

05AB1E , 41 37 bytes

•V›{₆Ÿ&∊WÍj¸•19вyεø`Ës‘ߌQ‘ŽćS‡Pθ«}èÆ

-4 bytes gracias a @Grimy .

Ingrese como una lista de la lista de caracteres, como el tercer formato de entrada de ejemplo en la descripción del desafío. Es decir, P1 7c Qhy P2 8s Ksse ingresarán como [[["7","c"],["Q","h"]],[["8","s"],["K","s"]]]. (Y usos "10"para 10)

Emite un entero negativo si el jugador 1 gana; un entero positivo si el jugador 2 gana; o 0 si es un empate.

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

V›{₆Ÿ&∊WÍj¸•  # Push compressed integer 36742512464916394906012008
 19в           # Convert it to base-19 as list:
               #   [18,10,16,6,17,12,15,10,14,7,13,3,11,2,11,5,9,4,8,1]
Iε             # Push the input, and map each of its hands to:
  ø            #  Zip/transpose the hand; swapping rows/columns
               #   i.e. [["8","s"],["K","s"]] → [[["8","K"],["s","s"]]
   `           #  Push them separated to the stack
    Ë          #  Check if the two suits in the top list are equal (1/0 for truthy/falsey)
    s          #  Swap to get the list with the two values
     ‘ߌQ     #  Push dictionary string "JAKEQ"
     ŽćS       #  Push compressed integer 39808
              #  Transliterate these characters to these digits
      P        #  Now take the product of the two values in the list
       θ       #  Only leave the last digit (basically modulo-10)
    «          #  And merge it to the 1/0
               #  (now we have the hand values of both players,
               #   where instead of a trailing "s" we have a leading 1)
             # After the map: index each value into the earlier created integer-list
               # (now we have the hand rank of both players)
   Æ           # And then reduce the resulting integers by subtracting
               # (after which the result is output implicitly)

Vea esta sugerencia mía 05AB1E (secciones ¿Cómo usar el diccionario? ¿Cómo comprimir enteros grandes? Y ¿Cómo comprimir listas enteras? ) Para comprender por qué •V›{₆Ÿ&∊WÍj¸•es 36742512464916394906012008, •V›{₆Ÿ&∊WÍj¸•19вes [18,10,16,6,17,12,15,10,14,7,13,3,11,2,11,5,9,4,8,1], ‘ߌQ‘es "JAKEQ"y ŽćSes 39808.

Kevin Cruijssen
fuente
La pregunta explícitamente permite tomar de entrada Tcomo 10, por lo que sólo puede caer el Tde JTQKA(y el uso comprimido entero de 3889 en lugar de 30.889). Además, T* ... +podría ser ... «.
Grimmy
1
@ Grimy Ah, de hecho sabía que en 10lugar de estar Tpermitido, pero no pensé en10nortemod10=0 0! Y T*...+ser ...«es obvio ahora que lo veo ..>.> ¡Gracias!
Kevin Cruijssen
1
37 (¡ahora realmente funciona!)
Grimmy
@Grimy Ah, ¡buen uso del diccionario así!
Kevin Cruijssen
3

PHP ,212 185 178 149 bytes

while($p=$argv[++$x])$$x=ord(rjpfqlojngmckbkeidha[(($v=[J=>3,Q=>8,K=>8,A=>9])[$p[0]]?:$p[0])*($v[$p[2]]?:$p[2])%10+($p[1]==$p[3])*10]);echo${1}-${2};

Pruébalo en línea!

  • -7 bytes gracias a @ Night2!
  • -29 bytes por ASCII que codifica la tabla en lugar de la matriz

La entrada es a través de la línea de comando. La salida a STDOUTes negativa si el jugador 1 gana, positiva si el jugador 2 gana, 0si empata. Ejemplo:

$ php modten.php Js3s KsKh
-1
640 KB
fuente
1
@ Night2 Supongo que si estuviera dispuesto a darnos el operador de la nave espacial (es decir, ¿con qué frecuencia puede usar eso?), Podría -2 bytes y simplemente devolver negativo, positivo o cero, en lugar de -1, 1o 0.
640 KB el
Me sorprendió (en el buen sentido) ver al operador de la nave espacial en la respuesta anterior.
Noche2
2

Jalea , 46 bytes

“T0J3Q8K8A9”yⱮZV€P$Eƭ€)%⁵UḌị“©N¿!Æßvṅ?żṀ’b18¤I

Pruébalo en línea!

Un programa completo que toma como argumento, por ejemplo, ["7h","Ks"],["4s","Ts"]e imprime cero si ambos jugadores empatan, positivo si el jugador 1 gana y negativo si el jugador 2 gana.

Nick Kennedy
fuente
2

C (gcc) , 172 167 165 164 bytes

p(l,v)char*l,*v;{v="T 23456789   J    QA        K";return"A<92?:51@:;4>893=760"[(l[1]==l[3])+(index(v,l[2])-v)*(index(v,*l)-v)%10*2];}f(char*s){return p(s+5)-p(s);}

Pruébalo en línea!

¡2 bytes eliminados gracias a @ceilingcat!

Básicamente un puerto de la solución Python3 de @ Joel, pero sin la codificación base18. Espera la entrada como una cadena con un espacio que separa las manos de los dos jugadores, y genera un número entero que es positivo, negativo o cero para indicar que el jugador 1 gana, el jugador 2 gana o si es un empate.

G. Sliepen
fuente
2

Perl 6 , 101 100 94 88 bytes

-1 byte gracias a Jo King

{[-] .map:{'HC92FA51GAB4E893D76'.ords[[*](.[*;0]>>.&{TR/JQKA/3889/})%10*2+[eq] .[*;1]]}}

Pruébalo en línea!

Toma la entrada como se f(((<J ♠>, <3 ♠>), (<10 ♠>, <K ♥>)))usa 10para Ten. Devuelve un valor <0 si el jugador 1 gana,> 0 si el jugador 2 gana, 0 si es un empate.

Explicación

{
  [-]  # subtract values
  .map:{  # map both hands
    'HC92FA51GAB4E893D76'.ords[  # lookup rank in code point array
      [*](  # multiply
        .[*;0]  # card ranks
        >>.&{TR/JQKA/3889/}  # translate J,Q,K,A to 3,8,8,9
      )
      %10*2  # mod 10 times 2
      +[eq] .[*;1]  # plus 1 if suited
    ]
  }
}
nwellnhof
fuente
1

Carbón , 97 bytes

≔”)¶&sNψU↓”ζF¹³F¹³F⁻⁴⁼ικ⊞υ⁺÷λ³⊗﹪Π⁺§ζι§ζκχ≔”A↘τ[⁵PkxτG”ε≔⁰δF⟦θη⟧≦⁻№υ⁺⁼§ι¹§ι³⊗﹪Π⁺§ζ⌕ε§ι⁰§ζ⌕ε§ι²χδIδ

Pruébalo en línea! El enlace es a la versión detallada del código. Toma la entrada como dos cadenas de 4 caracteres, por ejemplo, QcKc 6d4dy genera un entero con signo. Explicación:

≔”)¶&sNψU↓”ζ

La cadena comprimida 2345678903889representa los valores de la tarjeta.

F¹³F¹³

Pase sobre cada posible par de valores.

F⁻⁴⁼ικ

Pase sobre cada posible segundo palo de la tarjeta. Sin pérdida de generalidad, podemos suponer que la primera carta tiene el palo 3, por lo que la segunda carta puede variar de 0 a 3 a menos que los valores sean los mismos, en cuyo caso solo puede variar de 0 a 2.

⊞υ⁺÷λ³⊗﹪Π⁺§ζι§ζκχ

Calcule la puntuación modificada de la mano, que es el valor de la mano duplicada, más 1 si los palos son iguales (es decir, la segunda carta tiene el palo 3).

≔”A↘τ[⁵PkxτG”ε

La cadena comprimida 23456789TJQKArepresenta los caracteres de la tarjeta. Las tarjetas de entrada se buscan en esta cadena y luego la posición se usa para indexar en la primera cadena para obtener el valor de la tarjeta.

≔⁰δ

Inicializa el resultado a 0.

F⟦θη⟧

Pase sobre las dos manos.

≦⁻№υ⁺⁼§ι¹§ι³⊗﹪Π⁺§ζ⌕ε§ι⁰§ζ⌕ε§ι²χδ

Calcule el puntaje modificado de la mano y, por lo tanto, su frecuencia, y reste el resultado de esto.

Iδ

Salida de la diferencia de frecuencia.

Neil
fuente
0

Perl 5 -p , 107 bytes

$a=A;y/ATJQK/90388/;${$a++}=substr"IAG6HCFAE7D3B2B59481",($1eq$3).$&*$2%10,1while/.(.) (.)(.)/g;$_=$A cmp$B

Pruébalo en línea!

Entrada:

As 4d,Th 8c

(En realidad, la coma puede ser cualquier personaje).

Salida:

-1  Player one wins
 0  Draw
 1  Player two wins
Xcali
fuente