Kto wygra grę w kamień, papier, nożyczki, jaszczurkę, spock?

24

Istnieje kilka pytań dotyczących tej grze , nawet konkurs tutaj . Myślę jednak, że wszystkie te wyzwania i konkursy potrzebują sposobu na automatyczne określenie zwycięzcy gry. Więc:

Wyzwanie

Biorąc pod uwagę dwa dane wejściowe w zakresie ["rock", "paper", "scissors", "lizard", "spock"]reprezentującym wybory dla gracza 1 i gracza 2, określ zwycięzcę meczu.

Zasady

[Winner] [action]    [loser]
-----------------------------
scissors cut         paper
paper    covers      rock
rock     crushes     lizard
lizard   poisons     spock
spock    smashes     scissors
scissors decapitates lizard
lizard   eats        paper
paper    disproves   spock
spock    vaporizes   rock
rock     crushes     scissors

Ograniczenia

  • Dane wejściowe będą parą ciągów w danym zakresie (nie można użyć innych ciągów). Możesz użyć tablic znaków, jeśli chcesz, o ile reprezentują one dowolną z wymienionych wartości.
  • Możesz wybrać, czy chcesz używać małych liter, wielkich liter ( "ROCK") czy wielbłąda ( "Rock") dla ciągów wejściowych, o ile wybrana wielkość jest taka sama dla wszystkich danych wejściowych.
  • Rezultatem będzie trio wartości, które określają zwycięzcę, którym może być cokolwiek chcesz, o ile odpowiedzi są spójne. Przykład: 1jeśli pierwsze wejście wygrywa, 2jeśli drugie wejście wygrywa, 0jeśli jest remis. A może Ajeśli pierwsze wejście wygrywa, Bjeśli drugie wejście wygrywa, <empty string>jeśli jest remis.

Cel

To jest , więc może wygrać najkrótszy program / metoda / funkcja / lambda dla każdego języka!

Testy

[Input 1] [Input 2] [Output: 1/2/0]
-----------------------------------
 rock      paper     2
 rock      scissors  1
 lizard    spock     1
 spock     rock      1
 spock     paper     2
 rock      rock      0
Charlie
źródło
To pochodzi z piaskownicy .
Charlie
1
Bardzo spokrewniony .
Stewie Griffin
Zamknąłem to jako duplikat połączonego pytania, ponieważ jest to to samo pytanie z 2 nowymi wartościami i niewielką zmianą we / wy.
Kreator pszenicy
4
@WheatWizard czasami niewielka zmiana na wejściu powoduje bardzo różne wyniki. Pytania mogą być dość podobne, ale dwie nowe wartości tworzą więcej przypadków do rozważenia, więc zastosowane tutaj algorytmy są na tyle różne, aby ludzie ponownie się zastanowili (zobacz odpowiedzi z cakelewą).
Charlie
4
Zgadzam się i głosowałem za ponownym otwarciem.
GB

Odpowiedzi:

25

Python 3 , 68 50 48 bajtów

EDYCJA: Dzięki 3 sztuczkom od Neila i 2 od pana Xcodera

Każdy ciąg wejściowy ma odrębny czwarty znak, więc używam go do ich rozróżnienia. Jeśli ułożysz elementy w cyklu (nożyczki, papier, kamień, jaszczurka, spock), wówczas każdy element bije element bezpośrednio za nim, a element 3 spotyka się cyklicznie. Odejmujemy więc pozycje wejść w cyklu. Jeśli ta liczba to 0, to remis. Jeśli jest to 1 lub 3, to wygrana dla pierwszego gracza. W moim oryginalnym rozwiązaniu różnica cyklu indeksowałaby się do ciągu „210100”, aby rozróżnić wyniki gry. Neil w jakiś sposób zorientował się, że można to osiągnąć bez indeksowania, dodając 7 i biorąc moduł przez 3. Edycja: Pierwotnie użyłem drugiego znaku do zidentyfikowania łańcucha, ale jeśli użyjesz czwartego i odwrócisz cykl, dostaniesz ciasto. I wszyscy moglibyśmy użyć więcej ciasta.

lambda x,y,z="cake".find:(7+z(y[3])-z(x[3]))%5%3

