骑士在N步能走到哪里?


21

这是APL CodeGolf 秋季比赛的第 3洞。我是该问题的原始作者,因此可以在此处重新发布。


鉴于:

  1. 转数(如果没有运动为0,请说明,否则我们将其称为1),

  2. 在8 x 8棋盘上的一个或多个起始位置(以任何形式,例如0或1索引坐标或64个连续的数字/字符或A1-H8 –状态)的列表,

返回(以任何顺序)在给定匝数后,骑士可以位于的唯一位置列表(与输入格式相同)。

  • 每个骑士必须每转一个步,但您不必担心多个骑士占据同一广场。

  • 骑士只能相对于其当前位置移动到标记为X的位置,标记为♞:
    骑士可以移动的地方

示例(1索引坐标)

1[[1,1]]: [[2,3],[3,2]]

2来自[[1,1]]: [[1,1],[1,3],[1,5],[2,4],[3,1],[3,5],[4,2],[4,4],[5,1],[5,3]]

1[[1,1],[5,7]]: [[2,3],[3,2],[3,6],[3,8],[4,5],[6,5],[7,6],[7,8]]

2来自[[1,1],[5,7]]: [[1,1],[1,3],[1,5],[1,7],[2,4],[2,6],[2,8],[3,1],[3,3],[3,5],[3,7],[4,2],[4,4],[4,6],[4,8],[5,1],[5,3],[5,5],[5,7],[6,4],[6,6],[6,8],[7,3],[7,7],[8,4],[8,6],[8,8]]

0来自[[3,4]]: [[3,4]]


可以通过编号0-63而不是[rank,file]来输入和输出国际象棋空格吗?
戴夫

@戴夫当然,为什么不呢?只需与I / O保持一致即可。
阿达姆(Adám)

8
我发誓我读这本HNQ是“骑士在Ni的行进中”
Sidney

3
潘警告:对骑士的符号是N.
约书亚

我们可以在步数上使用基于1的索引吗?例如[[1,1]], 2 -> [[2,3],[3,2]]
Zgarb

Answers:


11

Wolfram语言(Mathematica),45字节

由于其他解决方案不正确(请参见下面的Martin评论),因此我决定发布我的解决方案:

8~KnightTourGraph~8~AdjacencyList~#&~Nest~##&

在线尝试!

最终缀符号...

接受2个输入,第一个是范围内的数字列表 [1,64]描述骑士起始位置的,第二个是步数。

该解决方案依赖于Mathematica内置函数的极大便利性:

  • AdjacencyListmay可以在其右侧获取一个顶点列表,并返回与已移除的重复项和sorted相邻的顶点列表。
  • KnightTourGraph是内置的。不奇怪。
  • Nest按顺序接受参数Nest[f, expr, n],我们可以将##其喷溅在右边Nest[f, ##]
  • 最后,Mathematica解析a~b~c~d~e(a~b~c)~d~e,因此不需要方括号。没有前缀符号和拼合##,它将会是Nest[AdjacencyList[KnightTourGraph[8, 8], #] &, #, #2]&

1
我认为超越现有解决方案没有任何问题。
亚当

1
这是否适用于多个起始职位?
亚当

惊人!现在我需要弄清楚ti是怎么读的……
Dave

在假设的Mthmca打高尔夫球语言中,这可能是17个字节。
迈克尔·斯特恩

7

JavaScript(ES7),99个字节

输入/输出格式:[0 ... 63]中的平方索引。

f=(a,n)=>n--?f([...Array(64).keys()].filter(p=>!a.every(P=>(p%8-P%8)**2^((p>>3)-(P>>3))**2^5)),n):a

测试用例

该代码段包括两个帮助程序功能,它们可以与OP提供的格式相互转换。

怎么样?

(x,y)(X,Y)的移动是有效的骑士移动,如果我们具有以下任一情况:

  • | xX | = 1| yY | = 2,或
  • | xX | = 2| yY | = 1

通过平方而不是使用绝对值,可以表示为:

  • (xX)²= 1(yY)²= 4,或
  • (xX)²= 4(yY)²= 1

因为14是在XOR在一起时给出5的唯一完美平方,所以如果发生以下情况,我们就有一个有效的骑士动作:

(xX)²XOR(yY)²XOR 5 = 0

我们将此公式应用于板上的每个正方形p = 8y + x和每个骑士正方形P = 8Y + X来推导新的可能的骑士目标正方形,并递归地重复此过程n次。


5

八度,69字节

function a=f(a,n,b=~a)for k=1:n;a=b&imdilate(a,de2bi(")0#0)"-31));end

在线演示!

输入/输出是板在开始/结束时的配置,为二进制8 * 8矩阵。

说明:

对于n步骤,请使用以下遮罩重复对板进行形态扩展:

01010
10001
00100
10001
01010

5

视网膜147102字节

