这是重复抽奖吗?


13

问题:

在国际象棋中,有一个关于重复抽奖的众所周知的规则。如果同一位置重复3次(或更多次),则打算进行此举动的玩家将引起平局。

有时候,如果最后几步只是球员的来回移动,这对于仲裁员来说是一件容易的事。有时,当零件在重复的位置之间显着移动时,它会变得不那么琐碎。

挑战中的问题是,给定坐标坐标的移动列表,如果要求的位置是通过重复绘制(已被看到3次或多次),则输出真值;如果要求的位置不是通过重复绘制,则输出假值。如下所述,或您选择的任何符号(但您必须转换测试用例)。


什么是职位?

在现实世界中,位置会受到诸如玩家是否可以装城堡或是否有传球之类的因素的影响;你应该不是在你的解决问题的办法考虑这些。在这个问题中,仅通过板上的部件的配置来确定位置。因此,出于此问题的目的,如果两个板上的每个正方形都被相同类型的相同颜色的零件占据,则两个位置被视为相同。这不一定是确切的棋子,例如,怀特的骑士可以交换正方形,并且如果所有其他棋子都符合条件,则该棋子仍将位于同一位置。


有效符号是什么样的?

尽管我将继续解释坐标符号,但是您可以自由选择所选择的符号系统进行输入。规定:

  • 符号中的每一项都描述以下任何一项或全部:涉及的一件或多件;是否已交付检查,将死,再次检查,将死或僵持;是否发生了被动捕获;初始位置;最后的位置。
  • 您的符号中可能没有重复的信息。

因此,只要满足这些条件,只要您在回答中指定,我就会很乐意接受您的符号系统。例如,可以是0索引行,列元组或任何对您的程序有意义的内容。


坐标符号

坐标符号是一种纯粹将移动描述为坐标系的符号。

首先将移动描述为来自该集合的初始坐标{A1-H8},然后再次描述为来自同一集合的目标坐标。因此,国王的甘比特看起来像(作为字符串的集合)

{"E2-E4","E7-E5","F2-F4"}

我认为这是解决此问题的最佳方法,因为它不会散布无关紧要的信息,例如是否进行过检查或工件移动的类型。如前所述,可以选择一种表示法,因此您可以使用另一种表示法,例如代数表示法,也可以改写该表示法(例如,删除破折号或作为元组列表)


规则:

  • 你应该考虑位置或移动是否有效,只有它是否会导致重复
  • 您可以假设将不会进行小规模促销和典当促销。
  • 您应该将字符串列表作为输入,并输出与最后一次移动是否发生了第三次(或更多次)重复相对应的真实或错误值
  • 游戏始终在国际象棋的标准起始位置开始。初始位置可以计入重复。
  • 如果最后一步没有重复该位置,则不会发生重复绘制

通用规则:

  • 这是,因此最短答案以字节为单位。
    不要让代码高尔夫球语言阻止您发布使用非代码高尔夫球语言的答案。尝试针对“任何”编程语言提出尽可能简短的答案。
  • 标准规则适用于具有默认I / O规则的答案,因此允许您使用STDIN / STDOUT,具有正确参数的函数/方法以及返回类型的完整程序。你的来电。
  • 默认漏洞是禁止的。
  • 如果可能的话,请添加一个带有测试代码的链接(即TIO)。
  • 另外,强烈建议为您的答案添加说明。

测试用例

您应该为以下内容返回真实值:

{"B1-C3","B8-C6","C3-B1","C6-B8","B1-C3","B8-C6","C3-B1","C6-B8"} 
{"B1-C3","B8-C6","C3-B1","C6-B8","B1-C3","B8-C6","C3-B1","C6-B8","B1-C3","B8-C6","C3-B1","C6-B8"}
{"B1-C3","B8-C6","D2-D4","D7-D5","D1-D3","D8-D6","C3-B1","C6-B8","B1-C3","B8-C6","D3-D1","D6-D8","D1-D3","D8-D6"}
{"D2-D4","B8-C6","E2-E4","C6-D4","D1-E2","D4-E6","E2-F3","E6-D4","F3-D1","D4-C6","D1-E2","C6-D4","E1-D1","D4-C6","D1-E1","C6-D4"}
{"B1-C3","B8-C6","C3-B1","C6-B8","B1-C3","B8-C6","C3-B1","C6-B8","B1-C3","B8-C6","C3-B1","C6-B8","B1-C3"}