Wypróbuj online!

Starsza wersja:

lambda x,y,z="caoip".index:(7+z(y[1])-z(x[1]))%5%3

Wypróbuj online!

Orginalna wersja:

b="caoip"
def r(x,y):return"210100"[(b.index(y[1])-b.index(x[1]))%5]

Wypróbuj online!

Co robić
źródło
1
50 bajtów: Wypróbuj online!
Neil
6
Witamy w PPCG!
Steadybox
1
49 bajtów: Wypróbuj online! (przejście .indexna .find)
Mr. Xcoder
1
48 bajtów: Wypróbuj online! (nie potrzebujesz p, "chaoi"wystarczy)
Pan Xcoder
14

JavaScript (ES6), 56 bajtów

Pobiera dane wejściowe w składni curry (a)(b). Zwraca, 0jeśli wygra A, 1jeśli wygra B lub falseremis.

a=>b=>a!=b&&a>b^614>>((g=s=>parseInt(s,31)%9)(a)^g(b))&1

Próbny

W jaki sposób?

Definiujemy funkcję skrótu H () jako:

H = s => parseInt(s, 31) % 9

To daje:

s          | H(s)
-----------+-----
"rock"     |  2
"paper"    |  8
"scissors" |  1
"lizard"   |  3
"spock"    |  4

Biorąc pod uwagę dwa wejścia i b , uważamy następujące oświadczenia:

  1. czy mamy > b ? (w porządku leksykograficznym)
  2. czy b wygrywa grę?
  3. jaka jest wartość N = H (a) XOR H (b) ?

Z (1) i (2) wywnioskujemy, czy wynik a> b powinien zostać odwrócony, aby uzyskać prawidłowego zwycięzcę, i przechowujemy tę flagę w N-tej części maski wyszukiwania.

a        | H(a) | b        | H(b) | N  | a > b | b wins | invert
---------+------+----------+------+----+-------+--------+-------
rock     |   2  | paper    |   8  | 10 | Yes   | Yes    | No
rock     |   2  | scissors |   1  |  3 | No    | No     | No
rock     |   2  | lizard   |   3  |  1 | Yes   | No     | Yes
rock     |   2  | spock    |   4  |  6 | No    | Yes    | Yes
paper    |   8  | rock     |   2  | 10 | No    | No     | No
paper    |   8  | scissors |   1  |  9 | No    | Yes    | Yes
paper    |   8  | lizard   |   3  | 11 | Yes   | Yes    | No
paper    |   8  | spock    |   4  | 12 | No    | No     | No
scissors |   1  | rock     |   2  |  3 | Yes   | Yes    | No
scissors |   1  | paper    |   8  |  9 | Yes   | No     | Yes
scissors |   1  | lizard   |   3  |  2 | Yes   | No     | Yes
scissors |   1  | spock    |   4  |  5 | No    | Yes    | Yes
lizard   |   3  | rock     |   2  |  1 | No    | Yes    | Yes
lizard   |   3  | paper    |   8  | 11 | No    | No     | No
lizard   |   3  | scissors |   1  |  2 | No    | Yes    | Yes
lizard   |   3  | spock    |   4  |  7 | No    | No     | No
spock    |   4  | rock     |   2  |  6 | Yes   | No     | Yes
spock    |   4  | paper    |   8  | 12 | Yes   | Yes    | No
spock    |   4  | scissors |   1  |  5 | Yes   | No     | Yes
spock    |   4  | lizard   |   3  |  7 | Yes   | Yes    | No

Stąd bity:

bit | value
----+-----------
 0  | 0 (unused)
 1  | 1
 2  | 1
 3  | 0
 4  | 0 (unused)
 5  | 1
 6  | 1
 7  | 0
 8  | 0 (unused)
 9  | 1
10  | 0
11  | 0
12  | 0

Czytanie tego od dołu do góry i ignorowanie zer wiodących daje 1001100110 , czyli 614 po przecinku.

Arnauld
źródło
6

05AB1E , 16 bajtów

ε'³²s3èk}Æ7+5%3%

Wypróbuj online! lub jako pakiet testowy

Wyjaśnienie

Używa bardzo miłego caketricka od user507295

