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

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


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.


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.


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

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.


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.


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

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.



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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.