Wer gewinnt ein Rock, Paper, Scissors, Lizard, Spock-Spiel?

24

Es gibt eine Reihe von Fragen in Bezug auf dieses Spiel , auch ein Wettbewerb hier . Aber ich denke, all diese Herausforderungen und Wettbewerbe erfordern eine Möglichkeit, den Gewinner eines Spiels automatisch zu ermitteln. So:

Herausforderung

Bestimmen Sie bei zwei Eingaben im Bereich, ["rock", "paper", "scissors", "lizard", "spock"]die die Auswahl für Spieler 1 und Spieler 2 darstellen, den Sieger des Spiels.

Regeln

[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

Beschränkungen

  • Die Eingabe erfolgt als Paar von Zeichenfolgen im angegebenen Bereich (es können keine anderen Zeichenfolgen verwendet werden). Wenn Sie möchten, können Sie Arrays von Zeichen verwenden, sofern diese einen der genannten Werte darstellen.
  • Sie können wählen, ob für die Eingabezeichenfolgen Kleinbuchstaben, Großbuchstaben ( "ROCK") oder Kamelbuchstaben ( "Rock") verwendet werden sollen, sofern die Groß- und Kleinschreibung für alle Eingaben gleich ist.
  • Es werden drei Werte ausgegeben, die den Gewinner bestimmen. Dies kann alles sein, was Sie wollen, solange die Antworten konsistent sind. Beispiel: 1Wenn der erste Eingang gewinnt, 2wenn der zweite Eingang gewinnt, 0wenn ein Gleichstand besteht. Oder vielleicht, Awenn der erste Eingang gewinnt, Bwenn der zweite Eingang gewinnt, <empty string>wenn es ein Unentschieden gibt.

Tor

Das ist , also kann das kürzeste Programm / die kürzeste Methode / Funktion / Lambda für jede Sprache gewinnen!

Tests

[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
quelle
Das kommt aus dem Sandkasten .
Charlie
1
Sehr verwandt .
Stewie Griffin
Ich habe es als Duplikat der verknüpften Frage geschlossen, da es sich um dieselbe Frage mit zwei neuen Werten und einer geringfügigen Variation von IO handelt.
Weizen-Zauberer
4
@WheatWizard Manchmal führt eine geringfügige Änderung der Eingabe zu sehr unterschiedlichen Ausgaben. Die Fragen mögen sich sehr ähnlich sein, aber die beiden neuen Werte schaffen mehr zu berücksichtigende Fälle. Die hier verwendeten Algorithmen sind also unterschiedlich genug, um die Leute zum Nachdenken zu bewegen (siehe die Antworten mit dem cakeTrick).
Charlie
4
Ich stimme zu und habe für die Wiedereröffnung gestimmt.
GB

Antworten:

25

Python 3 , 68 50 48 Bytes

EDIT: Dank 3 Tricks von Neil und 2 von Mr. Xcoder

Jede Eingabezeichenfolge hat ein unterschiedliches viertes Zeichen, daher benutze ich dieses, um sie zu unterscheiden. Wenn Sie die Elemente im Zyklus anordnen (Schere, Papier, Stein, Eidechse, Spock), schlägt jedes Element das Element direkt danach, und das Element 3 wird zyklisch nach rechts verschoben. Wir subtrahieren also die Positionen der Eingänge im Zyklus. Wenn diese Zahl 0 ist, ist es ein Unentschieden. Wenn es 1 oder 3 ist, ist es ein Gewinn für den ersten Spieler. In meiner ursprünglichen Lösung würde die Zyklusdifferenz in die Zeichenfolge "210100" indiziert, um die Ergebnisse des Spiels zu unterscheiden. Neil hat irgendwie herausgefunden, dass dies ohne Indizierung erreicht werden kann, indem er 7 addiert und den Modul durch 3 nimmt. Bearbeiten: Ursprünglich habe ich das zweite Zeichen verwendet, um die Zeichenfolge zu identifizieren. Und wir könnten alle mehr Kuchen gebrauchen.

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

Probieren Sie es online!

Ältere Version:

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

Probieren Sie es online!

Originalfassung:

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

Probieren Sie es online!

Was ist zu tun
quelle
1
50 Bytes: Probieren Sie es online!
Neil
6
Willkommen bei PPCG!
Steadybox
1
49 Bytes: Probieren Sie es online! (wechselt .indexzu .find)
Mr. Xcoder
1
48 Bytes: Probieren Sie es online! (Sie brauchen das nicht p, "chaoi"reicht aus)
Mr. Xcoder
14

JavaScript (ES6), 56 Byte

Übernimmt Eingaben in der Currying-Syntax (a)(b). Gibt zurück, 0wenn A gewinnt, 1wenn B gewinnt oder falsefür ein Unentschieden.

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

Demo

Wie?

Wir definieren die Hash-Funktion H () als:

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

Das gibt:

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

Bei zwei Eingaben a und b betrachten wir die folgenden Aussagen:

  1. haben wir einen> b ? (in lexikographischer Reihenfolge)
  2. gewinnt b das spiel
  3. Was ist der Wert von N = H (a) XOR H (b) ?

Aus (1) und (2) leiten wir ab, ob das Ergebnis von a> b invertiert werden soll, um den richtigen Gewinner zu erhalten, und speichern dieses Flag im N-ten Bit einer Nachschlagebitmaske.

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

Daher die Bits:

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

Wenn Sie dies von unten nach oben lesen und führende Nullen ignorieren, erhalten Sie 1001100110 oder 614 als Dezimalzahl.

Arnauld
quelle
5

05AB1E , 16 Bytes

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

Probieren Sie es online! oder als Test Suite

Erläuterung

Verwendet den sehr netten cake-trick von 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
quelle
4

JavaScript (ES6), 63 54 53 49 Bytes

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 von meinem Golf auf @ WhatToDo Antwort. Hinweis: Das Snippet dekodiert das numerische Ergebnis in etwas weniger Unlesbares. Bearbeiten: 1 Byte dank @Arnauld gespeichert. 4 Bytes dank @ovs gespeichert.

Neil
quelle
@ovs Ugh, ich habe mein Golf nicht hart genug auf WhatToDos Antwort portiert ...
Neil
3

Ruby , 36 Bytes

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

Gibt zurück, 0wenn der 1. Spieler gewinnt, 1wenn der 2. Spieler gewinnt, und 2für ein Unentschieden.

Basierend auf der Antwort von user507295, verwendet jedoch eine mathematische Formel, um den Hash auszuführen. a.sumist die Summe aller ASCII-Codes des Strings amod 1<<16und ist als rudimentäre Prüfsumme gedacht. Der Hash wurde mit dem folgenden Code gefunden:

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

Dies jergab zwei Werte , die einen geeigneten Hash für Kleinbuchstaben ergaben, nämlich 88 und 80, die beide die absteigende Reihenfolge ergaben [3,2,1,0,4](oder[4,3,2,1,0] wenn Spock an den Anfang gedreht wird).

Wie in anderen Antworten erläutert, wird ein Hash benötigt, der für aufeinanderfolgende Elemente in der obigen Sequenz ein konstantes Differenzmodul 5 ergibt, damit die (h[a]-h[b])%5Formel funktioniert. Jedes Element schlägt das Element um 1 oder 3 Stellen nach rechts und verliert gegen das Element um 2 oder 4 Stellen nach rechts.

Probieren Sie es online!

Level River St
quelle
3

C 53 Bytes

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

Ich habe dieses Problem als eine Zustandsmaschine behandelt, von der es 25 Zustände gibt, wie durch die zwei, fünf Zustandseingaben definiert.

Durch Definieren der Ergebnisse der Zustände in einem Array von Bits. Ich überprüfe die Ergebnisse anhand eindeutiger Markierungen in den Eingaben.

Wie in anderen Lösungen erwähnt, sind die Zeichen 2, 3 und 4 zwischen den möglichen Eingaben eindeutig. Ich habe mich auf die Zeichen 2 und 3 konzentriert, mit denen ich das entsprechende Bit in meinem Antwortfeld auswähle.

Innerhalb von Zeichen 2 kennzeichnen die Bits 1 bis 4 die Eingabe eindeutig. Durch Maskieren dieser Bits und entsprechendes Verschieben [das ist das "* y & 47 >> 1"] kann die Eingabe als 0, 1, 4, 7 oder 8 notiert werden. Daher hat meine Antwortzeichenfolge 9 Zeichen. (getrennte interessante Bits)

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

Innerhalb des Zeichens 3 kennzeichnen die Bits 0, 1 und 2 den Eingang eindeutig. Durch Maskieren dieser Bits (Verschieben nicht erforderlich) [das ist das "* x & 7"] kann die Eingabe als 0, 1, 2, 3 oder 7 notiert werden. (getrennte interessante Bits)

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

Die Antwortzeichenfolge kann dann berechnet werden, indem einfach die Bits für die entsprechenden Zeichen eingegeben werden.

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

Also setze ein Bit in char, wo Y gewinnt

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

Dann lautet die Logik einfach: Wenn das zweite Zeichen dasselbe ist, dann zeichne, andernfalls erhalte ASCII-Zeichen basierend auf dem zweiten Zeichen von y und verschiebe Bits um das dritte Zeichen von x und addiere eins. Dies macht die Antworten 0 für Unentschieden, 1 für x gewinnen und 2 für y gewinnen.

meismich
quelle
Willkommen bei PPCG! Dies ist eine großartige, gut durchdachte Antwort.
FantaC
1

Clojure, 130 118 Bytes

-12 Bytes durch meine seltsame Verwendung von loszuwerden 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)))

Ich dachte, ich wäre schlau, aber im Vergleich zu einigen anderen Antworten war das naiv und vieles mehr länger.

Nimmt die ersten 2 Buchstaben jeder Bewegungszeichenfolge, erhält die Zeichencodes und summiert sie. Es subtrahiert dann die Summen, um zu erhalten d. Wenn d0 ist, ist es ein Gleichstand (0), wenn es in der Menge von ist #{5 -16 12 -14 13 1 4 -18 2 11}, gewinnt p1 (1), sonst gewinnt p2 (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)))

Um die "magischen Zahlen" zu erhalten, die definieren, ob P1 gewinnt, bin ich gelaufen

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

Welche generiert eine Liste von dWerten für jedes mögliche Szenario:

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

Dann habe ich die Gewinnchart mit dieser Ausgabe verglichen. Zum Glück gab es außer 0 keine "Kollisionen".

Karzigenat
quelle