Đá, Giấy, Kéo, Thằn lằn, Spock [đóng]


16

Tạo một hàm sẽ lấy hai chuỗi làm đầu vào và trả về một đầu ra duy nhất cho kết quả. Câu trả lời phổ biến nhất chiến thắng.

Các quy tắc của Rock-paper-kéo-lizard-Spock là:

  • Kéo cắt giấy
  • Giấy bìa đá
  • Đá nghiền nát thằn lằn
  • Thằn lằn độc Spock
  • Spock đập kéo
  • Kéo thằn lằn
  • Thằn lằn ăn giấy
  • Giấy từ chối Spock
  • Spock bốc hơi đá
  • Đá phá vỡ kéo

Đầu ra cho mọi trường hợp đầu vào có thể là:

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'

Thử thách thêm được đề xuất bởi @Sean Cheshire: Cho phép danh sách tùy chỉnh, chẳng hạn như những danh sách từ trang web này. Với danh sách n-item, vật phẩm sẽ thua (n-1) / 2 trước đó và chiến thắng (n-1) / 2 sau


7
Tạo bảng tra cứu gồm 25 phần tử không phải là một thách thức và phổ biến không phải là một thách thức về mã .
Peter Taylor

6
Và khi tôi nói rằng việc phổ biến không phải là một thách thức về mã : giải thích về thẻ đó bắt đầu Thử thách mã là một cuộc cạnh tranh cho các cách sáng tạo để giải câu đố lập trình cho một tiêu chí khách quan khác với kích thước mã. "Chiến thắng câu trả lời phổ biến nhất" không phải là một tiêu chí khách quan: bạn không thể đưa văn bản của hai câu trả lời cho ai đó và hỏi họ câu nào là phổ biến nhất.
Peter Taylor

1
@PeterTaylor, dansalmo là đúng, miễn là bảng tra cứu đó nằm trong một vòng lặp: đây là một định lý nổi tiếng của Conway: en.wikipedia.org/wiki/FRACTRAN
boothby 21/07/13

1
@dansalmo Thử thách bạn liên kết được tạo ra trước sự tồn tại của thẻ cuộc thi phổ biến .
primo

1
Một đề xuất để thêm vào thử thách - Cho phép các danh sách tùy chỉnh, chẳng hạn như các danh sách từ trang web này có tới 101 mục. Với danh sách n-item, vật phẩm sẽ thua (n-1) / 2 trước đó và giành chiến thắng trước (n-1) / 2 follwing
SeanC

Câu trả lời:


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

Đầu ra chính xác theo yêu cầu trong mọi trường hợp, bao gồm cả cà vạt / cà vạt. Không có bảng tra cứu, ngoại trừ các từ thực tế.

Bạn có thể dùng thử trên http://ngn.github.io/apl/web/

'Spock' vs 'Paper'
Paper  disproves  Spock

APL chỉ biết!


+1, Chưa bao giờ nhận thấy APL cho đến bây giờ. Mê hoặc. Cấu trúc của bạn cũng rất tuyệt Tôi thích dòng cuối cùng là tốt nhất.
dansalmo

@dansalmo Cảm ơn :) Tôi thích nó rất nhiều. Và bây giờ nhờ có github.com/ngn/apl, chúng tôi có một trình thông dịch mã nguồn mở và sẵn sàng cho web (trong nhiều thập kỷ chỉ có các thông dịch viên thương mại)
Tobia

@dansalmo btw, APL là một sự phù hợp hoàn hảo cho loại mã hóa chức năng mà bạn dường như đang làm trong Python (mà tôi cũng muốn làm như vậy)
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
Đây là ... ma quỷ.
Wayne Conrad

4

Đây là một giải pháp chung dựa trên chuỗi quy tắc có kích thước bất kỳ. Nó thực hiện viết hoa đúng cho tên thích hợp "Spock" và cũng cho phép các quy tắc chỉ định 'tie' thay vì 'tie' cho các đối tượng số nhiều.

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

Các kết quả:

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

Khi xác định, rulesbạn có thể sử dụng một chuỗi nhiều dòng thay vì nối theo nghĩa đen. Điều này cho phép bạn loại bỏ các dấu ngoặc thừa.
Bakuriu

3

Con trăn

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)

