Stein, Papier, Schere, Eidechse, Spock [geschlossen]


16

Erstellen Sie eine Funktion, die zwei Zeichenfolgen als Eingabe verwendet und eine einzige Ausgabe für das Ergebnis zurückgibt. Die beliebteste Antwort gewinnt.

Die Regeln von Rock-Paper-Scissors-Lizard-Spock sind:

  • Schere schneiden Papier
  • Papier bedeckt Stein
  • Rock zerquetscht Eidechse
  • Eidechse vergiftet Spock
  • Spock zerschmettert eine Schere
  • Schere enthauptet Eidechse
  • Eidechse isst Papier
  • Papier widerlegt Spock
  • Spock verdampft den Stein
  • Rock bricht die Schere

Die Ausgabe für jeden möglichen Eingabefall ist:

winner('Scissors', 'Paper') -> 'Scissors cut Paper'
winner('Scissors', 'Rock') -> 'Rock breaks Scissors'
winner('Scissors', 'Spock') -> 'Spock smashes Scissors'
winner('Scissors', 'Lizard') -> 'Scissors decapitate Lizard'
winner('Scissors', 'Scissors') -> 'Scissors tie Scissors'
winner('Paper', 'Rock') -> 'Paper covers Rock'
winner('Paper', 'Spock') -> 'Paper disproves Spock'
winner('Paper', 'Lizard') -> 'Lizard eats Paper'
winner('Paper', 'Scissors') -> 'Scissors cut Paper'
winner('Paper', 'Paper') -> 'Paper ties Paper'
winner('Rock', 'Spock') -> 'Spock vaporizes Rock'
winner('Rock', 'Lizard') -> 'Rock crushes Lizard'
winner('Rock', 'Scissors') -> 'Rock breaks Scissors'
winner('Rock', 'Paper') -> 'Paper covers Rock'
winner('Rock', 'Rock') -> 'Rock ties Rock'
winner('Lizard', 'Rock') -> 'Rock crushes Lizard'
winner('Lizard', 'Spock') -> 'Lizard poisons Spock'
winner('Lizard', 'Scissors') -> 'Scissors decapitate Lizard'
winner('Lizard', 'Paper') -> 'Lizard eats Paper'
winner('Lizard', 'Lizard') -> 'Lizard ties Lizard'
winner('Spock', 'Rock') -> 'Spock vaporizes Rock'
winner('Spock', 'Lizard') -> 'Lizard poisons Spock'
winner('Spock', 'Scissors') -> 'Spock smashes Scissors'
winner('Spock', 'Paper') -> 'Paper disproves Spock'
winner('Spock', 'Spock') -> 'Spock ties Spock'

Zusätzliche von @Sean Cheshire vorgeschlagene Herausforderung: Zulassen von benutzerdefinierten Listen, z. B. von dieser Site. Mit der n-Item-Liste verliert das Item gegen das vorherige (n-1) / 2 und gewinnt über das folgende (n-1) / 2


7
Das Erstellen einer Nachschlagetabelle mit 25 Elementen ist keine Herausforderung, und beliebt zu sein ist keine Code-Herausforderung .
Peter Taylor

6
Und wenn ich sage, dass Populärsein keine Code-Herausforderung ist : Die Erklärung dieses Tags beginnt Eine Code-Herausforderung ist ein Wettbewerb für kreative Wege, um ein Programmierpuzzle für ein anderes objektives Kriterium als die Codegröße zu lösen. "Die beliebteste Antwort gewinnt" ist kein objektives Kriterium: Sie könnten nicht den Text von zwei Antworten an jemanden weitergeben und ihn fragen, welche die beliebteste ist.
Peter Taylor

1
@PeterTaylor, Dansalmo hat recht, solange sich diese Nachschlagetabelle in einer Schleife befindet: Dies ist ein berühmter Satz von Conway: en.wikipedia.org/wiki/FRACTRAN
Standby

1
@dansalmo Die Herausforderung, auf die Sie verlinken, wurde vor dem Vorhandensein des Beliebtheitswettbewerb- Tags erstellt.
Primo

1
Ein Vorschlag, der der Herausforderung hinzugefügt werden sollte: Ermöglichen Sie benutzerdefinierte Listen, z. B. von dieser Website , die bis zu 101 Elemente enthalten. Mit der n-Item-Liste verliert das Item gegen das vorherige (n-1) / 2 und gewinnt gegen das (n-1) / 2-Ergebnis
SeanC

Antworten:


13

APL