和虚假的值:

{}
{"E2-E4","E7-E5","F2-F4"}
{"B1-C3","B8-C6","C3-B1","C6-B8","B1-C3","B8-C6","C3-B1","C6-B8","F2-F4","F7-F5"}
{"E2-E4","E7-E5","G1-F3","B8-C6","F1-C4","G8-F6","F3-G5","D7-D5","E4-D5","F6-D5","G5-F7"}
{"D2-D4","B8-C6","E2-E4","C6-D4","D1-E2","D4-C6","E2-D1","C6-D4","D1-E2","D4-C6","E2-D1"}
{"B1-C3","B8-C6","C3-B5","C6-B4","B5-D4","B4-D5","D4-C6","D5-C3","C6-B8","C3-B1","B8-C6","B1-C3","C6-B8","C3-B1"}
{"E2-E4","E7-E5","D1-E2","E8-E7","E1-D1","D8-E8","E2-E1","E7-D8","E1-E2","E8-E7","E2-E1","E7-E8"}

我们是否可以将输入作为以成对的主要顺序编号的成对正方形列表的形式使用,从而完全摆脱象棋?一对成对的坐标列表怎么样?
我的代名词是monicareinstate '19

您将无法完全摆脱国际象棋,因为棋子本身和捕捉棋子仍然很重要。您可以随意定义坐标系。我将在问题中阐明一组有效的输入将具有哪些属性。
过期的数据

1
@KevinCruijssen我将明确添加初始状态确实起作用。我认为您发现这些作品很重要,因此作品的颜色也是如此。最后一个测试用例是黑白骑士之间的交换。在最后一个中,女王和国王为两个玩家交换位置
过期数据

1
@ExpiredData您能解释为什么第三个虚假案例是虚假的吗?在最后一个C6-B8位置之后,初始位置发生了三次。
亚当

2
嗯,它必须是至少出现过两次的最终位置。
亚当

Answers:


9

APL(Dyalog扩展)55 49 47 45 44 字节SBCS

-4感谢ngn。

完整程序。提示输入反向坐标对的反向列表:
 例如{"B1-C3","B8-C6"}is[[[8,2],[6,3]],[[1,2],[3,3]]]

2≤≢s∩{0,∘⊃@⍺⊃s,←⊂⍵}/⎕,⊂(⊖⍪-)¯4↑⍉6,⍪5,∘⌽⍥⍳s3

在线尝试!(包括Coords转换OP格式的实用程序功能)

设置状态列表:

s←3 分配三s(对小号大老)

由于3不是有效的董事会状态,因此不会影响我们的重复次数,因此我们需要分配的通过值…

建立棋盘代表:

5…为了在5到3之间应用以下派生函数的结果而丢弃该结果:
⍥⍳ 将两个参数都扩展到它们的基数
  [1,2,3,4,5]…… [1,2,3]
,∘⌽ 左侧与右侧的反面相连,
  [1,2,3,4,5,3,2,1]代表军官

 入桌
[[1],
[2],
[3],
[4],
[5],
[3],
[2],
[1]]

6, 在每行前面加一个代表棋子的6;
[[6,1],
[6,2],
[6,3],
[6,4],
[6,5],
[6,3],
[6,2],
[6,1]]

 转置
[[6,6,6,6,6,6,6,6],
[1,2,3,4,5,3,2,1]]

¯4↑ 取负数(即最后一个)四(行),以零填充,代表空的正方形;
[[0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0],
[6,6,6,6,6,6,6,6],
[1,2,3,4,5,3,2,1]]

(…… ) 对此应用以下默认功能:

- 取反(代表相反的颜色);
  [[ 0, 0, 0, 0, 0, 0, 0, 0],
   [ 0, 0, 0, 0, 0, 0, 0, 0],
   [-6,-6,-6,-6,-6,-6,-6,-6],
   [-1,-2,-3,-4,-5,-3,-2,-1]]

  ⊖⍪ 最重要的是,将翻转后的论点叠加在一起,使我们有充分的理由;
  [[ 1, 2, 3, 4, 5, 3, 2, 1],
   [ 6, 6, 6, 6, 6, 6, 6, 6],
   [ 0, 0, 0, 0, 0, 0, 0, 0],
   [ 0, 0, 0, 0, 0, 0, 0, 0],
   [ 0, 0, 0, 0, 0, 0, 0, 0],
   [ 0, 0, 0, 0, 0, 0, 0, 0],
   [-6,-6,-6,-6,-6,-6,-6,-6],
   [-1,-2,-3,-4,-5,-3,-2,-1]]

构造一个跟随初始状态的动作列表:

 将其封闭(将其视为一个单元)

⎕, 提示输入动作列表,并将其置于初始状态

通过将当前状态附加到列表并执行以下操作的函数来减少*:

{}/  减少以下匿名lambda:

 正确的参数(当前状态)

 将其封装为一个单元

s,← 就地将其添加到状态列表

 披露以使用该州

 ...... @⍺ 在与两个坐标,左参数表示的要素,放:
  0 一个零
  , ,随后
   通过
   第一个值
这有效地“移动”的第一坐标的值第二坐标,留下了零的背后

检查我们是否具有三个或更多的最终状态:

s∩ 所有国家与最后一个国家的交汇处;与之相同的状态子集

 整理他们

2≤ 检查是否有两个或更多(即包括最终状态的三个或更多)


* APL是右关联的,因此首先以初始状态为右参数,初始移动为左参数调用函数,然后其结果新状态变为新的右参数,第二步作为新左参数,等等。最终结果是


我很确定可以通过使用scan \而不是reduce 来显着缩短此时间/
–Adám19年

使用这个丑陋的技巧节省2个字节:⍳3⊣s←⍬-> ⍳s←3。它可以正常工作,因为3它不是一个有效的木板,因此不会影响重复检测
ngn

@ngn gh。谢谢。我们正在接近果冻。
亚当

(0,⊃)@->0,∘⊃@
ngn

@ngn完成。谢谢。
亚当

6