ε       }          # apply to each in the input pair
    s3è            # get the 4th letter
 '³²   k           # get its cake-index
         Æ         # reduce by subtraction
          7+       # add 7
            5%3%   # mod by 5 and then 3
Emigna
źródło
4

Rubinowy , 36 bajtów

->a,b{(2+a.sum%88%6-b.sum%88%6)%5%3}

Zwraca, 0jeśli pierwszy gracz wygra, 1jeśli drugi gracz wygra i 2dla remisu.

Oparty na odpowiedzi user507295, ale używa wzoru matematycznego do wykonania skrótu. a.sumjest sumą wszystkich kodów ASCII łańcucha a, mod 1<<16i jest przeznaczony jako podstawowa suma kontrolna. Hash został znaleziony przy użyciu następującego kodu:

1.upto(99){|j|p j,["scissors","paper","rock","lizard","spock"].map{|i|i.sum%j%6}}

To jdało dwie wartości, które dały odpowiedni skrót dla małych liter, mianowicie 88 i 80, z których obie dały malejącą sekwencję [3,2,1,0,4](lub [4,3,2,1,0]jeśli spock jest cyklicznie od początku do końca).

Jak wyjaśniono w innych odpowiedziach, hash, który daje stałą różnicę modulo 5 dla kolejnych elementów w powyższej sekwencji, jest potrzebny do działania (h[a]-h[b])%5formuły. Każdy element bije element 1 lub 3 miejsca po prawej stronie i przegrywa z elementem 2 lub 4 miejsca po prawej stronie.

Wypróbuj online!

Level River St
źródło
4

JavaScript (ES6), 63 54 53 49 bajtów

f=
(l,r,g=s=>"cake".search(s[3]))=>(7+g(r)-g(l))%5%3
<div onchange=o.textContent=`RLT`[f(a.selectedOptions[0].value,b.selectedOptions[0].value)]>L: <select id=a><option>Rock<option>Paper<option>Scissors<option>Lizard<option>Spock</select> R: <select id=b><option>Rock<option>Paper<option>Scissors<option>Lizard<option>Spock</select> Winner: <span id=o>T

Port mojego golfa na odpowiedź @ WhatToDo. Uwaga: fragment kodu dekoduje wynik liczbowy na coś nieco mniej nieczytelnego. Edycja: Zapisano 1 bajt dzięki @Arnauld. Zaoszczędź 4 bajty dzięki @ovs.

Neil
źródło
@ovs Ugh, nie przeniosłem swojego golfa na odpowiedź WhatToDo wystarczająco mocno ...
Neil
3

C, 53 bajtów

a="FÈ..J..ÁE";
z=*++y==*++x?0:a[*y&47>>1]>>*++x&7&1+1;

Problem ten potraktowałem jako maszynę stanu, której jest 25 stanów określonych przez dwa, pięć stanów wejściowych.

Poprzez zdefiniowanie wyników stanów w tablicy bitów. Sprawdzam wyniki wewnątrz, używając unikalnych znaczników w danych wejściowych.

Jak zauważono w innych rozwiązaniach, znaki 2, 3 i 4 są unikalne pomiędzy możliwymi danymi wejściowymi. Skoncentrowałem się na znakach 2 i 3, których używam, aby wybrać odpowiedni bit w mojej tablicy odpowiedzi.

W znaku 2 bity od 1 do 4 wyraźnie identyfikują dane wejściowe. Maskując te bity i odpowiednio przesuwając [to jest „* y & 47 >> 1”], dane wejściowe można zapisać jako 0, 1, 4, 7 lub 8. Stąd mój ciąg odpowiedzi ma 9 znaków. (oddzielne interesujące bity)

character 2:
a 61   011 0000 1
c 63   011 0001 1
i 69   011 0100 1
p 70   011 1000 0
o 6f   011 0111 1

W znaku 3 bity 0, 1 i 2 wyraźnie identyfikują dane wejściowe. Maskując te bity (przesunięcie nie jest wymagane) [to jest „* x i 7”], dane wejściowe można zapisać jako 0, 1, 2, 3 lub 7. (oddzielne interesujące bity)

character 3
p 70   01110 000
i 69   01101 001
z 7a   01111 010
o 6f   01101 111
c 63   01100 011