vs←{
    n←'Scissors' 'Paper' 'Rock' 'Lizard' 'Spock'
    x←n⍳⊂⍺ ⋄ y←n⍳⊂⍵ ⋄ X←⍺ ⋄ Y←⍵ ⋄ r←{X,⍵,⊂Y}
    x=y:     r (-x=0)↓'ties'
    y=5|1+x: r x⌷'cut' 'covers' 'crushes' 'poisons' 'smashes'
    y=5|3+x: r x⌷'decapitate' 'disproves' 'breaks' 'eats' 'vaporizes'
    ⍵∇⍺
}

In allen Fällen exakt die erforderliche Ausgabe, einschließlich Krawatten. Keine Nachschlagetabelle, außer den eigentlichen Wörtern.

Sie können es unter http://ngn.github.io/apl/web/ ausprobieren.

'Spock' vs 'Paper'
Paper  disproves  Spock

APL weiß es einfach!


+1, APL bis jetzt noch nie bemerkt. Faszinierend. Deine Struktur ist auch cool. Ich mag die letzte Zeile am besten.
Dansalmo

@dansalmo Danke :) Ich mag es sehr. Und jetzt haben wir dank github.com/ngn/apl einen Open Source und webfähigen Dolmetscher (jahrzehntelang gab es nur kommerzielle Dolmetscher)
Tobia

@dansalmo BTW, APL ist eine perfekte Ergänzung für die Art von funktionaler Codierung, die Sie in Python zu tun scheinen (was ich auch gerne mache)
Tobia

10

SED

#!/bin/sed
#expects input as 2 words, eg: scissors paper

s/^.*$/\L&/
s/$/;scissors cut paper covers rock crushes lizard poisons spock smashes scissors decapitates lizard eats paper disproves spock vaporizes rock breaks scissors/
t a
:a
s/^\(\w\+\)\s\+\(\w\+\);.*\1 \(\w\+\) \2.*$/\u\1 \3 \u\2/
s/^\(\w\+\)\s\+\(\w\+\);.*\2 \(\w\+\) \1.*$/\u\2 \3 \u\1/
t b
s/^\(\w\+\)\s\+\1;\(\1\?\(s\?\)\).*$/\u\1 tie\3 \u\1/
:b

1
Das ist ... teuflisch.
Wayne Conrad

4

Hier ist eine allgemeine Lösung, die auf einer Regelzeichenfolge beliebiger Größe basiert. Es führt die korrekte Groß- und Kleinschreibung für den Eigennamen "Spock" durch und erlaubt außerdem Regeln für die Angabe von "Krawatte" anstelle von "Krawatten" für mehrere Objekte.

def winner(p1, p2):
    rules = ('scissors cut paper covers rock crushes lizard poisons Spock'
    ' smashes scissors decapitate lizard eats paper disproves Spock vaporizes'
    ' rock breaks scissors tie scissors'.split())

    idxs = sorted(set(i for i, x in enumerate(rules) 
                      if x.lower() in (p1.lower(), p2.lower())))
    idx = [i for i, j in zip(idxs, idxs[1:]) if j-i == 2]
    s=' '.join(rules[idx[0]:idx[0]+3] if idx 
          else (rules[idxs[0]], 'ties', rules[idxs[0]]))
    return s[0].upper()+s[1:]

Ergebnisse:

>>> winner('spock', 'paper')
'Paper disproves Spock'
>>> winner('spock', 'lizard')
'Lizard poisons Spock'
>>> winner('Paper', 'lizard')
'Lizard eats paper'
>>> winner('Paper', 'Paper')
'Paper ties paper'
>>> winner('scissors',  'scissors')
'Scissors tie scissors'    

Bei der Definition können rulesSie anstelle der wörtlichen Verkettung eine mehrzeilige Zeichenfolge verwenden. Auf diese Weise können Sie die redundanten Klammern entfernen.
Bakuriu

3

Python

class Participant (object):
    def __str__(self): return str(type(self)).split(".")[-1].split("'")[0]
    def is_a(self, cls): return (type(self) is cls)
    def do(self, method, victim): return "%s %ss %s" % (self, method, victim)

class Rock (Participant):
        def fight(self, opponent):
                return (self.do("break", opponent)  if opponent.is_a(Scissors) else
                        self.do("crushe", opponent) if opponent.is_a(Lizard)   else
                        None)

class Paper (Participant):
        def fight(self, opponent):
                return (self.do("cover", opponent)    if opponent.is_a(Rock)  else
                        self.do("disprove", opponent) if opponent.is_a(Spock) else
                        None)

class Scissors (Participant):
        def fight(self, opponent):
                return (self.do("cut", opponent)       if opponent.is_a(Paper)  else
                        self.do("decaitate", opponent) if opponent.is_a(Lizard) else
                        None)

