Quem ganhará um jogo de Pedra, Papel, Tesoura, Lagarto e Spock?


24

várias perguntas sobre este jogo , até mesmo uma concurso aqui . Mas acho que todos esses desafios e concursos precisam de uma maneira de determinar automaticamente o vencedor de um jogo. Tão:

Desafio

Dadas duas entradas no intervalo que ["rock", "paper", "scissors", "lizard", "spock"]representam as seleções para o jogador 1 e o jogador 2, determine o vencedor da partida.

Regras

[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

Restrições

  • A entrada será um par de strings no intervalo especificado (nenhuma outra string pode ser usada). Você pode usar matrizes de caracteres, se desejar, desde que representem qualquer um dos valores mencionados.
  • Você pode optar por usar minúsculas, maiúsculas ( "ROCK") ou caixa de camelo ( "Rock") para as seqüências de entrada, desde que a caixa escolhida seja a mesma para todas as entradas.
  • A saída será um trio de valores que determinam o vencedor, que pode ser o que você quiser, desde que as respostas sejam consistentes. Exemplo: 1se a primeira entrada vencer, 2se a segunda entrada vencer, 0se houver um empate. Ou talvez Ase a primeira entrada vencer, Bse a segunda entrada vencer, <empty string>se houver um empate.

Objetivo

Este é o , portanto, pode ganhar o programa / método / função / lambda mais curto para cada idioma!

Testes

[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

Isso vem da caixa de areia .
Charlie


Fechei-o como uma duplicata da pergunta vinculada, porque é exatamente a mesma pergunta com 2 novos valores e uma ligeira variação no IO.
Assistente de trigo

4
Às vezes, @WheatWizard uma pequena alteração na entrada produz saídas muito diferentes. As perguntas podem ser bastante semelhantes, mas os dois novos valores criam mais casos a serem considerados, portanto os algoritmos usados ​​aqui são diferentes o suficiente para fazer as pessoas pensarem novamente (veja as respostas com o caketruque).
27417 Charlie

4
Eu concordo e votei para reabrir.
GB

Respostas:


25

Python 3 , 68 50 48 bytes

EDIT: Graças a 3 truques de Neil e 2 do Sr. Xcoder

Cada string de entrada possui um quarto caractere distinto, então estou usando isso para distingui-los. Se você organizar os elementos no ciclo (tesoura, papel, pedra, lagarto, spock), cada elemento superará o elemento diretamente depois dele e o elemento 3 será apontado para a direita, ciclicamente. Então subtraímos as posições das entradas no ciclo. Se esse número é 0, é um empate. Se for 1 ou 3, é uma vitória para o primeiro jogador. Na minha solução original, a diferença de ciclo seria indexada na sequência "210100" para distinguir os resultados do jogo. De alguma forma, Neil descobriu que isso pode ser conseguido sem a indexação adicionando 7 e levando o módulo em 3. Editar: Originalmente, eu usei o segundo caractere para identificar a string, mas se você usar o quarto e inverter o ciclo, obterá bolo. E todos nós poderíamos usar mais bolo.

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

Experimente online!

Versão antiga:

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

Experimente online!

Versão original:

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

Experimente online!



6
Bem-vindo ao PPCG!
Steadybox

11
49 bytes: Experimente online! (alternando .indexpara .find)
Sr. Xcoder

11
48 bytes: Experimente online! (você não precisa as p, "chaoi"sufixos)
Mr. Xcoder

14

JavaScript (ES6), 56 bytes

Recebe entrada na sintaxe de currying (a)(b). Retorna 0se A vencer, 1se B vencer ou falseempatar.

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

Demo

Quão?

Definimos a função hash H () como:

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

Isto dá:

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

Dadas duas entradas a e b , consideramos as seguintes declarações:

  1. nós temos a> b ? (em ordem lexicográfica)
  2. não b ganhar o jogo?
  3. qual é o valor de N = H (a) XOR H (b) ?

De (1) e (2), deduzimos se o resultado de a> b deve ser invertido para obter o vencedor correto e armazenamos esse sinalizador no N-ésimo bit de uma máscara de pesquisa.

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

Daí os bits:

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

Lendo isso de baixo para cima e ignorando zeros à esquerda, isso fornece 1001100110 ou 614 em decimal.


6

05AB1E , 16 bytes

ε'³²s3èk}Æ7+5%3%

Experimente online! ou como um conjunto de testes

Explicação

Usa o muito agradável cake-trick do user507295

ε       }          # apply to each in the input pair
    s3è            # get the 4th letter
 '³²   k           # get its cake-index
         Æ         # reduce by subtraction
          7+       # add 7
            5%3%   # mod by 5 and then 3

4

Ruby , 36 bytes

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

Retorna 0se o 1º jogador vencer, 1se o 2º jogador vencer e 2empatar.

Com base na resposta do usuário507295, mas usa uma fórmula matemática para executar o hash. a.sumé a soma de todos os códigos ASCII da string a, mod 1<<16e deve ser uma soma de verificação rudimentar. O hash foi encontrado usando o seguinte código:

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

Isso produziu dois valores jque deram um hash adequado para letras minúsculas, ou seja, 88 e 80, os quais deram a sequência descendente [3,2,1,0,4](ou [4,3,2,1,0]se spock é alternado entre o início e o início).

Como explicado em outras respostas, um hash que fornece uma diferença constante no módulo 5 para elementos consecutivos na sequência acima é necessário para fazer a (h[a]-h[b])%5fórmula funcionar. Cada elemento bate o elemento 1 ou 3 lugares à direita e perde ao elemento 2 ou 4 lugares à direita.

Experimente online!


4

JavaScript (ES6), 63 54 53 49 bytes

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

Porto do meu golfe para a resposta do @ WhatToDo. Nota: o trecho decodifica o resultado numérico em algo um pouco menos ilegível. Editar: salvou 1 byte graças a @Arnauld. Guardado 4 bytes graças a @ovs.


@ovs Ugh, eu não fiz port meu golfe para resposta bastante difícil de WhatToDo ...
Neil

3

C, 53bytes

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

Tratei esse problema como uma máquina de estados, da qual existem 25 estados, conforme definido pelas duas, cinco entradas de estado.

Definindo os resultados dos estados dentro de uma matriz de bits. Examino os resultados usando marcadores exclusivos nas entradas.

Conforme observado em outras soluções, os caracteres 2, 3 e 4 são únicos entre as possíveis entradas. Concentrei o uso nos caracteres 2 e 3, que utilizo para selecionar o bit apropriado na minha matriz de respostas.

No caractere 2, os bits 1 a 4 identificam claramente a entrada. Ao mascarar esses bits e mudar apropriadamente [que é "* y & 47 >> 1"]], a entrada pode ser anotada como 0, 1, 4, 7 ou 8. Portanto, minha sequência de respostas possui 9 caracteres. (pedaços interessantes separados)

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

