Nie ma to jak dobra, stara gra ModTen

27

Uwaga: ModTen to fikcyjna gra karciana, która została stworzona wyłącznie w celu wykonania tego wyzwania.

Zasady ModTen

ModTen jest odtwarzany standardową talią 52 kart. Ponieważ pełne reguły nie zostały jeszcze wynalezione, skupimy się wyłącznie na rankingu rozdań.

Jack & Three, w kolorze

Zwycięska ręka w ModTen. Grafika z Wikipedii .

Wartości kart

Karty mają następujące wartości:

  • 2 do 9 : warte swojej wartości nominalnej
  • Dziesięć : 0 punktów
  • Jack : 3 punkty
  • Królowa lub król : 8 punktów
  • As : 9 punktów

Wartości ręczne

  • ModTen ręcznie wykonany jest z dwóch kart . Podstawową wartość ręki uzyskuje się poprzez pomnożenie wartości obu kart razem i zachowanie tylko ostatniej cyfry (tj. Zastosowanie modulo 10).

    Na przykład wartość 7 ♥ - Q ♣ wynosi „ 6 ”, ponieważ (7×8)mod10=6 .

  • Jedyną inną zasadą w ModTen jest to, że karty w kolorze są warte więcej niż karty nieodpowiednie. Zgodnie z konwencją dodamy „s” do wartości, jeśli obie karty są tego samego koloru.

    Na przykład wartość 9 ♠ - 5 ♠ będzie oznaczona jako „ 5s ”, ponieważ (9×5)mod10=5 i karty są w kolorze.

Ranking rozdań i zwycięzca

Powyższe zasady dają 18 odrębnych rang, które zestawiono w poniższej tabeli, od najsilniejszych do najniższych (lub od najrzadszych do najczęstszych). Prawdopodobieństwa podano jedynie w celach informacyjnych.

Biorąc pod uwagę dwie ręce, wygrywa ręka o najniższej pozycji. Jeśli obie ręce mają tę samą rangę, to jest remis (nie ma rozstrzygającego remisu).

 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%

Wyzwanie

Biorąc pod uwagę dwie ręce ModTen , wypisz jedną z trzech spójnych wybranych wartości, aby stwierdzić, czy:

  • pierwszy gracz wygrywa
  • drugi gracz wygrywa
  • jest remis

Obowiązują następujące zasady:

  • Karta musi być opisany przez jego rangi w górnej części obudowy ( 2, 3, ...,9 , T, J, Q, Klub A), a następnie przez jego garnitur w dolnej obudowy ( c, d, hlub s, dla klubów, diamenty, serca i pik).
  • Możesz użyć "10"zamiast, "T"ale jakakolwiek inna zamiana jest zabroniona.
  • Dopóki powyższe zasady są przestrzegane, możesz wziąć ręce w dowolny rozsądny i jednoznaczny format. Możesz przyjąć rangę i kolor jako dwa odrębne znaki zamiast jednego ciągu.

    Niektóre prawidłowe formaty wejściowe to:

    • "7c Qh 8s Ks"
    • [["7c","Qh"], ["8s","Ks"]]
    • [[['7','c'], ['Q','h']], [['8','s'], ['K','s']]]
    • itp.
  • Zamiast używać 3 spójnych odrębnych wartości, wynik może być również ujemny , dodatni lub zerowy . Podaj format wyjściowy użyty w odpowiedzi.

  • To jest .

Przypadki testowe

Gracz 1 wygrywa

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

Gracz 2 wygrywa

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

rysować

["Js","3s"], ["3d","Jd"]
["Ah","Ac"], ["3d","9s"]
["Qc","Kc"], ["6d","4d"]
["2d","3d"], ["3s","2s"]
["Ts","9c"], ["4h","5d"]
Arnauld
źródło
Co z przyjmowaniem wyliczeń jako wkładem? Haskell ma dość potężny system typów ; Jestem całkiem pewien, że coś takiego można zrobić bezpośrednio w nim.
wizzwizz4
To nie jest Haskell, ale czy {{J, s}, {3, s}}wszystko w porządku?
wizzwizz4
1
@ wizzwizz4 Tak, w porządku.
Arnauld
2
Może to być bardziej zrozumiałe w przypadku „układów kart o pasujących kolorach” zamiast „kart w kolorze”.
Chrylis -on strike-

Odpowiedzi:

13

Python 3 , 114 110 bajtów

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]

Wypróbuj online!

