Кто победит в игре «Камень, Бумага, Ножницы, Ящерица, Спок»?

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
Чарли
источник
Это происходит из песочницы .
Чарли
1
Очень связано .
Стьюи Гриффин
Я закрыл его как дубликат связанного вопроса, потому что это тот же вопрос с двумя новыми значениями и небольшим изменением ввода-вывода.
Пшеничный волшебник
4
@WheatWizard иногда небольшое изменение во входных данных дает очень разные выходы. Вопросы могут быть очень похожими, но эти два новых значения создают больше вариантов для рассмотрения, поэтому используемые здесь алгоритмы достаточно различны, чтобы заставить людей снова думать (см. Ответы с cakeхитростью).
Чарли
4
Я согласен и проголосовал за открытие.
ГБ

Ответы:

25

Python 3 , 68 50 48 байтов

РЕДАКТИРОВАТЬ: Благодаря 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)
Mr. Xcoder
1
48 байт: попробуйте онлайн! (вам не нужно p, "chaoi"достаточно)
Mr. Xcoder
14

JavaScript (ES6), 56 байт

Принимает ввод в синтаксисе карри (a)(b). Возвращает, 0если победит,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. у нас есть > б ? (в лексикографическом порядке)
  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 в десятичном виде.

Arnauld
источник
4

Рубин , 36 байт

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

Возвращает, 0если 1-й игрок выигрывает, 1если 2-й игрок выигрывает, и 2для ничьей.

Основано на ответе пользователя 507295, но использует математическую формулу для выполнения хэша. a.sumявляется суммой всех ASCII-кодов строки amod 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 места справа.

Попробуйте онлайн!

Уровень реки St
источник
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

Тогда логика проста: если второй символ такой же, то нарисуйте, в противном случае получите символ ascii на основе второго символа y, сдвиньте биты на третий символ x и добавьте один. Это дает ответы 0 для ничьей, 1 для выигрыша х и 2 для выигрыша у.

meismich
источник
Добро пожаловать в 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 буквы каждой строки перемещения, получает коды символов и суммирует их. Затем вычитает суммы, чтобы получить 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.

Carcigenicate
источник