Chi vincerà un gioco Rock, Paper, Scissors, Lizard, Spock?


24

Ci sono alcune domande per quanto riguarda questo gioco , anche un contest qui . Ma penso che tutte quelle sfide e contest abbiano bisogno di un modo per determinare automaticamente il vincitore di una partita. Così:

Sfida

Dati due input nell'intervallo che ["rock", "paper", "scissors", "lizard", "spock"]rappresentano le selezioni per il giocatore 1 e il giocatore 2, determinare il vincitore della partita.

Regole

[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

restrizioni

  • L'input sarà una coppia di stringhe nell'intervallo indicato (non è possibile utilizzare altre stringhe). È possibile utilizzare matrici di caratteri se lo si desidera, purché rappresentino uno dei valori indicati.
  • È possibile scegliere se utilizzare le lettere minuscole, maiuscole ( "ROCK") o maiuscole ( "Rock") per le stringhe di input, purché il caso scelto sia lo stesso per tutti gli input.
  • L'output sarà un trio di valori che determinano il vincitore, che può essere tutto ciò che desideri purché le risposte siano coerenti. Esempio: 1se il primo input vince, 2se il secondo input vince, 0se c'è un pareggio. O forse Ase vince il primo input, Bse vince il secondo input, <empty string>se c'è un pareggio.

Obbiettivo

Questo è , quindi può vincere il programma / metodo / funzione / lambda più breve per ogni lingua!

test

[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

Questo viene dalla sandbox .
Charlie,


L'ho chiuso come duplicato della domanda collegata perché è la stessa domanda con 2 nuovi valori e una leggera variazione su IO.
Mago del grano,

4
@WheatWizard a volte un leggero cambiamento nell'input produce output molto diversi. Le domande possono essere abbastanza simili ma i due nuovi valori creano più casi da considerare, quindi gli algoritmi usati qui sono abbastanza diversi da far riflettere di nuovo le persone (vedi le risposte con il caketrucco).
Charlie,

4
Sono d'accordo e ho votato per riaprire.
GB

Risposte:


25

Python 3 , 68 50 48 byte

EDIT: grazie a 3 prese da Neil e 2 da Mr. Xcoder

Ogni stringa di input ha un quarto carattere distinto, quindi lo sto usando per distinguerli. Se disponi gli elementi nel ciclo (forbici, carta, roccia, lucertola, spock), ogni elemento batte l'elemento immediatamente dopo di esso e l'elemento 3 si posiziona a destra, ciclicamente. Quindi sottraggiamo le posizioni degli input nel ciclo. Se quel numero è 0, è un pareggio. Se è 1 o 3, è una vittoria per il primo giocatore. Nella mia soluzione originale, la differenza di ciclo sarebbe indicizzata nella stringa "210100" per distinguere i risultati del gioco. Neil in qualche modo ha capito che questo può essere realizzato senza indicizzare aggiungendo 7 e prendendo il modulo per 3. Modifica: originariamente ho usato il secondo carattere per identificare la stringa, ma se usi il quarto e inverti il ​​ciclo, ottieni una torta. E tutti potremmo usare più torta.

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

Provalo online!

Versione precedente:

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

Provalo online!

Versione originale:

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

Provalo online!



6
Benvenuti in PPCG!
Steadybox,

1
49 byte: provalo online! (passando .indexa .find)
Mr. Xcoder il

1
48 byte: provalo online! (non è necessario p, "chaoi"basta)
Mr. Xcoder

14

JavaScript (ES6), 56 byte

Accetta input nella sintassi del curry (a)(b). Restituisce 0se A vince, 1se B vince o falseper un pareggio.

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

dimostrazione

Come?

Definiamo la funzione hash H () come:

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

Questo da:

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

Dato due ingressi uno e B , si considerano le seguenti dichiarazioni:

  1. abbiamo a> b ? (in ordine lessicografico)
  2. non b vincere la partita?
  3. qual è il valore di N = H (a) XOR H (b) ?

Da (1) e (2), deduciamo se il risultato di a> b debba essere invertito per ottenere il vincitore corretto e memorizziamo questo flag nell'N-esimo bit di una maschera di bit di ricerca.

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

Da qui i bit:

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

Leggendolo dal basso verso l'alto e ignorando gli zeri iniziali , questo dà 1001100110 o 614 in decimale.


6

05AB1E , 16 byte

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

Provalo online! o come una suite di test

Spiegazione

Usa il caketrucco molto carino di 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

4

Rubino , 36 byte

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

Restituisce 0se il 1 ° giocatore vince, 1se il 2 ° giocatore vince e 2per un pareggio.

Basato sulla risposta dell'utente 507295 ma utilizza una formula matematica per eseguire l'hash. a.sumè la somma di tutti i codici ASCII della stringa a, mod 1<<16ed è intesa come checksum rudimentale. L'hash è stato trovato utilizzando il seguente codice:

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

Ciò ha prodotto due valori jche hanno dato un hash adatto per le lettere minuscole, vale a dire 88 e 80, entrambi i quali hanno dato la sequenza discendente [3,2,1,0,4](o [4,3,2,1,0]se lo spock è ciclicamente arrotondato all'inizio).

Come spiegato in altre risposte, per far funzionare la (h[a]-h[b])%5formula è necessario un hash che dia una differenza costante al modulo 5 per elementi consecutivi nella sequenza sopra . Ogni elemento batte l'elemento 1 o 3 posti a destra e perde l'elemento 2 o 4 posti a destra.

Provalo online!


4

JavaScript (ES6), 63 54 53 49 byte

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 of my golf to @ WhatToDo's answer. Nota: lo snippet decodifica il risultato numerico in qualcosa di leggermente meno illeggibile. Modifica: salvato 1 byte grazie a @Arnauld. 4 byte salvati grazie a @ovs.


@ovs Ugh, non ho portato il mio golf alla risposta di WhatToDo abbastanza forte ...
Neil,

3

C, 53bytes

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

Ho trattato questo problema come una macchina a stati, di cui ci sono 25 stati definiti dai due, cinque ingressi di stato.

Definendo i risultati degli stati all'interno di una matrice di bit. Cerco i risultati all'interno usando marcatori unici all'interno degli input.

Come notato in altre soluzioni, i caratteri 2, 3 e 4 sono univoci tra i possibili input. Ho concentrato l'uso sui caratteri 2 e 3 che utilizzo per selezionare il bit appropriato all'interno del mio array di risposte.

All'interno del carattere 2, i bit da 1 a 4 identificano chiaramente l'ingresso. Mascherando questi bit e spostando opportunamente [questo è "* y & 47 >> 1"], l'input può essere notato come 0, 1, 4, 7 o 8. Quindi la mia stringa di risposta ha 9 caratteri. (frammenti interessanti separati)

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

All'interno del carattere 3, i bit 0, 1 e 2 identificano chiaramente l'ingresso. Mascherando questi bit (spostamento non necessario) [questo è "* x & 7"], l'ingresso può essere notato come 0, 1, 2, 3 o 7. (frammenti interessanti separati)

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

La stringa di risposta può quindi essere calcolata semplicemente inserendo i bit per i caratteri appropriati.

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

Quindi, imposta bit in char dove Y vince

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

Quindi la logica è semplicemente: se il secondo carattere è lo stesso, disegna, altrimenti, ottieni il carattere ASCII in base al secondo carattere di y e sposta i bit dal terzo carattere di x e aggiungi uno. Questo rende le risposte 0 per pareggio, 1 per vittoria x e 2 per vittoria y.


Benvenuti in PPCG! Questa è un'ottima risposta ben ponderata.
FantaC,

1

Clojure, 130 118 byte

-12 byte eliminando il mio strano utilizzo di 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)))

Pensavo di essere intelligente, ma alla fine è stato ingenuo rispetto ad altre risposte e molto più a lungo.

Prende le prime 2 lettere di ogni stringa di spostamento, ottiene i codici char e li somma. Quindi sottrae le somme da ottenere d. Se dè 0, è un pareggio (0), se è nel set di #{5 -16 12 -14 13 1 4 -18 2 11}, p1 vince (1), altrimenti p2 vince (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)))

Per ottenere i "numeri magici" che definiscono se P1 vince, ho corso

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

Che genera un elenco di dvalori per ogni possibile scenario:

(["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])

Quindi ho confrontato il grafico delle vincite con questo risultato. Fortunatamente non ci sono state "collisioni" diverse da 0.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.