Nada como um bom e velho jogo de ModTen

27

Isenção de responsabilidade: ModTen é um jogo de cartas fictício criado para o único objetivo deste desafio.

As regras do ModTen

O ModTen é jogado com um baralho de 52 cartas padrão. Como as regras completas ainda não foram inventadas, vamos nos concentrar exclusivamente no ranking das mãos.

Jack & Three, adequado

Uma mão vencedora no ModTen. Gráficos da Wikipedia .

Valores do cartão

Os cartões têm os seguintes valores:

  • 2 a 9 : vale o seu valor nominal
  • Dez : 0 ponto
  • Jack : 3 pontos
  • Rainha ou rei : 8 pontos
  • Ás : 9 pontos

Valores manuais

  • Uma mão ModTen é feita de duas cartas . O valor base de uma mão é obtido multiplicando o valor de ambas as cartas e mantendo apenas o último dígito (ou seja, aplicando o módulo 10).

    Por exemplo, o valor de 7 ♥ - Q ♣ é " " porque .6(7×8)mod10=6

  • A única outra regra no ModTen é que as cartas do mesmo naipe valem mais do que as não usadas . Por convenção, vamos acrescentar um "s" ao valor se ambas as cartas forem do mesmo naipe.

    Por exemplo, o valor de 9 5 - 5 ♠ será anotado como " ", porque e as cartas são do mesmo naipe.5s(9×5)mod10=5

Classificação da mão e vencedor

As regras acima resultam em 18 posições distintas, resumidas na tabela a seguir, da mais forte à mais baixa (ou mais rara à mais comum). As probabilidades são fornecidas apenas para informação.

Dadas duas mãos, a mão com a classificação mais baixa ganha. Se ambas as mãos tiverem o mesmo valor, é um empate (não há 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%

O desafio

Dadas duas mãos ModTen , produza um dos três valores consistentes de sua escolha para dizer se:

  • o primeiro jogador ganha
  • o segundo jogador ganha
  • É um empate

As seguintes regras se aplicam:

  • O cartão deve ser descrito por sua posição em maiúsculas ( 2, 3, ..., 9, T, J, Q, Kou A) seguido por seu terno em minúsculas ( c, d, hou s, para os clubes, diamantes, corações e pás).
  • Você pode usar em "10"vez de, "T"mas qualquer outra substituição é proibida.
  • Desde que as regras acima sejam seguidas, você poderá tomar as mãos em qualquer formato razoável e inequívoco. Você tem a classificação e o naipe como dois caracteres distintos, em vez de uma única sequência.

    Alguns formatos de entrada válidos são:

    • "7c Qh 8s Ks"
    • [["7c","Qh"], ["8s","Ks"]]
    • [[['7','c'], ['Q','h']], [['8','s'], ['K','s']]]
    • etc.
  • Em vez de usar três valores distintos consistentes, sua saída também pode ser negativa , positiva ou zero . Especifique o formato de saída usado na sua resposta.

  • Isso é .

Casos de teste

Jogador 1 vence

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

Jogador 2 vence

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

Desenhar

["Js","3s"], ["3d","Jd"]
["Ah","Ac"], ["3d","9s"]
["Qc","Kc"], ["6d","4d"]
["2d","3d"], ["3s","2s"]
["Ts","9c"], ["4h","5d"]
Arnauld
fonte
Que tal receber enums como entrada? Haskell tem um sistema de tipos bastante poderoso ; Tenho certeza de que algo assim poderia ser feito diretamente nele.
wizzwizz4 23/08
Isso não é Haskell, mas estaria {{J, s}, {3, s}}tudo bem?
wizzwizz4 23/08
1
@ wizzwizz4 Sim, tudo bem.
Arnauld
2
Isso pode ser mais claro com "mãos de cartas com naipes iguais" em vez de "cartas do mesmo naipe".
chrylis -on strike - 24/08/08

Respostas:

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]

Experimente online!