class Lizard (Participant):
        def fight(self, opponent):
                return (self.do("poison", opponent) if opponent.is_a(Spock) else
                        self.do("eat", opponent)    if opponent.is_a(Paper) else
                        None)

class Spock (Participant):
        def fight(self, opponent):
                return (self.do("vaporize", opponent) if opponent.is_a(Rock)     else
                        self.do("smashe", opponent)    if opponent.is_a(Scissors) else
                        None)

def winner(a, b):
    a,b = ( eval(x+"()") for x in (a,b))
    return a.fight(b) or b.fight(a) or a.do("tie", b)

Schere Plural sind, so "cut s " Papier und "decaitate s " Eidechse“falsch ist (die letzte verpasst ein P zu) Und. "Spock smashs zertrümmert "" sollte";)
daniero

@daniero, danke. Ich habe das Problem mit der Schere bemerkt, aber die Behebung erschwert die Sache. Behebung von "Smashes".
Ugoren

@ Daniel "Scissors" ist Plural. "Scissors" ist auch einzigartig. Siehe de.wiktionary.org/wiki/scissors
DavidC

So subtil. Liebe es.
kaoD

2

Python

def winner(p1, p2):
    actors = ['Paper', 'Scissors', 'Spock', 'Lizard', 'Rock']
    verbs = {'RoLi':'crushes', 'RoSc':'breaks', 'LiSp':'poisons',
             'LiPa':'eats', 'SpSc':'smashes', 'SpRo':'vaporizes', 
             'ScPa':'cut', 'ScLi':'decapitate', 'PaRo':'covers', 
             'PaSp':'disproves', 'ScSc':'tie'}
    p1, p2 = actors.index(p1), actors.index(p2)
    winner, loser = ((p1, p2), (p2, p1))[(1,0,1,0,1)[p1 - p2]]
    return ' '.join([actors[winner],
                     verbs.get(actors[winner][0:2] + actors[loser][0:2],
                               'ties'),
                     actors[loser]])

1
Übrigens ist "lockerer" das Gegenteil von "enger". "Loser" ist das Gegenteil von "Gewinner". Und Sie sparen ein paar Zeichen in Ihrem Code.
Joe

2

Ruby, arithmetischer Ansatz

Die Akteure können in einer Reihe so angeordnet werden, dass jeder Akteur a[i]gegen die Akteure gewinnt, a[i+1]und a[i+2]modulo 5 zum Beispiel:

%w(Scissors Lizard Paper Spock Rock)

Dann können wir für einen Schauspieler Amit Index isehen, wie er mit einem Schauspieler Bmit Index übereinstimmt, indem wir Folgendes jtun result = (j-i)%5: Ergebnis 1und 2bedeutet, dass Schauspieler A gegen einen Schauspieler 1 oder 2 Plätze vor ihm gewonnen hat; 3und 4bedeutet in ähnlicher Weise, dass er gegen einen Schauspieler hinter sich in der Reihe verloren hat. 0bedeutet ein Unentschieden. (Beachten Sie, dass dies sprachabhängig sein kann; in Ruby (j-i)%5 == (5+j-i)%5auch, wenn j>i.)

Der interessanteste Teil meines Codes ist die Verwendung dieser Eigenschaft, um eine Sortierfunktion der Indizes zweier Akteure zu finden. Der Rückgabewert wird -1, 0 oder 1 sein, wie es sollte :

winner,loser = [i,j].sort { |x,y| ((y-x)%5+1)/2-1 }

Hier ist das Ganze:

def battle p1,p2
    who = %w(Scissors Lizard Paper Spock Rock)
    how = %w(cut decapitate poisons eats covers disproves smashes vaporizes crushes breaks)
    i,j = [p1,p2].map { |s| who.find_index s }

    winner,loser = [i,j].sort { |x,y| ((y-x)%5+1)/2-1 }

    method = (winner-loser)%5/2
    what = method == 0 && "ties" || how[winner*2 + method-1]

    return "#{who[winner]} #{what} #{who[loser]}"
end

2

Python


  def winner(p,q):
        if p==q:
           return(' '.join([p,'tie',q]))
        d = {'ca':'cut','ao':'covers','oi':'crushes','ip':'poisons','pc': 'smashes','ci':'decapitate','ia':'eats', 'ap':'disproves', 'po':'vaporizes','oc': 'breaks'}
        [a,b] = [p[1],q[1]]
        try:
           return(' '.join([p,d[a+b],q]))
        except KeyError:
           return(' '.join([q,d[b+a],p]))

Mit einem kniffligen Wörterbuch.