[R 180个 177 144字节

function(M,`+`=rep,l=c(1:5,3:1,6+8,0+16)){z=rev(Reduce(function(x,y){x[y[2:1]]=x[y]*1:0;x},M,c(l,-rev(l)),,T));sum(sapply(z,identical,el(z)))>2}

在线尝试!

Giuseppe提供了 -3个
字节,尼克·肯尼迪(Nick Kennedy)使用Reduce和提供了-29个字节-rev(l)
-4通过反向字节z

将表示正方形的1到64之间的整数向量作为输入。TIO包含转换为该格式的功能。不同的部分存储为1到6之间以及-1到-6之间的整数。

说明:

function(M,                                # M is the vector of moves 
         `+` = rep,
         l = c(1:5, 3:1, 6 + 8, 0 + 16)) { # initial position of white pieces
  z = rev(Reduce(function(x, y) {
    x[y[2:1]] = x[y] * 1:0                 # a piece moves from y[1] to y[2]; y[1] becomes 0
    x
  }, M, c(l, -rev(l)), , T))
  sum(sapply(z, identical, el(z))) > 2    # find number of past positions identical to the last position
}

1
我已经将您的修订版本放在[ bit.ly/2OHPexp]中。TIO没关系,但是链接太长,无法发表评论。该代码受您的启发,但Reduce在其核心使用了累积代码。148个字节。
尼克·肯尼迪

@NickKennedy谢谢!我实际上正打算对黑色部分使用负整数。我很高兴您首先做到了。我喜欢您对Reduce所做的事情:我显然需要更多地了解这一点。
罗宾·赖德

@NickKennedy通过反转z,我的版本又减少了4个字节。
罗宾·赖德

3

果冻41 37字节

Ø0;6x8;“Ġ²F’D¤UN;ƊW;µị@⁹Ṫ¤¦0⁹¦$\ċṪ$>1

在线尝试!

一个单子链接,将输入作为一对1索引的行主要移动的列表,[from, to]并返回1表示平移,0表示不平移。

注意,TIO上的页脚代码将OP提供的移动转换为数字格式,但是根据问题下方的讨论,数字格式将是有效的输入。

说明

Ø0                                    | 0,0
  ;6                                  | concatenate to 6 (pawn)
    x8                                | repeat each 8 times (two blank rows and 1 row of pawns)
      ;“Ġ²F’D¤                        | concatenate to 1,2,3,4,5,3,2,1
              UN;Ɗ                    | concatenate a negated flipped version to this one
                  W;                  | wrap as a list and concatenate the input list to the board
                    µ                 | start a new monadic chain
                              $\      | reduce using the two links below
                     ị@⁹Ṫ¤¦           | replace the item pointed to by the second coordinate by the value of the one at the first
                           0⁹¦        | replace the item at first coordinate with zero
                                ċṪ$   | finally count the items equal to the final one (not including it)
                                   >1 | and check of >1

3

JavaScript(Node.js) 121111 字节

[sq0, sq1][0..63]a8=0b8=1h1=63

返回一个布尔值。

a=>[a,...a].map(([x,y])=>r=b[b[b[y]=b[x],x]=0,b]=-~b[b],b=[...'89ABCA981111111'+10n**32n+0x7e5196ee74377])&&r>2

在线尝试!

怎么样?

用来识别作品的值并不重要,只要每种作品类型有一个唯一的值即可。

我们用:

  • 0代表空方块
  • 1 / 8 / 9 / / / ç为♟/♜/♞/♝/♛/♚
  • 2 / 3 / 4 / 5 / 6 / 7为♙/♖/♘/♗/♕/♔

董事会和初始职位

b

  • '89ABCA981111111' →8个黑色主要棋子,然后是前7个黑色棋子
  • 10n**32nh710
  • 0x7e5196ee74377→全部为白色(以2222222234567543小数点开头)

结果是:

    a b c d e f g h
  +----------------
8 | 8 9 A B C A 9 8
7 | 1 1 1 1 1 1 1 1
6 | 0 0 0 0 0 0 0 0
5 | 0 0 0 0 0 0 0 0
4 | 0 0 0 0 0 0 0 0
3 | 0 0 0 0 0 0 0 0
2 | 2 2 2 2 2 2 2 2
1 | 3 4 5 6 7 5 4 3

跟踪位置

bb

这就是我们这样做的原因:

b[b] = -~b[b]

已评论

a =>                    // a[] = input
  [ a,                  // dummy entry to mark the initial position as encountered once
    ...a                // append the actual data
  ].map(([x, y]) =>     // for each pair of squares [x, y] in this array:
    r =                 //   store the last result in r
    b[                  //   update b[b]:
      b[                //     update b[x]:
        b[y] = b[x],    //       set b[y] to b[x]
        x               //       set b[x] ...
      ] = 0,            //     ... to 0
      b                 //     set b[b] ...
    ] = -~b[b],         //   ... to b[b] + 1 (or 1 if b[b] is undefined)
    b = [...(…)]        //   initialize b[] (see above)
  )                     // end of map()
  && r > 2              // return true if the last result is greater than 2

我还没有为此编写测试用例,但是如果将2种相同颜色的部分互换(例如重复交换两个白色骑士的重复),这项工作是否可行?如果有机会,我会写一个测试用例。
过期的数据

是的,我的意思是,我会在可能的情况下进行更新
过期的数据

1
@ExpiredData现在应该可以正常工作了。
Arnauld

3

爪哇10,336个 330 287 285 282 276字节

m->{var V=new java.util.HashMap();int i=64,A[]=new int[i];var t="";for(;i-->0;)t+=A[i]=(i%56<8?i%8*35%41%10%8+2:9>>i/16&1)*(i/32*2-1);V.put(t,1);for(var a:m){for(t="",A[a[1]]=A[a[0]],A[a[0]]=0,i=64;i-->0;)t+=A[i];V.compute(t,(k,v)->v!=null?(int)v+1:1);}return(int)V.get(t)>2;}

通过将@Arnauld更改i%56<8?"ABCDECBA".charAt(i%56%7):i%48<16?1:0为-11个字节i%56<8?i%8*35%41%10%8+2:9>>i/16&1

a1=0,b1=1,...,h8=63{"E2-E4",...[[12,28],...

在线尝试。

说明:

m->{                   // Method with 3D character array parameter and boolean return-type
  var V=new java.util.HashMap();
                       //  Create a Map to store the occurrences of the board-states
  int i=64,            //  Index integer, starting at 64
      A[]=new int[i];  //  Create the 8 by 8 board
  var t="";            //  Temp-String, starting empty
  for(;i-->0;)         //  Loop `i` in the range (64,0]:
    t+=                //    Append the string `t` with:
      A[i]=            //     Fill the `i`'th cell with:
        i%56<8?        //      If it's either the first or eighth row:
         i%8*35%41%10%8+2
                       //       Fill it with 2,7,3,5,9,3,7,2 based on index `i`
        :9>>i/16&1)    //      Else if it's either the second or seventh row:
                       //       Fill it with 1
                       //      Else (the third, fourth, fifth, or sixth rows):
                       //       Fill it with 0
        *(i/32*2-1);   //      Then multiply it by -1 or 1 depending on whether `i`
                       //      is below 32 or not
  V.put(t,1);          //  Then set string `t` in the map to 1 for the initial state
  for(var a:m){        //  Loop over each of the input's integer-pairs:
    for(t="",          //   Make the String empty again
        A[a[1]]=       //   Set the to-cell of the current integer-pair of the input to:
          A[a[0]],     //    The value in the from-cell of the same integer-pair
        A[a[0]]=0,     //   And then empty this from-cell
        i=65;i-->0;)   //   Inner loop `i` in the range (64,0]:
          t+=A[i];     //    Append the `i`'th value to the String `t`
    V.compute(t,(k,v)->v!=null?(int)v+1:1);}
                       //   Increase the value in the map for String `t` as key by 1
  return(int)V.get(t)  //  Return whether the value in the map for the last String `t`
          >2;}         //  is at least 3

填充后的碎片值A[i]=(i%56<8?i%8*35%41%10%8+2:9>>i/16&1)*(i/32*2-1)是:

     a  b  c  d  e  f  g  h
  +------------------------
1 | -2 -7 -3 -5 -9 -3 -7 -2
2 | -1 -1 -1 -1 -1 -1 -1 -1
3 |  0  0  0  0  0  0  0  0
4 |  0  0  0  0  0  0  0  0
5 |  0  0  0  0  0  0  0  0
6 |  0  0  0  0  0  0  0  0
7 |  1  1  1  1  1  1  1  1
8 |  2  7  3  5  9  3  7  2

在线尝试。


挣扎了一段时间,避免了使用t的方法,有没有可以用来存储状态的结构,该结构可以做类似java.util.Arrays.deepHashCode的事情?如果是这样,则有很多字节要备用
数据过期,

另外,我想知道这是否基于哈希图的实现在技术上是正确的,考虑到可能的配置巨大,国际象棋棋盘可能会有哈希冲突?不过,我不会为您提供反例!
过期的数据

1
@ExpiredData确实存在一个java.util.Arrays.deepHashCode(A),但是-447346111=3如果我比较当前答案的结果图和使用deepHashCode(A)的结果图则某些哈希显然仍然是相同的(即,地图中的最后一个测试用例)。另外,它会更长而不是更短3个字节,因为我必须使用deepHashCode(A)两次(对于初始状态也是如此)。
凯文·克鲁伊森

1
但是第一个黑鸦不同于第二个黑鸦。two positions are seen to be the same if each square on both boards is occupied by the same type of piece of the same colour
无知的体现,

1
尚未在Java中经过全面测试,但是该表达式i%8*35%41%10%8+2应该可以替换"ABCDECBA".charAt(i%8),节省6个字节。它生成模式[ 2, 7, 3, 5, 9, 3, 7, 2 ]
阿纳尔德

2

木炭,62字节

≔↨²³⁴⁵⁶⁴³²χηF⁴⁸⊞η÷⁻⁴⁰ι³²F…η⁸⊞η±ιFθ«⊞υ⮌η§≔η⊟ι§η§ι⁰§≔η⊟ι⁰»›№υ⮌η¹

在线尝试!链接是详细版本的代码。将输入作为一组数字对,其中将正方形编号为A1,,B1... H8(索引为0),因此例如第一个测试用例将表示为[[[1, 18], [57, 42], [18, 1], [42, 57], [1, 18], [57, 42], [18, 1], [42, 57]]]-如果位置是重复绘制,则输出a 。转换程序。 一体。说明:

≔↨²³⁴⁵⁶⁴³²χη

将数字拆分23456432为单个数字。这些代表白色的部分。

F⁴⁸⊞η÷⁻⁴⁰ι³²

添加典当和空行。白色棋子有价值1,黑色棋子有价值-1

F…η⁸⊞η±ι

附加白色代表黑色部分的否定副本。

Fθ«

循环移动。

⊞υ⮌η

保存董事会的副本。(反向是复制木板的最简单的方法。)

§≔η⊟ι§η§ι⁰

用源文件更新目标。

§≔η⊟ι⁰

卸下源片。

»›№υ⮌η¹

确定当前位置是否多次出现。


2

C#(Visual C#交互式编译器),204字节

n=>{var j=new List<char[]>();var d=("ABCDECBATTTTTTTT"+new string('Z',32)+7777777712345321).ToArray();foreach(var(a,b)in n){j.Add(d.ToArray());d[b]=d[a];d[a]='Z';}return j.Count(r=>r.SequenceEqual(d))>1;}

将输入作为整数元组的列表,其中第一个整数是要移动的位置,第二个整数是要移动的位置。0代表A1,1代表A2,63代表H8。

在线尝试!

n=>{
  var j=new List<char[]>();    //Initialize a list to save states of a board
  var d=("ABCDECBATTTTTTTT" +  //White pieces
  new string('Z',32) +         //Empty spaces
  7777777712345321)            //Black pieces
  .ToArray(); //Initialize the chessboard
  foreach(var(a,b)in n){       //Foreach (source square, destination square) in the input
    j.Add(d.ToArray());        //  Add the current board to the list
    d[b]=d[a];                 //  Set the destination square to the source square's value
    d[a]='Z';                  //  And set the souce square to empty
  }
  return j.Count(         //Return that the amount...
    r=>r.SequenceEqual(d) //  of past positions that are equal to the current position...
  )>1;                    //is at least two
}

0

爪哇(JDK) 246个 245 244字节

import java.util.*;n->{var j=new ArrayList<char[]>();var d=("ABCDECBATTTTTTTT"+"".repeat(32)+7777777712345321l).toCharArray();for(var k:n){j.add(d.clone());d[k[1]]=d[k[0]];d[k[0]]=1;}return j.stream().filter(x->Arrays.equals(d,x)).count()>1;}

在线尝试!

import java.util.*;                   //Import the java.util package

n->{                                  //Function taking in int[][], 
                                      //where each int[] is a a pair of numbers
  var j = new ArrayList<char[]>();    //List to save each position of the chessboard
  var d =                             //The chessboard's starting position
    ("ABCDECBATTTTTTTT" +             //  All the white pieces
    "&#1".repeat(32) +                //  Plus the empty squares
    7777777712345321l)                //  And the black pieces
  .toCharArray();                     //Split to array of chars
  for(var k:n){                       //Foreach [sourceSquare, destinationSquare] in input
    j.add(d.clone());                 //  Add the current position to the list
    d[ k[1] ] = d[ k[0] ];            //  Set the destination square's value
                                      //  to the source squares
    d[ k[0] ] = 1;                    //  And clear the source square 
}                                     //End foreach
return j.stream()                     //Convert list of states to stream
  .filter(x ->                        //Filter each position by
    Arrays.equals(d,x)                //  if the position equals the final position 
  ).count() > 1;                      //And return if there are at least two
                                      //positions that are left
}
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.