A @Arnauld propôs a idéia de mesclar o valor do cartão e a sequência de tabelas da tabela. Depois de algumas tentativas, consegui criar uma string mesclada R="T 2J45UNK9RL<3SLM;QAK:O>=/678", que tem o mesmo comprimento da string de valor do cartão original. A substring R[6:25]="UNK9RL<3SLM;QAK:O>=/"serve como tabela de classificação, bem como uma tabela de pesquisa valor do cartão para 3, 9, A, K, e Q. A decodificação de valor ASCII da nova tabela de classificação tem o mesmo efeito de classificação que a tabela de classificação anterior.

Usar cadeias de bytes como entrada economiza 4 bytes.

O uso cmpno Python 2 pode reduzir a solução para 102 bytes, como mostra a solução do @ 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])

Experimente online!

-23 bytes graças a @ Jonathan Allan

-2 bytes graças a @ovs

-1 byte graças a @mypetlion

Ungolfed:

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

A função faceita dois argumentos que representam a mão do jogador 1 e do jogador 2. Retorna um valor positivo, negativo ou zero no caso de uma vitória do jogador 1, uma vitória do jogador 2 ou um empate, correspondentemente. Cada ponteiro é codificado como uma única sequência, por exemplo, "7cQh".

Joel
fonte
3
Olá Joel, bem-vindo ao CGCC! Idéia muito inteligente dividindo o ranking de mãos em dois! Continue vindo!
640KB 23/08
1
@ Jonathan Allan Obrigado. Incorporei sua ideia usando abordagens ligeiramente diferentes.
Joel
1
Você pode salvar 2 bytes armazenando a tabela de classificação em uma única sequência:"HC92FA51GAB4E893D760"[s==t::2]
ovs
1
E outros 4 bytes mais curtos se você quiser mudar para o Python 2. ( cmpnão está disponível no Python 3)
ovs
1
Você pode usar em str.findvez de str.indexsalvar um byte. A única diferença de comportamento entre os dois métodos é que indexgera um erro quando o elemento não é encontrado, enquanto findretorna -1. Portanto, não será um problema para o seu código.
mypetlion
11

x86-16 Assembly, 87 83 bytes

Binário:

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

A entrada é como uma sequência, como Js3sKsKh, no ponteiro SI. A saída é ZF = 0 and SF = OF(teste com JG) se o jogador 1 vencer, SF ≠ OF(teste com JL) se o jogador 2 vencer ou ZF(teste com JE) se um empate.

Saída usando o programa de teste do DOS:

insira a descrição da imagem aqui

Faça o download e teste o MODTEN.COM para DOS.

640KB
fonte
7

05AB1E , 41 37 bytes

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

-4 bytes graças a @Grimy .

Insira como uma lista da lista de caracteres, como o terceiro exemplo de formato de entrada na descrição do desafio. Ou seja, P1 7c Qhe P2 8s Ksseriam inseridos como [[["7","c"],["Q","h"]],[["8","s"],["K","s"]]]. (E usa "10"para 10.)

Emite um número inteiro negativo se o jogador 1 vencer; um número inteiro positivo se o jogador 2 vencer; ou 0 se for um empate.

Experimente online ou verifique todos os casos de teste .

Explicação:

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)