@Arnauld zaproponował pomysł połączenia wartości karty i ciągów tabeli rang. Po kilku próbach udało mi się stworzyć scalony ciąg R="T 2J45UNK9RL<3SLM;QAK:O>=/678", który ma taką samą długość jak oryginalny ciąg wartości karty. Podciąg R[6:25]="UNK9RL<3SLM;QAK:O>=/"służy jako tabeli rang, jak również tabeli odnośników do wartości karty 3, 9, A,K , i Q. Dekodowanie wartości ASCII nowej tabeli rang ma taki sam efekt rankingowy jak poprzednia tabela rang.

Użycie ciągów bajtów jako danych wejściowych pozwala zaoszczędzić 4 bajty.

Używanie cmpw Pythonie 2 może zredukować rozwiązanie do 102 bajtów, jak pokazuje rozwiązanie @ xnor .


Python 3 , 165 142 130 129 bajtów

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

Wypróbuj online!

-23 bajty dzięki @Jonathan Allan

-2 bajty dzięki @ovs

-1 bajt dzięki @mypetlion

Nie golfowany:

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

Funkcja fprzyjmuje dwa argumenty reprezentujące rękę gracza 1 i gracza 2. Zwraca wartość dodatnią, ujemną lub zerową w przypadku odpowiednio wygranej gracza 1, wygranej gracza 2 lub remisu. Każda ręka jest kodowana jako pojedynczy ciąg, np. „7cQh”.

Joel
źródło
3
Cześć Joel, witamy w CGCC! Bardzo sprytny pomysł dzielący tablicę rang na dwie części! Nadal ich!
640 KB
1
@Jonathan Allan Thanks. Włączyłem twój pomysł, używając nieco innych podejść.
Joel
1
Można zapisać 2 bajty przechowując tabeli rang w jednym ciągiem:"HC92FA51GAB4E893D760"[s==t::2]
OVS
1
I kolejna 4 bajty krótszy , jeśli jesteś gotów, aby przełączyć do Python 2. ( cmpnie jest dostępny w Pythonie 3)
OVS
1
Możesz użyć str.findzamiast str.indexzapisać jeden bajt. Jedyna różnica w zachowaniu między tymi dwiema metodami polega na tym, że indexzgłasza błąd, gdy element nie zostanie znaleziony, podczas gdy findzwraca -1. Więc to nie będzie problem dla twojego kodu.
mypetlion
11

Montaż x86-16, 87 83 bajty

Dwójkowy:

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                                  ...

Niezmontowane:

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

Dane wejściowe są takie jak ciąg znaków, np. Js3sKsKhPrzy wskaźniku w SI. Wyjście to ZF = 0 and SF = OF(test z JG), jeśli gracz 1 wygra, SF ≠ OF(test z JL), jeśli gracz 2 wygra lub ZF(test z JE), jeśli remis.

Dane wyjściowe za pomocą programu testowego DOS:

wprowadź opis zdjęcia tutaj

Pobierz i przetestuj MODTEN.COM dla DOS.

640 KB
źródło
7

05AB1E , 41 37 bajtów

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

-4 bajty dzięki @Grimy .

Wprowadź jako listę listy znaków, podobnie jak trzeci przykładowy format wejściowy w opisie wyzwania. Tj. P1 7c Qhi P2 8s Ksbędą wprowadzane jako [[["7","c"],["Q","h"]],[["8","s"],["K","s"]]]. (I używa "10"dla 10.)

Zwraca ujemną liczbę całkowitą, jeśli gracz 1 wygra; dodatnia liczba całkowita, jeśli gracz 2 wygra; lub 0, jeśli jest to remis.

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

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)