Łańcuch odpowiedzi można następnie obliczyć, po prostu wypełniając bity dla odpowiednich znaków.

0th char represents X=paper
1st char represents X=scissors
4th char represents X=Lizard
7th char represents X=Rock
8th char represents X=Spock

0th bit represents Y=Paper
1st bit represents Y=Scissors
2nd bit represents Y=Lizard
3rd bit represents Y=Rock
7th bit represents Y=Spock

Więc ustaw bit w char, gdzie wygrywa Y

char  7654 3210   in hex    in ascii
0     0100 0110    46         F
1     1100 1000    c8         È
2     0100 0000    d/c        .
3     0100 0000    d/c        .
4     0100 1010    4a         J
5     0100 0000    d/c        .
6     0100 0000    d/c        .
7     1100 0001    c1         Á
8     0100 0101    45         E

Zatem logika jest prosta: jeśli drugi znak jest taki sam, to narysuj, w przeciwnym razie zdobądź znak ascii na podstawie drugiego znaku y i przesuń bity o trzeci znak x i dodaj jeden. To powoduje, że odpowiedzi 0 dla remisu, 1 dla x wygranej i 2 dla y wygranej.

meismich
źródło
Witamy w PPCG! To świetna, przemyślana odpowiedź.
FantaC
1

Clojure, 130 118 bajtów

-12 bajtów, pozbywając się mojego dziwnego użycia comp.

(fn[& m](let[[p q](map #(apply +(map int(take 2 %)))m)d(- p q)](cond(= d 0)0(#{5 -16 12 -14 13 1 4 -18 2 11}d)1 1 2)))

Myślałem, że jestem sprytny, ale skończyło się to naiwnością w porównaniu z innymi odpowiedziami i znacznie dłużej.

Pobiera pierwsze 2 litery każdego ciągu ruchu, pobiera kody znaków i sumuje je. Następnie odejmuje sumy, aby uzyskać d. Jeśli dwynosi 0, to remis (0), jeśli jest w zbiorze #{5 -16 12 -14 13 1 4 -18 2 11}, p1 wygrywa (1), w przeciwnym razie p2 wygrywa (2).

(defn decide [& moves] ; Using varargs so I don't need to duplicate the steps.
  ; Pop the first 2 chars of each string, convert them to their ASCII code, and sum them.
  (let [[p1 p2] (map #(apply + (map int (take 2 %))) moves)
        d (- p1 p2)]

    (cond
      (= d 0) ; A tie
      0

      (#{5 -16 12 -14 13
         1 4 -18 2 11} d) ; P1 Wins
      1

      :else ; P2 Wins
      2)))

Uzyskałem „magiczne liczby”, które określają, czy P1 wygra

(let [ms ["rock", "paper", "scissors", "lizard", "spock"]]
  (for [p1 ms
        p2 ms]

    ; Same as above
    (let [[p q] (map #(apply + (map int (take 2 %))) [p1 p2])
          d (- p q)]

      [p1 p2 d])))

Która generuje listę dwartości dla każdego możliwego scenariusza:

(["rock" "rock" 0]
 ["rock" "paper" 16]
 ["rock" "scissors" 11]
 ["rock" "lizard" 12]
 ["rock" "spock" -2]
 ["paper" "rock" -16]
 ["paper" "paper" 0]
 ["paper" "scissors" -5]
 ["paper" "lizard" -4]
 ["paper" "spock" -18]
 ["scissors" "rock" -11]
 ["scissors" "paper" 5]
 ["scissors" "scissors" 0]
 ["scissors" "lizard" 1]
 ["scissors" "spock" -13]
 ["lizard" "rock" -12]
 ["lizard" "paper" 4]
 ["lizard" "scissors" -1]
 ["lizard" "lizard" 0]
 ["lizard" "spock" -14]
 ["spock" "rock" 2]
 ["spock" "paper" 18]
 ["spock" "scissors" 13]
 ["spock" "lizard" 14]
 ["spock" "spock" 0])

Następnie porównałem tabelę wygranych z tym wynikiem. Na szczęście nie było żadnych „kolizji” innych niż 0.

Carcigenicate
źródło