Schön. return(' '.join([p,'tie' + 's'*(p[1]!='c'),q]))wird die Zeitform korrekt bekommen.
Dansalmo

2

C #

Annahmen

Die Gegner sind in einem n-Item-Array angeordnet, in dem die Spieler die (n-1) / 2 Spieler vor sich schlagen und gegen die (n-1) / 2 Spieler hinter sich verlieren. (Bei Listen mit gerader Länge verliert der Spieler gegen die ((n-1) / 2 + 1) Spieler dahinter)

Spieleraktionen sind in einem Array angeordnet, in dem Aktionen im Bereich von [(indexOfPlayer * (n-1) / 2)] bis [(indexOfPlayer * (n-1) / 2)) + (n-2) / 2-1 liegen ].

Zusätzliche Information

CircularBuffer<T>ist ein Wrapper um ein Array, um ein "unendlich" adressierbares Array zu erstellen. Die IndexOfFunktion gibt den Index eines Elements innerhalb der tatsächlichen Grenzen des Arrays zurück.

Die Klasse

public class RockPaperScissors<T> where T : IComparable
{
    private CircularBuffer<T> players;
    private CircularBuffer<T> actions;

    private RockPaperScissors() { }

    public RockPaperScissors(T[] opponents, T[] actions)
    {
        this.players = new CircularBuffer<T>(opponents);
        this.actions = new CircularBuffer<T>(actions);
    }

    public string Battle(T a, T b)
    {
        int indexA = players.IndexOf(a);
        int indexB = players.IndexOf(b);

        if (indexA == -1 || indexB == -1)
        {
            return "A dark rift opens in the side of the arena.\n" +
                   "Out of it begins to crawl a creature of such unimaginable\n" +
                   "horror, that the spectators very minds are rendered\n" +
                   "but a mass of gibbering, grey jelly. The horrific creature\n" +
                   "wins the match by virtue of rendering all possible opponents\n" +
                   "completely incapable of conscious thought.";
        }

        int range = (players.Length - 1) / 2;

        if (indexA == indexB)
        {
            return "'Tis a tie!";
        }
        else
        {
            indexB = indexB < indexA ? indexB + players.Length : indexB;
            if (indexA + range < indexB)
            {
                // A Lost
                indexB = indexB >= players.Length ? indexB - players.Length : indexB;
                int actionIndex = indexB * range + (indexA > indexB ? indexA - indexB : (indexA + players.Length) - indexB) - 1;

                return players[indexB] + " " + actions[actionIndex] + " " + players[indexA];
            }
            else
            {
                // A Won
                int actionIndex = indexA * range + (indexB - indexA) - 1;

                return players[indexA] + " " + actions[actionIndex] + " " + players[indexB];
            }
        }
    }
}

Beispiel

string[] players = new string[] { "Scissors", "Lizard", "Paper", "Spock", "Rock" };
string[] actions = new string[] { "decapitates", "cuts", "eats", "poisons", "disproves", "covers", "vaporizes", "smashes", "breaks", "crushes" };

RockPaperScissors<string> rps = new RockPaperScissors<string>(players, actions);

foreach (string player1 in players)
{
    foreach (string player2 in players)
    {
        Console.WriteLine(rps.Battle(player1, player2));
    }
}
Console.ReadKey(true);

1

Python, Einzeiler

winner=lambda a,b:(
    [a+" ties "+b]+
    [x for x in 
        "Scissors cut Paper,Paper covers Rock,Rock crushes Lizard,Lizard poisons Spock,Spock smashes Scissors,Scissors decapitate Lizard,Lizard eats Paper,Paper disproves Spock,Spock vaporizes Rock,Rock break Scissors"
        .split(',') 
     if a in x and b in x])[a!=b]

Sehr cool! Sie können .split(', ')und müssen nicht zusammen jammen.
Dansalmo

@dansalmo, Danke, aber ich sehe keinen Schaden in JammingTheRulesTogether. Obwohl es kein Golfwettbewerb ist, denke ich, je kürzer, desto besser.
Ugoren

1

Nur eine kleine Sache, die ich mir ausgedacht habe:

echo "winners('Paper', 'Rock')"|sed -r ":a;s/[^ ]*'([[:alpha:]]+)'./\1/;ta;h;s/([[:alpha:]]+) ([[:alpha:]]+)/\2 \1/;G"|awk '{while(getline line<"rules"){split(line,a," ");if(match(a[1],$1)&&match(a[3],$2))print line};close("rules")}' IGNORECASE=1

Hier ist rules die Datei, die alle Regeln enthält, die angegeben wurden.


0