.$
$*	
¶
 ¶
{s`((?<=N(....|.{11}|.{13})?.{7})|(?=.{8}(....|.{11}|.{13})?N))\S(?=.*	)
n
Ts`	Nn`_:N`.*¶	

在线尝试!将输入作为:s 的8x8板子(带有标记为s的骑士)N,并在下一行上加上圈数(不超过9圈是没有意义的,但是如果您坚持要我多加支持的话)字节)。请注意,输出包含其他空格。编辑:感谢@MartinEnder,节省了45个字节。说明:第一阶段将匝数转换为一元,但使用制表符,以便以后不会意外匹配,而第二阶段在板的右侧添加一些空格以防止正则表达式绕开边缘。第三阶段替换所有NS和:是一个骑士的举动从靠近S N与s到n,而第四个阶段将删除任何剩余N S,改变了nNs,并从移动计数中减去1。重复直到移动计数为零为止。


这是最令人印象深刻的。绝对不是工作的正确工具!
亚当

4

果冻,29个字节

+þ1,2Œ!×þ1,-p`¤¤Ẏ¤Ẏ⁼%8$$ÐfQµ¡

在线尝试!

0分度坐标。几乎可以肯定这是次优的。

-1字节感谢user202729

说明

+þ1,2Œ!×þ1,-p`¤¤Ẏ¤Ẏ⁼%8$$ÐfQµ¡  Main Link
+þ                             Addition Table (all pairs using + as combining function) with
  1,2Œ!×þ1,-p`¤¤Ẏ¤             All knight moves:
  1,2                          [1, 2]
     Œ!                        All permutations ([1, 2], [2, 1])
       ×þ                      Product Table (all pairs using × as combining function) with
         1,-p`¤                [1, 1], [1, -1], [-1, 1], [-1, -1]
         1,-                   [1, -1]
            p`                 Cartestian Product with itself
               ¤               All knight moves (in a nested array) as a nilad
                Ẏ¤             Tighten (flatten once); all knight moves in a (semi-)flat array
                        Ðf     Keep elements where
                   ⁼%8$$       The element equals itself modulo 8 (discard all elements out of the range)
                          Q    Remove Duplicates
                           µ   Start new monadic chain (essentially, terminates previous chain)
                            ¡  Repeat n times; n is implicitly the second input (right argument)

1
0索引的果冻?
阿达姆(Adám)

1
@Adám使过滤更容易:P
HyperNeutrino

2
我希望Jelly能够在15个字节以内完成此操作,因为APL中的当前记录保存器以24个字符为单位。
亚当

当您有> = 3 $时,很可能可以将其移至上一个链接,并使用返回Ç
user202729 '17

@ user202729哦,是的,谢谢。
HyperNeutrino

3

05AB1E27 25字节

感谢Emigna节省了2个字节!

使用1索引坐标。

码:

F•eĆ•SÍü‚Dí«δ+€`Ùʒ{`9‹*0›

使用05AB1E编码。在线尝试!

说明:

F                          # Do the following <input_1> times..
 •eĆ•SÍ                    #   Push [-1, -2, 1, 2, -1]
       ü‚                  #   Pairwise pairing: [[-1, -2], [-2, 1], [1, 2], [2, -1]]
         D                 #   Duplicate the array
          í                #   Reverse each element
           «               #   Concatenate to the previous array

这为我们提供了以下数组:

[[-1, -2], [-2, 1], [1, 2], [2, -1], [-2, -1], [1, -2], [2, 1], [-1, 2]]

哪些是骑士行动的三角洲。

            δ+             #   Addition vectorized on both sides
              €`           #   Flatten each element
                Ù          #   Uniquify
                 ʒ         #   Keep elements which..
                  {`9‹     #     Has a maximum element smaller than 9
                      *0›  #     And a minimum element larger than 0

您可以使用•eĆ•SÍü‚而不是Ƶ‡4в2ô<D(«保存2个字节。
Emigna

@Emigna Ahh,这很聪明,谢谢!
阿德南(Adnan)

2

Python 3,105个字节

p=lambda g,i:i and list(set(p([x+y for x in g for y in[6,10,15,17,-6,-10,-15,-17]if 0<=x+y<64],i-1)))or g

必须为递归使用命名的lambda。不知道这是否不合格。将起始位置作为0索引的平方数列表传递。0计为无动。


2

Java(OpenJDK 8),124字节

(m,p)->{for(;m-->0;)for(long a=p,i=p=0,j;i<64;i++)for(j=64;j-->0;)p|=(p=i%8-j%8)*p+(p=i/8-j/8)*p==5?(a>>i&1)<<j:0;return p;}

在线尝试!

输入/输出格式

输入/输出以a中的位表示long(64位):设置位表示存在一匹马,未设置位表示无一匹马。例:

// [[0, 0]]
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001L

说明

(m, p) -> {                          // Lambda. No currying because m and p are modified
 for(;m-->0;)                        // For each move
  for(long a=p,i=p=0,j;i<64;i++)     // Declare variables, move p to a, create a new p and loop on bits of a.
   for(j=64;j-->0;)                  // Loop on bits of p.
    p |=                             // Assign to p a value.
     (p=i%8-j%8)*p+(p=i/8-j/8)*p==5  // If i -> j is a valid horse move, see Arnauld's JavaScript answer for full explanations
      ? (a>>i&1)<<j                  // Assign the presence of the horse (i-th bit of a) to the resulting board (j-th bit of p).
      : 0;                           // Else it's not a valid horse move
 return p;
}

学分

  • Nevay节省了19个字节!
  • 重用(X-x)²+(Y-y)²==5Arnauld的JavaScript回答中的技巧
  • 多亏了Nevay在新算法中节省了1个字节!
  • 再次感谢Nevay,从切换int[]到64位又节省了7个字节long

1
169个字节:(m,p)->{for(;m-->0;){int i=64,a[]=p,x,y,u[]={1,3,5,9,15,19,21,23};for(p=new int[i];i-->0;)for(int z:u)if((((x=i/8+z/5-2)|(y=i%8+z%5-2))&-8)==0)p[x*8+y]|=a[i];}return p;}
Nevay

1
-1个字节:(m,p)->{for(int i,j,a[],x;m-->0;)for(a=p,p=new int[i=64];i-->0;)for(j=64;j-->0;)p[j]|=(x=i%8-j%8)*x+(x=i/8-j/8)*x==5?a[i]:0;return p;}
Nevay

谢谢@Nevay!添加代码以删除括号/块总是很不错的!;-)
OlivierGrégoire17年

1
替换int[]为-7个字节long(m,p)->{for(long i,j,a;m-->0;)for(a=p,p=i=0;i<64;i++)for(j=64;j-->0;)p|=(p=i%8-j%8)*p+(p=i/8-j/8)*p==5?(a>>i&1)<<j:0;return p;}
Nevay

干杯,我什至没有考虑这样做!干得好,@Nevay ;-)
奥利维尔·格雷瓜尔

2

果冻29 28字节

8Rp`
“¦Ʋƈ2’D_2ṡ2+€µẎ
ÇƓ¡f1£Q

在线尝试!

转数是通过STDIN进行的,而平方是一个参数。

这与@HyperNeutrino的Jelly解决方案联系在一起,但是采用了不同的方法。

现在以1个完整字节击败@HyperNeutrino!

需要敲除一些字节的任何建议!

链接1(棋盘)

8Rp`
8R   = The list [1,2,3,4,5,6,7,8]
  p` = cartesian multiplied with itself (this results in the chessboard)

链接2(移动生成)

“¦Ʋƈ2’D_2ṡ2+€µẎ
“¦Ʋƈ2’          = the number 103414301
      D         = converted into a list of digits
       _2       = subtract two from each element
         ṡ2     = overlapping pairs
           +€   = add to the list of squares
             µ  = Make sure the next part isn't treated as a right argument
              Ẏ = Tighten the list (Reducing the depth by one)

链接3(正方形检查)

ÇƓ¡f1£Q
ÇƓ¡     = Repeat link #2 the requested amount of times
   f1£  = Remove everything not a member of link #1 (not on the chess board)
      Q = Make sure squares don't appear more than once

1

外壳,18个字节

u!¡ṁö`fΠR2ḣ8=5ṁ□z-

使用基于1的正方形和台阶索引。 在线尝试!

说明

u!¡ṁö`fΠR2ḣ8=5ṁ□z-  Implicit inputs, say P=[[1,1],[5,7]] and n=2
  ¡                 Iterate on P:
   ṁö               Map the following function, then concatenate:
                     Argument is a pair, say p=[5,7].
          ḣ8         The range [1,2,..,8]
       ΠR2           Repeat twice, take cartesian product: [[1,1],[1,2],..,[8,8]]
     `f              Filter with this predicate:
                      Argument is a pair, say q=[3,8].
                z-    Zip p and q with difference: [-2,1]
              ṁ□      Sum of squares: 5
            =5        Is it 5? Yes, so [3,8] is kept.
 !                  Take n'th step of the iteration.
u                   Remove duplicates, implicitly print.

1

[R 145个 183 134字节

这是朱塞佩(Giuseppe)出色打高尔夫球的结果,这是我最初不太喜欢高尔夫的算法(请参阅下面的评论)

function(x,n){x=x%/%8*24+x%%8
t=c(49,47,26,22)
t=c(t,-t)
for(i in 1:n)x=intersect(v<-outer(1:8,0:7*24,"+"),outer(x,t,"+"))
match(x,v)}

在线尝试!

输入和输出基于1 ... 64。使用1 ... 64表示法获取位置向量。将其映射为1:576表示法,这是一个由九个板组成的超级板。在这种表示法中,在每次迭代中,每个骑士应能够移动+/- 22,26,47,49,以1 ... 64表示法返回将来的位置,但不包括从中央板上掉落的位置。TIO示例使用8x8矩阵显示结果。


这似乎在第一个测试用例上失败(它返回4个坐标而不是2个坐标)。
Zgarb

感谢您指出Zgarb,我想我已经解决了这个问题
NofP,2017年


148字节(如果使用[0...63]符号表示)。
朱塞佩

1
134个字节[1..64]用于输入和输出。但是,+ 1是一个很好的答案。
朱塞佩
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.