Consulte esta minha dica do 05AB1E (seções Como usar o dicionário? Como compactar números inteiros grandes? E Como compactar listas de números inteiros? ) Para entender por que •V›{₆Ÿ&∊WÍj¸•é 36742512464916394906012008, •V›{₆Ÿ&∊WÍj¸•19вé [18,10,16,6,17,12,15,10,14,7,13,3,11,2,11,5,9,4,8,1], ‘ߌQ‘é "JAKEQ"e ŽćSé 39808.

Kevin Cruijssen
fonte
A pergunta permite explicitamente aceitar a entrada Tcomo 10, para que você possa simplesmente excluir o Tfrom JTQKA(e usar o número inteiro comprimido 3889 em vez de 30889). Além disso, T* ... +poderia ser ... «.
Grimmy 26/08
1
@ Grimy Ah, eu realmente sabia que em 10vez de Té permitido, mas não pensei em ! E o ser é óbvio agora que eu vejo ..>.> Obrigado! 10nmod10=0T*...+...«
Kevin Cruijssen 26/08
1
37 (agora realmente funciona!)
Grimmy
@ Grimy Ah, bom uso do dicionário assim!
Kevin Cruijssen 26/08
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};

Experimente online!

  • -7 bytes graças a @ Night2!
  • -29 bytes por ASCII codificando a tabela em vez de matriz

A entrada é via linha de comando. A saída para STDOUTé negativa se o jogador 1 vencer, positiva se o jogador 2 vencer, 0se empatar. Exemplo:

$ php modten.php Js3s KsKh
-1
640KB
fonte
1
@ Night2 Suponho que se eu estava disposto a dar-nos o operador nave espacial (quero dizer, quantas vezes você começa a usar isso?), Eu poderia -2 bytes e retornar apenas negativo, positivo ou zero, em vez de -1, 1ou 0.
640KB
Fiquei impressionado (em um bom sentido) ao ver o operador da nave espacial na resposta anterior.
Night2
2

Gelatina , 46 bytes

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

Experimente online!

Um programa completo, tomando como argumento, por exemplo, ["7h","Ks"],["4s","Ts"]e imprimindo zero se os dois jogadores empatarem, positivo se o jogador 1 vencer e negativo se o jogador 2 vencer.

Nick Kennedy
fonte
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);}

Experimente online!

2 bytes eliminados graças a @ceilingcat!

Basicamente, uma porta da solução Python3 do @ Joel, mas sem a codificação base18. Espera a entrada como uma sequência com um espaço que separa as mãos dos dois jogadores e gera um número inteiro positivo, negativo ou zero para indicar que o jogador 1 vence, o jogador 2 vence ou se é um empate.

G. Sliepen
fonte
2

Perl 6 , 101 100 94 88 bytes

-1 byte graças a Jo King

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

Experimente online!

Toma entrada como f(((<J ♠>, <3 ♠>), (<10 ♠>, <K ♥>)))usar 10para dez. Retorna um valor <0 se o jogador 1 vencer,> 0 se o jogador 2 vencer, 0 se for um empate.

Explicação

{
  [-]  # 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
fonte
1

Carvão vegetal , 97 bytes

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

Experimente online! Link é a versão detalhada do código. Toma entrada como duas seqüências de caracteres de 4 caracteres, por exemplo, QcKc 6d4de gera um número inteiro assinado. Explicação:

≔”)¶&sNψU↓”ζ

A sequência compactada 2345678903889representa os valores do cartão.

F¹³F¹³

Faça um loop sobre cada par de valores possível.

F⁻⁴⁼ικ

Faça um loop sobre cada segundo naipe possível. Sem perda de generalidade, podemos supor que a primeira carta tenha naipe 3, portanto a segunda carta pode variar de 0 a 3, a menos que os valores sejam os mesmos; nesse caso, ela pode variar apenas de 0 a 2.

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

Calcule a pontuação modificada da mão, que é o valor da mão dobrada, mais 1 se os naipes forem iguais (ou seja, a segunda carta tem o naipe 3).

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

A sequência compactada 23456789TJQKArepresenta os caracteres do cartão. Os cartões de entrada são procurados nessa sequência e, em seguida, a posição é usada para indexar a primeira sequência para obter o valor do cartão.

≔⁰δ

Inicialize o resultado para 0.

F⟦θη⟧

Laço nas duas mãos.

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

Calcule a pontuação modificada da mão e, portanto, sua frequência e subtraia o resultado disso.

Iδ

Saída a diferença de frequência.

Neil
fonte
0

Perl 5 -p , 107 bytes

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

Experimente online!

Entrada:

As 4d,Th 8c

(Na verdade, a vírgula pode ser qualquer caractere.)

Saída:

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