Хто виграє гру «Рок», «Папір», «Ножиці», «Ящірка», «Спок»?


24

Є кілька питань по приводу цієї гри , навіть конкурс тут . Але я думаю, що всі ці виклики та змагання потребують способу автоматичного визначення переможця гри. Так:

Виклик

З огляду на два входи в діапазоні, що ["rock", "paper", "scissors", "lizard", "spock"]представляють вибір для гравця 1 та гравця 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") для вхідних рядків, якщо вибраний регістр однаковий для всіх входів.
  • Вихід буде тріою значень, що визначають переможця. Це може бути все, що завгодно, доки відповіді будуть узгоджені. Приклад: 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

Це відбувається з пісочниці .
Чарлі


Я закрив його як дублікат зв'язаного питання, оскільки його саме те саме питання з двома новими значеннями та незначною варіацією на IO.
Пшеничний майстер

4
@WheatWizard іноді незначна зміна вводу дає дуже різні результати. Питання можуть бути дуже схожими, але два нових значення створюють більше випадків для розгляду, тому алгоритми, які використовуються тут, є досить різними, щоб змусити людей задуматися (див. Відповіді з cakeхитрістю).
Чарлі

4
Я згоден і проголосував за повторне відкриття.
ГБ

Відповіді:


25

Python 3 , 68 50 48 байт

EDIT: Завдяки 3 трюкам від Ніла та 2 від містера Xcoder

Кожен рядок введення має чіткий четвертий символ, тому я використовую його для їх розрізнення. Якщо ви розташовуєте елементи в циклі (ножиці, папір, скеля, ящірка, тріска), то кожен елемент б'є елемент прямо після нього, а елемент 3 - циклічно вправо. Отже, ми віднімаємо позиції входів у циклі. Якщо це число дорівнює 0, це краватка. Якщо це 1 або 3, це виграш для першого гравця. У моєму оригінальному рішенні різниця циклів буде індексувати на рядок "210100", щоб відрізнити результати гри. Ніл якось зрозумів, що це може бути досягнуто без індексації, додавши 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"достатньо)
Містер Xcoder

14

JavaScript (ES6), 56 байт

Здійснює введення в синтаксис currying (a)(b). Повертається, 0якщо виграє A, 1якщо виграє B, або 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

Давши два входи a і b , ми розглянемо наступні твердження:

  1. чи маємо a> b ? (у лексикографічному порядку)
  2. Чи б виграти гру?
  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

Читаючи це знизу вгору і ігноруючи провідні нулі, це дає 1001100110 або 614 у десятковій частині.



4

Рубін , 36 байт

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

Повертається, 0якщо виграє 1-й гравець, 1якщо переможе 2-й гравець, і 2за нічию.

На основі відповіді user507295, але використовує математичну формулу для виконання хешу. a.sum- це сума всіх ASCII кодів рядка a, mod 1<<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]якщо спок прокручений до початку).

Як пояснено в інших відповідях, хеш, який дає постійну різницю по модулю 5 для послідовних елементів у наведеній вище послідовності, потрібен для того, щоб (h[a]-h[b])%5формула працювала. Кожен елемент б'є елемент 1 або 3 місця праворуч і програє елементу 2 або 4 місця праворуч.

Спробуйте в Інтернеті!


4

JavaScript (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. Примітка: фрагмент декодує числовий результат у щось трохи менш нечитабельне. Редагувати: Збережено 1 байт завдяки @Arnauld. Збережено 4 байти завдяки @ovs.


@ovs Фу, я не портував свій гольф на відповідь WhatToDo досить важко ...
Ніл

3

C, 53 байт

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

Я розглядав цю проблему як машину стану, з якої є 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

Отже, встановіть біт у char, де виграє Y

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

Тоді логіка проста: якщо другий char однаковий, то намалюйте, інакше отримайте ascii char на основі другого символу y і перемістіть біти на третій символ x і додайте його. Це робить відповіді 0 за нічию, 1 за х виграш та 2 за виграш.


Ласкаво просимо до PPCG! Це чудова, продумана відповідь.
FantaC

1

Clojure, 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 букви кожного рядка переміщення, отримує коди char та підсумовує їх. Потім він віднімає отримані суми 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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.