谁将赢得摇滚,纸,剪刀,蜥蜴,史波克(Spock)游戏?


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

限制条件

  • 输入将是给定范围内的一对字符串(不能使用其他字符串)。您可以根据需要使用char数组,只要它们表示任何上述值即可。
  • 您可以选择对输入字符串使用小写,大写("ROCK")还是驼峰大写()"Rock",只要所有输入的大小写都相同。
  • 输出将是确定获胜者的三项价值观,只要答案是一致的,您就可以选择任何值。示例:1如果第一个输入获胜,2如果第二个输入获胜,0则平局。或者,A如果第一个输入获胜,B则第二个输入获胜,<empty string>如果有平局。

目标

这是,因此每种语言中最短的程序/方法/函数/ lambda可能会获胜!

测验

[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

Answers:


25

Python 3中68个 50 48字节

编辑:感谢Neil的3招和Xcoder先生的2招

每个输入字符串都有一个不同的第四个字符,因此我使用它来区分它们。如果您在循环中排列元素(剪刀,纸张,岩石,蜥蜴,鸡腿),则每个元素都会在其之后直接击败该元素,并且该元素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]

在线尝试!


1
50个字节:在线尝试!
尼尔

6
欢迎来到PPCG!
Steadybox

1
49个字节:在线尝试!(切换.index.find
Xcoder先生,2017年

1
48个字节:在线尝试!(您不需要p"chaoi"就足够了)
Xcoder先生17年

14

JavaScript(ES6),56个字节

以currying语法接受输入(a)(b)0如果A获胜,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

从下至上读取此数据,并忽略前导零,这将产生1001100110或十进制614



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的答案。注意:该代码段会将数字结果解码为不太可读的内容。编辑:由于@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是字符串amod 的所有ASCII代码的总和,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]如果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;

我将这个问题视为状态机,其中两个,五个状态输入定义了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 '17

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之外没有任何“冲突”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.