Python

Inspiriert von @ Tobias APL-Code.

def winner(p1, p2):
  x,y = map(lambda s:'  scparolisp'.find(s.lower())/2, (p1[:2], p2[:2]))
  v = (' cut covers crushes poisons smashes'.split(' ')[x*(y in (x+1, x-4))] or
       ' decapitate disproves breaks eats vaporizes'.split(' ')[x*(y in (x+3, x-2))])
  return ' '.join((p1.capitalize(), v or 'tie'+'s'*(x!=1), p2)) if v or p1==p2 \
    else winner(p2, p1)

Ergebnisse:

>>> winner('Spock', 'paper')
'Paper disproves Spock'
>>> winner('Spock', 'lizard')
'Lizard poisons Spock'
>>> winner('paper', 'lizard')
'Lizard eats paper'
>>> winner('paper', 'paper')
'Paper ties paper'
>>> winner('scissors',  'scissors')
'Scissors tie scissors'    

0

C ++

#include <stdio.h>
#include <string>
#include <map>
using namespace std ;
map<string,int> type = { {"Scissors",0},{"Paper",1},{"Rock",2},{"Lizard",3},{"Spock",4} };
map<pair<int,int>, string> joiner = {
  {{0,1}, " cuts "},{{0,3}, " decapitates "}, {{1,2}, " covers "},{{1,4}, " disproves "},
  {{2,3}, " crushes "},{{2,0}, " crushes "},  {{3,4}, " poisons "},{{3,1}, " eats "},
  {{4,0}, " smashes "},{{4,2}, " vaporizes "},
} ;
// return 0 if first loses, return 1 if 2nd wins
int winner( pair<int,int> p ) {
  return (p.first+1)%5!=p.second && (p.first+3)%5!=p.second ;
}
string winner( string sa, string sb ) {
  pair<int,int> pa = {type[sa],type[sb]};
  int w = winner( pa ) ;
  if( w )  swap(pa.first,pa.second), swap(sa,sb) ;
  return sa+(pa.first==pa.second?" Ties ":joiner[pa])+sb ;
}

Ein bisschen wie ein Test

int main(int argc, const char * argv[])
{
  for( pair<const string&, int> a : type )
    for( pair<const string&, int> b : type )
      puts( winner( a.first, b.first ).c_str() ) ;
}

0

Javascript

function winner(c1,c2){
    var c = ["Scissors", "Paper", "Rock", "Lizard", "Spock"];
    var method={
        1:["cut", "covers", "crushes", "poisons", "smashes"],
        2:["decapitate", "disproves", "breaks", "eats", "vaporizes"]};
    //Initial hypothesis: first argument wins
    var win = [c.indexOf(c1),c.indexOf(c2)];
    //Check for equality
    var diff = win[0] - win[1];
    if(diff === 0){
        return c1 + ((win[0]===0)?" tie ":" ties ") + c2;
    }
    //If s is -1 we'll swap the order of win[] array
    var s = (diff>0)?1:-1;
    diff = Math.abs(diff);
    if(diff >2){
        diff = 5-diff;
        s= s * -1;
    }
    s=(diff==1)?s*-1:s;
    if(s === -1){
        win = [win[1],win[0]];
    }
    return c[win[0]] + " " + method[diff][win[0]] + " " + c[win[1]];
}

0

Javascript

Ich sehe, dass dies kein Golfwettbewerb ist, aber ich habe eine Weile an diesem Rätsel herumgespielt, bevor ich diesen Thread gefunden habe.

Hier ist eine (Standard-) js-Version mit 278 Zeichen:

function winner(a,b){var c={rock:0,paper:1,scissors:2,spock:3,lizard:4},d="crushe,crushe,cover,disprove,cut,decapitate,smashe,vaporize,poison,eat".split(","),i=c[a],j=c[b],I=i==(j+3)%5;return i^j?i==(j+1)%5||I?a+" "+d[i*2+I]+"s "+b:b+" "+d[j*2+(j==(i+3)%5)]+"s "+a:a+" ties "+b}

Oder eine mit E6-Funktionen (funktioniert wahrscheinlich nur in Firefox) in 259 Zeichen:

winner=(a,b,c={rock:0,paper:1,scissors:2,spock:3,lizard:4},d="crushe,crushe,cover,disprove,cut,decapitate,smashe,vaporize,poison,eat".split(","),i=c[a],j=c[b],I=i==(j+3)%5)=>i^j?i==(j+1)%5||I?a+" "+d[i*2+I]+"s "+b:b+" "+d[j*2+(j==(i+3)%5)]+"s "+a:a+" ties "+b
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.