No caractere 3, os bits 0, 1 e 2 identificam claramente a entrada. Ao mascarar esses bits (não é necessário deslocamento) [esse é o "* x & 7"]], a entrada pode ser anotada como 0, 1, 2, 3 ou 7. (pedaços interessantes separados)

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

A sequência de respostas pode ser calculada simplesmente preenchendo os bits dos caracteres apropriados.

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

Então, defina bit em char onde Y vence

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

Então a lógica é simples: se o segundo caractere é o mesmo, então desenhe, caso contrário, obtenha o caractere ascii com base no segundo caractere de y e troque os bits pelo terceiro caractere de x e adicione um. Isso torna as respostas 0 para empate, 1 para x ganha e 2 para y ganha.


Bem-vindo ao PPCG! Esta é uma ótima resposta bem pensada.
FantaC 29/11/19

1

Clojure, 130 118 bytes

-12 bytes, livrando-me do meu uso estranho de 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)))

Eu pensei que estava sendo inteligente, mas isso acabou sendo ingênuo em comparação com outras respostas, e por muito mais tempo.

Pega as 2 primeiras letras de cada sequência de movimento, obtém os códigos de caracteres e os soma. Em seguida, subtrai as somas a obter d. Se dfor 0, é um empate (0), se estiver no conjunto de #{5 -16 12 -14 13 1 4 -18 2 11}, p1 vence (1), caso contrário, p2 vence (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)))

Para obter os "números mágicos" que definem se P1 vence, corri

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

O que gera uma lista de dvalores para cada cenário possível:

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

Então eu comparei o gráfico de vitórias contra essa saída. Felizmente, não houve "colisões" além de 0.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.