得分一个游戏的负载,保卫和射击


11

小时候,我经常玩这个游戏。

规则

有两个玩家(我们分别称为A和B),每个玩家都用他的手作为枪支。有三种可能的动作:

  1. 举起手来向您的枪支装弹药。

    每把枪空着。装载使弹药增加一倍。

  2. 指向另一个球员射击的手。

    这会使弹药减少一倍。您必须至少有一个单位的弹药才能射击。

  3. 双臂交叉以保护自己免受射击。

两名玩家同时移动。如果两个玩家同时射击,子弹会互相击中,然后游戏继续进行。当一名玩家射击而另一名玩家携带弹药时,游戏结束。

射击和空枪被认为是作弊行为。如果一名玩家作弊,而另一名玩家执行法律诉讼,则该作弊者立即输掉。如果两个玩家同时作弊,游戏将继续。

作弊尝试不会减少弹药,因此永远不会是负面的。

挑战

给定玩家A和B的举动,输出赢得游戏1的玩家:玩家A,-1玩家B和0平局。您可以使用其他任何三元组的返回值,但是您需要在答案中说明使用了哪些返回值。

游戏可能会:

  • 无需处理所有移动即可结束;
  • 不能以给定的动作结束,因此被视为平局。

输入可以采取:

  • 作为字符串
  • 作为整数的数组/列表
  • 以任何其他不预处理输入的方式

允许完整的程序或功能。由于这是,因此以字节为单位的最短答案为胜!

测试用例

A: "123331123"
B: "131122332"
    -----^                Player B shoots player A and wins.

Output: -1
A: "111322213312"
B: "131332221133"
    -------^              Player B cheats and loses.

Output: 1
A: "1333211232221"
B: "1213211322221"
    ----------^^          Both players cheat at the same time. The game continues.

Output: 0
A: "12333213112222212"
B: "13122213312232211"
         |       || ^---- Player A shoots player B and wins.
         ^-------^^------ Both players cheat at the same time. The game continues.

Output: 1

1
相关的KotH(有趣的是,我从未玩过这个游戏的变体;我认为链接的问题是由一个曾经的朋友启发的,但是很久以前,我已经不记得了)。
门把手

Answers:


6

果冻,33 32 24字节

Zæ%1.»0$+¥\>-‘żZḅ3Ff5,7Ḣ

这将打印5而不是-1,并打印7而不是1在线尝试!验证所有测试用例

这个怎么运作

Zæ%1.»0$+¥\>-‘żZḅ3Ff5,7Ḣ  Main link. Argument: A (digit list array)

Z                         Zip; group corresponding digits.
 æ%1.                     Map the digits in (-1.5, 1.5].
                          This replaces [1, 2, 3] with [1, -1, 0].
          \               Cumulatively reduce the pairs by doing the following.
     »0$                    Take the maximum of the left value and 0, i.e., replace
                            a -1 with a 0.
        +¥                  Add the modified left value to the right value.
                          This computes the available ammo after each action. An
                          ammo of -1 indicates a cheating attempt.
           >-             Compare the results with -1.
             ‘            Increment. And unilateral cheating attempt is now [1, 2]
                          or [2, 1], where 1 signals the cheater and 2 the winner.
              żZ          Pair each result with the corr., original digits.
                ḅ3        Convert each pair from base 3 to integer.
                          This maps [1, 2] and [2, 1] to 5 and 7.
                  F       Flatten the resulting, nested list.
                   f5,7   Discard all but 5's and 7's.
                       Ḣ  Grab the first element (5 or 7).
                          If the list is empty, this returns 0.

2

Pyth,48 46 49 47字节

.xhfT|M.e,-FmgF.b/<dhkY2S2Q?}b_BS2-FbZ.b,NYCQ)0

在这里尝试!

感谢@isaacg节省2 4个字节!

将输入信息作为2元组,首先列出玩家A的动作,然后列出玩家B的动作。输出与挑战中的输出相同。

说明

简短概述

  • 首先,我们将两个玩家的移动分组在一起,这样我们得到了一个2元组的列表。
  • 然后,我们将这些元组中的每个元组映射到[cheating win, fair win]具有其-1, 0, 1每个值的表格中的另一个2元组,以指示玩家在这一点上是否获胜(-1, 1)或游戏是否继续(0
  • 现在,我们只需要获取不是的第一个元组[0,0],并采用它的第一个非零元素即可表示获胜者

代码细目

.xhfT | Me,-FmgF.b / <dhkY2S2Q?} b_BS2-FbZ.b,NYCQ)0#Q =移动列表清单

                                      .b,NYCQ#配对两个输入列表的元素
       .e#映射成对的列表 
                                                 #b为对,k为索引
            m Q#映射每个移动列表d
               .b 2S2#映射到[1,2],我不能使用m,因为它是
                                                 #lambda变量与.e中的变量冲突
                  <dhk#d [:k + 1]
                 / Y#计算此列表中1或2的出现
          -F#(计数1s)-(计数2s),表示作弊获胜
                           ?} b_BS2#如果b为(1,2)或(2,1)
                                  -fb#取差,表示公平获胜
                                     Z#else 0,尚无胜者
         ,#将这两个值配对
     | M#对于每个结果对,如果出现则取第一个
                                                 #不为零,否则为第二个
   fT#过滤掉所有零值
