록, 페이퍼, 가위, 도마뱀, 스팍 게임에서 누가 이길까요?


24

있다 이 게임에 대한 몇 가지 질문 , 심지어 대회 여기가 . 그러나 모든 도전과 콘테스트는 게임의 승자를 자동으로 결정하는 방법이 필요하다고 생각합니다. 그래서:

도전

["rock", "paper", "scissors", "lizard", "spock"]플레이어 1과 플레이어 2에 대한 선택을 나타내는 범위에 2 개의 입력이 주어지면 경기의 승자를 결정하십시오.

규칙

[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

제한 사항

  • 입력은 주어진 범위에서 한 쌍의 문자열이됩니다 (다른 문자열은 사용할 수 없습니다). 언급 된 값을 나타내는 한 원하는 경우 문자 배열을 사용할 수 있습니다.
  • 선택한 대소 문자가 모든 입력에 대해 동일하다면 입력 문자열에 소문자, 대문자 ( "ROCK") 또는 낙타 ( ) 를 사용할지 여부를 선택할 수 있습니다 "Rock".
  • 결과는 승자를 결정하는 3 가지 값의 트리오 (trio)가 될 것이며, 답변이 일관된 한 원하는 것이 될 수 있습니다. 예 : 1첫 번째 입력이 이기고 2두 번째 입력이 이기면 0동점이있는 경우 또는 A첫 번째 입력이 이기고 B두 번째 입력이 이기면 타이가있는 <empty string>경우가 있습니다.

이것은 이므로 각 언어마다 가장 짧은 프로그램 / 방법 / 함수 / 람다가 이길 수 있습니다!

테스트

[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

이것은 샌드 박스 에서 온 입니다.
찰리


나는 2 개의 새로운 값과 IO에 약간의 변화가있는 동일한 질문이므로 링크 된 질문의 복제본으로 닫았습니다.
밀 마법사

4
@WheatWizard는 때때로 입력의 약간의 변화가 매우 다른 출력을 생성합니다. 질문은 매우 비슷하지만 두 가지 새로운 값을 사용하면 더 많은 사례를 고려해야하므로 여기에 사용 된 알고리즘은 사람들이 다시 생각하게 할만큼 충분히 다릅니다 ( cake트릭으로 답을보십시오 ).
찰리

4
동의하고 다시 열기로 투표했습니다.
GB

답변:


25

파이썬 3 , 68 50 48 바이트

편집 : Neil의 3 가지 트릭과 Xcoder의 2 가지 트릭 덕분에

각 입력 문자열에는 고유 한 네 번째 문자가 있으므로이를 구별하기 위해 사용하고 있습니다. 사이클에서 요소 (가위, 종이, 바위, 도마뱀, 스팍)를 정렬하면 각 요소가 요소 바로 다음에 이기고 요소 3이 주기적으로 오른쪽으로 이동합니다. 따라서 사이클에서 입력 위치를 뺍니다. 해당 숫자가 0이면 동점입니다. 1 또는 3이면 첫 번째 플레이어의 승리입니다. 내 원래 솔루션에서 사이클 차이는 문자열 "210100"으로 색인되어 게임 결과를 구별합니다. Neil은 어떻게 든 7을 추가하고 모듈러스를 3으로 가져 와서 색인을 생성하지 않고도이 작업을 수행 할 수 있다고 생각했습니다. 그리고 우리는 더 많은 케이크를 사용할 수 있습니다.

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

온라인으로 사용해보십시오!

이전 버전 :

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

온라인으로 사용해보십시오!

원본 버전 :

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

온라인으로 사용해보십시오!



6
PPCG에 오신 것을 환영합니다!
Steadybox

1
49 바이트 : 온라인으로 사용해보십시오! (스위칭 .index.find)
씨 Xcoder

1
48 바이트 : 온라인으로 사용해보십시오! (당신은 필요하지 않습니다 p, "chaoi"충분합니다)
Mr. Xcoder

14

자바 스크립트 (ES6), 56 바이트

카레 구문으로 입력을 (a)(b)받습니다. 0A가 이기면 1B가이기거나 false넥타이를 반환 합니다 .

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

데모

방법?

해시 함수 H () 를 다음과 같이 정의합니다 .

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

이것은 다음을 제공합니다.

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

두 개의 입력 ab가 주어지면 다음 문장을 고려합니다.

  1. 우리는 > b를 가지고 있습니까? (사전 순서)
  2. 않는 B는 게임을 승리?
  3. N = H (a) XOR H (b) 의 값은 무엇 입니까?

(1)과 (2) 에서 올바른 승자를 얻기 위해 a> b 의 결과를 반전 해야하는지 여부를 추론 하고이 플래그를 조회 비트 마스크 의 N 번째 비트에 저장합니다 .

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

따라서 비트 :

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

이것을 아래에서 위로 읽고 선행 0을 무시하면 1001100110 또는 614 가 10 진수로 나타납니다.



4

자바 스크립트 (ES6), 63 54 53 49 바이트

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

@WhatToDo의 답변에 내 골프 포트. 참고 :이 스 니펫은 숫자 결과를 읽을 수없는 내용으로 디코딩합니다. 편집 : @ Arnauld 덕분에 1 바이트가 절약되었습니다. @ovs 덕분에 4 바이트가 절약되었습니다.


@ovs Ugh, 나는 내 골프를 WhatToDo의 대답으로 충분히 포팅하지 않았다 ...
Neil

3

루비 , 36 바이트

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

보고 0첫 번째 플레이어가 이길 1경우, 두 번째 플레이어가 이길 경우, 그리고 2추첨을 위해 합니다 .

user507295의 답변을 기반으로하지만 수학 공식을 사용하여 해시를 수행합니다. a.sum문자열의 모든 ASCII 코드의 합계입니다 a. mod1<<16 기본적인 체크섬으로 사용됩니다. 해시는 다음 코드를 사용하여 발견되었습니다.

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

이것은 두 가지 가치를 만들어 냈다 j 소문자, 즉 88과 80에 적합한 해시를 제공하는 . 둘 다 내림차순을 나타냅니다 [3,2,1,0,4](또는 [4,3,2,1,0]spock이 처음으로 순환되는 경우).

다른 답변에서 설명했듯이 위 시퀀스의 연속 요소에 대해 일정한 차이 모듈로 5를주는 해시가 필요합니다. (h[a]-h[b])%5 공식이 작동 . 각 요소는 요소 1 또는 3을 오른쪽으로 치고 요소 2 또는 4를 오른쪽으로 잃습니다.

온라인으로 사용해보십시오!


3

C, 53 바이트

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

이 문제를 상태 머신으로 취급했는데, 2, 5 개의 상태 입력으로 정의 된 25 개의 상태가 있습니다.

비트 배열 내에서 상태 결과를 정의합니다. 입력 내에서 고유 한 마커를 사용하여 결과를 찾습니다.

다른 솔루션에서 언급했듯이 문자 2, 3 및 4는 가능한 입력간에 고유합니다. 응답 배열 내에서 적절한 비트를 선택하는 데 사용하는 문자 2와 3에 집중했습니다.

문자 2 내에서 비트 1 ~ 4는 입력을 명확하게 식별합니다. 이 비트를 마스킹하고 적절하게 이동하면 (즉, "* y & 47 >> 1") 입력이 0, 1, 4, 7 또는 8로 표시 될 수 있습니다. 따라서 응답 문자열에는 9자가 있습니다. (분리 된 재미있는 비트)

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

문자 3 내에서 비트 0, 1 및 2는 입력을 명확하게 식별합니다. 이 비트들을 마스킹 (시프 팅이 필요하지 않음) [즉 "* x & 7"]으로 입력을 0, 1, 2, 3 또는 7로 표시 할 수 있습니다. (분리 된 재미있는 비트)

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

그런 다음 해당 문자에 대한 비트를 간단히 채워서 응답 문자열을 계산할 수 있습니다.

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

따라서 Y가 이길 char에 비트를 설정하십시오.

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

그런 다음 논리는 간단합니다. 두 번째 문자가 같으면 y의 두 번째 문자를 기반으로 ASCII 문자를 가져 와서 x의 세 번째 문자로 비트를 이동하고 하나를 추가하십시오. 이렇게하면 답이 0, x가 1, y가 2입니다.


PPCG에 오신 것을 환영합니다! 이것은 훌륭하고 신중한 답변입니다.
FantaC

1

클로저, 130 118 바이트

내 이상한 사용을 제거하여 -12 바이트 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)))

나는 영리한되고 있다고 생각하지만, 이것은 순진한 다른 답변에 비교되는 결국, 그리고 많은 길었습니다.

각 이동 문자열의 처음 2자를 가져 와서 문자 코드를 가져와 합합니다. 그런 다음 얻을 합계를 뺍니다 d. 값 d이 0이면 동점 (0)이고 집합에 있으면 #{5 -16 12 -14 13 1 4 -18 2 11}p1이 이기고 (1), 그렇지 않으면 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)))

P1이이기는지 정의하는 "마법의 숫자"를 얻기 위해

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

d가능한 각 시나리오에 대한 값 목록을 생성합니다 .

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

그런 다음 승리 차트를이 출력과 비교했습니다. 다행히 0 이외의 "충돌"은 없었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.