Kéo là số nhiều, vì vậy "cắt s " giấy và "decaitate s " thằn lằn" là sai (người cuối cùng bỏ lỡ một P quá) Và. 'Spock smashs ' cần được 'đập vỡ';)
daniero

@daniero, cảm ơn. Tôi nhận thấy vấn đề kéo, nhưng sửa nó làm phức tạp mọi thứ. Sửa "đập" ngay.
ugoren

@Daniel "Kéo" là số nhiều. "Kéo" cũng là số ít. Xem en.wiktionary.org/wiki/sc khoa
DavidC

Thật tinh tế. Yêu nó.
kaoD

2

Con trăn

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
Nhân tiện, "lỏng lẻo" là trái ngược với "chặt chẽ hơn". "Người thua cuộc" trái ngược với "người chiến thắng". Và nó sẽ giúp bạn tiết kiệm một vài ký tự trong mã của bạn.
Joe

2

Ruby, cách tiếp cận số học

Các diễn viên có thể được sắp xếp thành một mảng theo cách mà mỗi diễn viên a[i]giành chiến thắng trước các diễn viên a[i+1]a[i+2], ví dụ, modulo 5:

%w(Scissors Lizard Paper Spock Rock)

Sau đó, đối với một diễn viên Acó chỉ số, ichúng ta có thể thấy cách anh ta khớp với diễn viên Bvới chỉ số jbằng cách thực hiện result = (j-i)%5: Kết quả 12có nghĩa là diễn viên A đã giành chiến thắng trước một diễn viên 1 hoặc 2 vị trí trước mặt anh ta; 34tương tự có nghĩa là anh ta thua trước một diễn viên đằng sau anh ta trong mảng. 0có nghĩa là cà vạt. (Lưu ý rằng điều này có thể phụ thuộc vào ngôn ngữ; trong Ruby (j-i)%5 == (5+j-i)%5cũng có khi j>i.)

Phần thú vị nhất trong mã của tôi là việc sử dụng thuộc tính này để tìm hàm sắp xếp các chỉ số của hai diễn viên. Giá trị trả về sẽ là -1, 0 hoặc 1 như mong muốn :

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

Đây là toàn bộ:

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

Con trăn


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

Sử dụng một từ điển khó khăn.


Đẹp một. return(' '.join([p,'tie' + 's'*(p[1]!='c'),q]))sẽ nhận được các động từ đúng.
dansalmo

2

C #

Giả định

Các đối thủ được sắp xếp trong một mảng n-item trong đó người chơi đánh bại (n-1) / 2 người chơi trước họ và thua (n-1) / 2 người chơi phía sau họ. (Với danh sách độ dài chẵn, người chơi sẽ thua những người chơi ((n-1) / 2 + 1) phía sau họ)

Các hành động của người chơi được sắp xếp trong một mảng trong đó các hành động trong phạm vi [(indexOfPlayer * (n-1) / 2)] thành [(indexOfPlayer * (n-1) / 2)) + (n-2) / 2 - 1 ].

Thông tin bổ sung

CircularBuffer<T>là một trình bao bọc xung quanh một mảng để tạo ra một mảng có thể định địa chỉ "vô hạn". Các IndexOfhàm trả về chỉ số của một mục trong phạm vi thực tế của mảng.

Lớp

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

Thí dụ

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, một lớp lót

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]

Rất tuyệt! Bạn có thể .split(', ')và không phải kẹt, các, quy tắc, cùng nhau.
dansalmo

@dansalmo, Cảm ơn, nhưng tôi thấy không có hại trong JammingTheRulesTogether. Mặc dù nó không phải là một cuộc thi golf, tôi nghĩ càng ngắn càng tốt.
ugoren

1

Chỉ là một điều nhỏ tôi nghĩ ra:

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

Ở đây, quy tắc là tệp chứa tất cả các quy tắc đã được đưa ra.


0

Con trăn

Lấy cảm hứng từ mã APL của @ 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)

Các kết quả:

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

Một chút kiểm tra

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

Tôi thấy đây không phải là một cuộc thi đánh gôn, nhưng tôi đã loay hoay với câu đố này một thời gian trước khi tìm ra chủ đề này, vì vậy hãy đến đây.

Đây là phiên bản js (tiêu chuẩn) với 278 ký tự:

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}

Hoặc một tính năng sử dụng các tính năng E6 (có thể chỉ hoạt động trong Firefox) với 259 ký tự:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.