Zobacz moją wskazówkę 05AB1E (sekcje Jak korzystać ze słownika? Jak kompresować duże liczby całkowite? I Jak kompresować listy liczb całkowitych? ), Aby zrozumieć, dlaczego •V›{₆Ÿ&∊WÍj¸•jest 36742512464916394906012008, •V›{₆Ÿ&∊WÍj¸•19вjest [18,10,16,6,17,12,15,10,14,7,13,3,11,2,11,5,9,4,8,1], ‘ߌQ‘jest "JAKEQ"i ŽćSjest 39808.

Kevin Cruijssen
źródło
Pytanie wyraźnie zezwala na przyjmowanie danych wejściowych Tjako 10, więc możesz po prostu usunąć wartość Tz JTQKA(i użyć skompresowanej liczby całkowitej 3889 zamiast 30889). Również T* ... +może być ... «.
Grimmy
1
10T10nmod10=0T*...+...«
1
37 (teraz faktycznie działa!)
Grimmy
@Grimy Ah, miłe użycie takiego słownika!
Kevin Cruijssen
3

PHP ,212 185 178 149 bajtów

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};

Wypróbuj online!

  • -7 bajtów dzięki @ Night2!
  • -29 bajtów wg ASCII kodujących tabelę zamiast tablicy

Dane wejściowe są przez wiersz poleceń. Wynik STDOUTjest ujemny, jeśli gracz 1 wygra, dodatni, jeśli gracz 2 wygra, 0jeśli remis. Przykład:

$ php modten.php Js3s KsKh
-1
640 KB
źródło
1
@ Night2 Przypuszczam, gdybym był skłonny dać nam operatora statku kosmicznego (mam na myśli, jak często można dostać się do wykorzystania takiego?), Mogę -2 bajtów i po prostu wrócić ujemny, dodatni lub zerowy, zamiast -1, 1albo 0.
640 KB
Byłem zaskoczony (w dobry sposób), widząc operatora statku kosmicznego w poprzedniej odpowiedzi.
Noc2
2

Galaretka , 46 bajtów

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

Wypróbuj online!

Pełny program bierze na przykład swój argument ["7h","Ks"],["4s","Ts"]i wypisuje zero, jeśli obaj gracze losują, dodatni, jeśli gracz 1 wygrywa, a ujemny, jeśli gracz 2 wygrywa.

Nick Kennedy
źródło
2

C (gcc) , 172 167 165 164 bajtów

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);}

Wypróbuj online!

Ogolono 2 bajty dzięki @ceilingcat!

Zasadniczo port rozwiązania Python3 @ Joela, ale bez kodowania base18. Oczekuje, że dane wejściowe są jednym ciągiem ze spacją oddzielającą ręce dwóch graczy i generują liczbę całkowitą, która jest dodatnia, ujemna lub zero, co oznacza, że ​​gracz 1 wygrywa, gracz 2 wygrywa lub jeśli jest to remis.

G. Sliepen
źródło
2

Perl 6 , 101 100 94 88 bajtów

-1 bajt dzięki Jo King

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

Wypróbuj online!

Staje się jako dane wejściowe f(((<J ♠>, <3 ♠>), (<10 ♠>, <K ♥>)))z wykorzystaniem 10przez dziesięć. Zwraca wartość <0, jeśli gracz 1 wygra,> 0, jeśli gracz 2 wygra, 0, jeśli to remis.

Wyjaśnienie

{
  [-]  # 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
źródło
1

Węgiel drzewny , 97 bajtów

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

Wypróbuj online! Link jest do pełnej wersji kodu. Pobiera dane wejściowe jako dwa ciągi 4 znaków, np. QcKc 6d4dI wypisuje liczbę całkowitą ze znakiem. Wyjaśnienie:

≔”)¶&sNψU↓”ζ

Skompresowany ciąg 2345678903889reprezentuje wartości kart.

F¹³F¹³

Pętlę nad każdą możliwą parą wartości.

F⁻⁴⁼ικ

Pętla nad każdym możliwym drugim kolorem karty. Bez utraty ogólności możemy założyć, że pierwsza karta ma kolor 3, więc drugi kolor karty może wynosić od 0 do 3, chyba że wartości są takie same, w takim przypadku może ona wynosić tylko od 0 do 2.

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

Oblicz zmodyfikowany wynik rozdania, który jest wartością podwojonej ręki, plus 1, jeśli kolory są takie same (tj. Druga karta ma kolor 3).

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

Skompresowany ciąg 23456789TJQKAreprezentuje znaki karty. Karty wejściowe są wyszukiwane w tym ciągu, a następnie pozycja służy do indeksowania do pierwszego ciągu w celu uzyskania wartości karty.

≔⁰δ

Zainicjuj wynik na 0.

F⟦θη⟧

Zapętlić obie ręce.

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

Oblicz zmodyfikowany wynik rozdania, a tym samym jego częstotliwość, i odejmij od tego wynik.

Iδ

Wyjmij różnicę częstotliwości.

Neil
źródło
0

Perl 5 -p , 107 bajtów

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

Wypróbuj online!

Wkład:

As 4d,Th 8c

(W rzeczywistości przecinek może być dowolnym znakiem).

Wydajność:

-1  Player one wins
 0  Draw
 1  Player two wins
Xcali
źródło