Batu, Kertas, Gunting, Kadal, Spock [ditutup]


16

Buat fungsi yang akan mengambil dua string sebagai input dan mengembalikan satu output untuk hasilnya. Jawaban yang paling populer menang.

Aturan-aturan Rock-paper-scissors-lizard-Spock adalah:

  • Gunting memotong kertas
  • Kertas menutupi batu
  • Kadal menghancurkan batu
  • Kadal meracuni Spock
  • Spock menghancurkan gunting
  • Gunting memenggal kadal
  • Kadal makan kertas
  • Kertas membuktikan Spock
  • Spock menguapkan batu
  • Pemecah batu gunting

Output untuk setiap kasus input yang mungkin adalah:

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'

Tantangan ekstra yang disarankan oleh @Sean Cheshire: Izinkan daftar khusus, seperti yang dari situs ini. Dengan daftar n-item, item kehilangan ke (n-1) / 2 sebelumnya, dan menang atas (n-1) / 2 berikut


7
Membuat tabel pencarian 25-elemen bukanlah tantangan, dan menjadi populer bukanlah tantangan kode .
Peter Taylor

6
Dan ketika saya mengatakan bahwa menjadi populer bukanlah tantangan kode : penjelasan tag itu dimulai . Tantangan kode adalah kompetisi cara kreatif untuk memecahkan teka-teki pemrograman untuk kriteria objektif selain ukuran kode. "Sebagian besar jawaban populer menang" bukan kriteria objektif: Anda tidak bisa memberikan teks dua jawaban kepada seseorang dan bertanya kepada mereka yang mana yang paling populer.
Peter Taylor

1
@PeterTaylor, dansalmo benar, selama tabel pencarian dalam satu lingkaran: ini adalah teorema Conway yang terkenal: en.wikipedia.org/wiki/FRACTRAN
boothby

1
@dansalmo Tantangan yang Anda tautkan dibuat sebelum adanya tag kontes-popularitas .
Primo

1
Saran untuk ditambahkan ke tantangan - Izinkan daftar kustom, seperti yang dari situs ini yang mencapai hingga 101 item. Dengan daftar n-item, item kalah dari (n-1) / 2 sebelumnya, dan menang atas (n-1) / 2 follwing
SeanC

Jawaban:


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'
    ⍵∇⍺
}

Keluaran persis seperti yang disyaratkan dalam semua kasus, termasuk dasi / dasi. Tidak ada tabel pencarian, kecuali kata-kata yang sebenarnya.

Anda dapat mencobanya di http://ngn.github.io/apl/web/

'Spock' vs 'Paper'
Paper  disproves  Spock

APL hanya tahu!


+1, Tidak pernah memperhatikan APL hingga sekarang. Mempesona. Struktur Anda juga keren. Saya suka baris terakhir yang terbaik.
dansalmo

@dansalmo Terima kasih :) Saya sangat menyukainya. Dan sekarang terima kasih kepada github.com/ngn/apl kami memiliki sumber terbuka dan penerjemah siap-web (selama beberapa dekade hanya ada penerjemah komersial)
Tobia

@dansalmo btw, APL sangat cocok untuk jenis pengkodean fungsional yang tampaknya Anda lakukan dengan Python (yang saya juga ingin lakukan)
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
Ini ... jahat.
Wayne Conrad

4

Berikut adalah solusi umum berdasarkan string aturan ukuran berapa pun. Ini melakukan huruf besar yang benar untuk nama yang tepat "Spock" dan juga memungkinkan aturan untuk menentukan 'dasi' bukan 'ikatan' untuk objek jamak.

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

Hasil:

>>> 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'    

Saat mendefinisikan, rulesAnda dapat menggunakan string multiline alih-alih penggabungan literal. Ini memungkinkan Anda untuk menghapus tanda kurung yang berlebihan.
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)

Gunting yang plural, sehingga "memotong s " kertas dan "decaitate s " kadal" adalah salah (yang terakhir merindukan P juga) Dan. 'Spock smashs ' harus 'smash';)
daniero

@daniero, terima kasih. Saya perhatikan masalah gunting, tetapi memperbaikinya mempersulit. Memperbaiki "smash" sekarang.
ugoren

@Daniel "Gunting" jamak. "Gunting" juga tunggal. Lihat en.wiktionary.org/wiki/scissors
DavidC

Sangat halus. Suka.
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
By the way, "lebih longgar" adalah kebalikan dari "lebih ketat". "Pecundang" adalah kebalikan dari "pemenang". Dan itu akan menghemat beberapa karakter dalam kode Anda.
Joe

2

Ruby, pendekatan aritmatika

Para aktor dapat diatur dalam susunan sedemikian rupa sehingga masing-masing aktor a[i]menang melawan para aktor a[i+1]dan a[i+2], modulo 5, misalnya:

%w(Scissors Lizard Paper Spock Rock)

Kemudian, untuk seorang aktor Adengan indeks ikita dapat melihat bagaimana dia cocok Bdengan aktor dengan indeks jdengan melakukan result = (j-i)%5: Hasil 1dan 2berarti bahwa aktor A menang melawan aktor 1 atau 2 tempat di depannya masing-masing; 3dan 4juga berarti dia kalah melawan aktor di belakangnya dalam array. 0berarti dasi. (Perhatikan bahwa ini mungkin tergantung pada bahasa; di Ruby (j-i)%5 == (5+j-i)%5juga kapanj>i .)

Bagian paling menarik dari kode saya adalah penggunaan properti ini untuk menemukan fungsi penyortiran indeks dua aktor. Nilai kembali akan -1, 0 atau 1 sebagaimana mestinya :

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

Ini semuanya:

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

Menggunakan kamus yang rumit.


Bagus return(' '.join([p,'tie' + 's'*(p[1]!='c'),q]))akan mendapatkan kata kerja yang benar.
dansalmo

2

C #

Asumsi

Lawan disusun dalam array n-item di mana pemain mengalahkan (n-1) / 2 pemain di depan mereka dan kalah dari (n-1) / 2 pemain di belakang mereka. (Dengan daftar panjang genap, pemain kalah dari ((n-1) / 2 + 1) pemain di belakang mereka)

Tindakan pemain diatur dalam larik di mana tindakan dalam kisaran [(indexOfPlayer * (n-1) / 2)] hingga [(indexOfPlayer * (n-1) / 2)) + (n-2) / 2 - 1 ]

Informasi tambahan

CircularBuffer<T>adalah pembungkus array untuk membuat array addressable "tak terbatas". The IndexOfmengembalikan fungsi indeks item dalam batas-batas yang sebenarnya dari array.

Kelas

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

Contoh

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, satu garis

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]

Sangat keren! Anda bisa .split(', ')dan tidak harus macet, aturan, bersama.
dansalmo

@dansalmo, Terima kasih, Tapi saya tidak melihat ada salahnya di JammingTheRulesTogether. Meskipun ini bukan kontes golf, saya pikir semakin pendek semakin baik.
ugoren

1

Hanya hal kecil yang saya dapatkan:

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

Di sini, aturan adalah file yang berisi semua aturan yang diberikan.


0

Python

Terinspirasi oleh kode APL @ Tobia.

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)

Hasil:

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

Sedikit ujian

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

Saya melihat ini bukan kontes golf, tapi saya sudah mengotak-atik puzzle ini untuk sementara waktu sebelum menemukan utas ini, jadi begini.

Berikut ini adalah versi (standar) js dalam 278 karakter:

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}

Atau yang menggunakan fitur E6 (kemungkinan hanya berfungsi di Firefox) dalam 259 karakter:

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.