.xh#尝试取第一个表示获胜者的值
                                             )0#如果由于列表为空而无法执行
                                                 #输出零以表示平局

m|Fd与相同|M
isaacg

@isaacg谢谢!我总是忘记它M也会飞溅。顺便说一句:关于lambda变量冲突的问题,我们在聊天中讨论了,这使我
损失

,1 2S2
isaacg

我添加了另一个测试用例;)
删除了

@isaacg再次感谢!不知道我怎么想的。
Denker

1

Python,217字节

def f(A,B):
 x=y=0;c=[-1,1,0]
 for i in range(len(A)):
  a=A[i];b=B[i]
  for s in[0,1]:
   if(a,b)==(2,1):return c[s]*c[x<1]
   if(a,b)==(2,3)and x<1:return-c[s]
   x-=c[a-1];x+=x<0;a,b,x,y=b,a,y,x
 return 0

说明:将A和B作为整数列表。只需简单地完成每对动作,然后根据需要加或减1,然后在有人作弊或获胜时返回。使用另一个for循环执行相同的操作两次,一次用于A的移动,一次用于B的移动。如果x低于0到-1,则加1。


1

Java中,226个 212 200 196 194字节

-14字节(通过重新排序逻辑)

-12字节,感谢Public先生指出了如何对射击逻辑使用三元运算

如果将负载逻辑塞入一个短路中,则将-4字节短路

-2字节,因为==1=== <2当输入只能是123

(a,b)->{for(int m=0,n=0,w,v,r=0,i=0,x;i<a.length;){w=a[i];v=b[i++];x=w==2?m<1?r--:m--:0;x=v==2?n<1?r++:n--:0;if(r!=0)return r;if(w<2&&++m>0&v==2)return -1;if(v<2&&++n>0&w==2)return 1;}return 0;}

用法和缩进版本:

static BiFunction<Integer[], Integer[], Integer> game = (a,b) -> {
    for(int m=0,n=0,w,v,r=0,i=0,x;i<a.length;) {
        w=a[i];v=b[i++];
        // shoot
        x=w==2?m<1?r--:m--:0;
        x=v==2?n<1?r++:n--:0;
        if(r!=0)return r;
        // load
        if(w<2&&++m>0&v==2)return -1;
        if(v<2&&++n>0&w==2)return 1;
    }
    return 0;
};

public static void main(String[] args) {
    System.out.println(game.apply(new Integer[] {1,2,3,3,3,1,1,2,3}, new Integer[] {1,3,1,1,2,2,3,3,2}));
    System.out.println(game.apply(new Integer[] {1,1,1,3,2,2,2,1,3,3,1,2}, new Integer[] {1,3,1,3,3,2,2,2,1,1,3,3}));
    System.out.println(game.apply(new Integer[] {1,3,3,3,2,1,1,2,3,2,2,2,1}, new Integer[] {1,2,1,3,2,1,1,3,2,2,2,2,1}));
}

游戏规则的实现不再是那么简单,而是简单。每个周期执行以下操作:

  • 负载移入临时变量
  • 如果玩家投篮
    • 无弹药:偏置cheate r走向失败
    • 与弹药:减少弹药
  • 如果作弊r不是0,则返回值,因为有人作弊
  • 如果玩家重装
    • 增量弹药
    • 如果其他玩家投篮,回程损失

x 是一个虚拟变量,用于使编译器让我使用三元表达式。

等一下,Java比Python更廉价?


我添加了另一个测试用例;)
删除了

1
@WashingtonGuedes由于我的逻辑重新排序,我的作品得以解决!
CAD97

如果可以将其做成三元组?例如w==2&&m<1?r--:m++
Downgoat

@Downgoat否则将与内部一起使用,如果您编写了它,那么三级将不起作用。但是,我可能可以使用内部if这样做。如果有机会,我会进行测试。
CAD97

1
@ CAD97 @Downgoat实际上,可以将三元运算符用于if语句。对于第一个三元数,int x=w==2?m<1?r--:r:m--;然后继续使用x(因为这只是使三元数起作用的虚拟变量),例如x=v==2?n<1?r++:r:n--;
Mr Public
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.