骑士距离


24

在国际象棋中,网格(x,y)上的骑士可能会移动到(x-2,y-1),(x-2,y + 1),(x-1,y-2),(x-1, y + 2),(x + 1,y-2),(x + 1,y + 2),(x + 2,y-1),(x + 2,y + 1)。想象一个无限的棋盘,只有一个骑士在(0,0)上:

将骑士从(0,0)移到(t x,t y)需要多少步骤?

输入项

两个整数:t x,t y

-100 <t x <100,-100 <t y <100

输出量

将骑士从(0,0)移至(t x,t y)所需的最小步伐。

规则

  • 高尔夫代码

测试用例

  x    y -> out
  0,   0 ->  0
  0,   1 ->  3
  0,   2 ->  2
  1,   1 ->  2
  1,   2 ->  1
  3,   3 ->  2
  4,   0 ->  2
 42,  22 -> 22
 84,  73 -> 53
 45,  66 -> 37
 99,  99 -> 66
-45, -91 -> 46
-81,   1 -> 42
 11,  -2 ->  7

document.write('<div>');[..."EFEDEDCDCBCBCBCBCBCBCBCBCBCBCBCBCBCDCDEDEFE;FEDEDCDCBCBABABABABABABABABABABABCBCDCDEDEF;EDEDCDCBCBABABABABABABABABABABABABCBCDCDEDE;DEDCDCBCBABA9A9A9A9A9A9A9A9A9A9ABABCBCDCDED;EDCDCBCBABA9A9A9A9A9A9A9A9A9A9A9ABABCBCDCDE;DCDCBCBABA9A9898989898989898989A9ABABCBCDCD;CDCBCBABA9A989898989898989898989A9ABABCBCDC;DCBCBABA9A98987878787878787878989A9ABABCBCD;CBCBABA9A9898787878787878787878989A9ABABCBC;BCBABA9A989878767676767676767878989A9ABABCB;CBABA9A98987876767676767676767878989A9ABABC;BABA9A9898787676565656565656767878989A9ABAB;CBA9A989878767656565656565656767878989A9ABC;BABA98987876765654545454545656767878989ABAB;CBA9A987876765654545454545456567678789A9ABC;BABA98987676565454343434345456567678989ABAB;CBA9A987876565454343434343454565678789A9ABC;BABA98987676545434323232343454567678989ABAB;CBA9A987876565434323232323434565678789A9ABC;BABA98987676545432341214323454567678989ABAB;CBA9A987876565434321232123434565678789A9ABC;BABA98987676545432323032323454567678989ABAB;CBA9A987876565434321232123434565678789A9ABC;BABA98987676545432341214323454567678989ABAB;CBA9A987876565434323232323434565678789A9ABC;BABA98987676545434323232343454567678989ABAB;CBA9A987876565454343434343454565678789A9ABC;BABA98987676565454343434345456567678989ABAB;CBA9A987876765654545454545456567678789A9ABC;BABA98987876765654545454545656767878989ABAB;CBA9A989878767656565656565656767878989A9ABC;BABA9A9898787676565656565656767878989A9ABAB;CBABA9A98987876767676767676767878989A9ABABC;BCBABA9A989878767676767676767878989A9ABABCB;CBCBABA9A9898787878787878787878989A9ABABCBC;DCBCBABA9A98987878787878787878989A9ABABCBCD;CDCBCBABA9A989898989898989898989A9ABABCBCDC;DCDCBCBABA9A9898989898989898989A9ABABCBCDCD;EDCDCBCBABA9A9A9A9A9A9A9A9A9A9A9ABABCBCDCDE;DEDCDCBCBABA9A9A9A9A9A9A9A9A9A9ABABCBCDCDED;EDEDCDCBCBABABABABABABABABABABABABCBCDCDEDE;FEDEDCDCBCBABABABABABABABABABABABCBCDCDEDEF;EFEDEDCDCBCBCBCBCBCBCBCBCBCBCBCBCBCDCDEDEFE"].forEach(c=>document.write(c==';'?'<br>':`<span class="d-${c}">${c}</span>`));
document.write('<style>body{line-height:16px;color:rgba(255,255,255,0.2);}span{display:inline-block;width:16px;font-size:16px;text-align:center;}div{white-space:pre;}');[...'0123456789ABCDEF'].map((c,i)=>document.write(`.d-${c}{background:hsl(${60-4*i},80%,${65-2*i}%)}`));

相关OEIS

这是一些OEIS供进一步阅读

  • A018837:骑士在无限棋盘上达到(n,0)的步数。
  • A018838:骑士在无限棋盘上达到(n,n)的步数。
  • A065775:按对角线读取的数组T:T(i,j)=棋盘上从(0,0)移至(i,j)所需的最少骑士移动次数(在所有方向上都是无限的)。
  • A183041:无限棋盘上骑士从(0,0)移至(n,1)的最少次数。

您可以参考oeis.org/A065775
tsh

2
我可以将输入作为复数x+yi吗?
林恩

1
@lynn我认为这是可以接受的。
tsh

@ user202729更新了代码段以显示结果。
tsh

一张非常精美的地图。
Willtech '18

Answers:


11

Wolfram语言(Mathematica),64字节

使用内置的KnightTourGraph

由于Mathe172节省了2个字节。

GraphDistance[KnightTourGraph@@({x,y}=Abs@{##}+4),y+2,(x-2)y-2]&

在线尝试!

ArrayPlot @ Array [GraphDistance [KnightTourGraph @@({x,y} = Abs @ {##} + 5),2y + 3,(x-2)y-2]&,{65,65},-32]


14
Mathematica
Builtins

1
稍短一些:GraphDistance[KnightTourGraph@@({x,y}=Abs@{##}+5),2y+3,(x-2)y-2]&
Lukas Lang

这是什么语言?所有这些内置插件怎么被预加载?尝试使用制表符完成短语是否需要花费时间?
OganM

@OganM Mathematica在其命令行界面中不支持自动完成。笔记本界面中的自动完成如下所示
alephalpha

1
@OganM也许开发人员使用Trie(数据结构),或者只是对已排序的内置列表进行二进制搜索。是的,为什么要线性搜索?| 请注意,Mathematica是一种非免费的封闭源语言,因此没有人知道预测变量的实际工作方式。| 真正的程序员不需要自动完成。:P
user202729 '18

7

JavaScript(ES6),90 75 72字节

受到A065775给出的公式的启发。慢如地狱般的长距离。

f=(x,y,z=x|y)=>z<0?f(-y,x):z>1?1+Math.min(f(x-1,y-2),f(x-2,y-1)):z*3^x&y

在线尝试!

怎么样?

我们将z定义为xy之间的按位或。

步骤1

我们首先通过强制xy为非负值来确保位于特定象限。只要z <0(这意味着xy为负),我们就处理递归调用f(-y,x)

(+1, -2) --> (+2, +1)
(-1, +2) --> (-2, -1) --> (+1, -2) --> (+2, +1)
(-1, -2) --> (+2, -1) --> (+1, +2)

第2步

z> 1(这意味着xy大于1)时,我们递归地尝试使我们接近(0,0)的两个移动:f(x-1,y-2)f( x-2,y-1)。我们最终会走最短的路。

步骤三

z小于或等于1时,我们剩下3种可能的处理方式z*3^x&y(可以z*3-x*y代替使用):

  • x&y == 1表示x | y == 1表示x = y = 1。我们还需要两个动作才能达到(0,0)

    2招

  • x&y == 0x | y == 1表示x = 1 / y = 0x = 0 / y = 1。我们还需要三步才能达到(0,0)

    3招

  • x&y == 0x | y == 0意味着我们已经有x = y = 0

Chess.com借用的图形


5

Python 3,90个字节

感谢tsh -11个字节!

def f(x,y):x=abs(x);y=abs(y);s=x+y;return(.9+max(x/4,y/4,s/6)-s/2+(s==1or x==y==2))//1*2+s

在线尝试!

(内联代码格式,以避免读者不得不滚动。抱歉,但是我必须打高尔夫球)

非常非常有效率。


我怎么能想到这个!

1.平价

假设整个棋盘以棋盘格图案着色(即,具有x+y奇数和x+y偶数的单元格以不同的颜色着色)。

请注意,每个步骤都必须在两个颜色不同的单元格之间跳转。因此:

  • 步骤数的奇偶性必须等于的奇偶性x+y

2.近似值

假设骑士从坐标开始(0,0),并且已经移动了n步伐,并且当前位于(x,y)
为了简单起见,假设x ≥ 0y ≥ 0
我们可以得出以下结论:

  • 由于每个步骤x最多增加2x ≤ 2×n。同样,y ≤ 2×n
  • 由于每个步骤x+y最多增加3x+y ≤ 3×n

因此,n ≥ l(x,y)在哪里l(x,y) = max(max(x,y)/2, (x+y)/3。(请注意,我们不需要在公式中包含-xx-y,因为根据假设x ≥ 0 and y ≥ 0,so x+y ≥ max(x-y,y-x,-x-y)x ≥ -xy ≥ -y

事实证明,这a(x,y) = round(0.4 + l(x,y))是的很好的近似值n

  • 假设a(x,y)误差小于1,则正确的值由给出

    f(x,y) = round((a(x,y) - (x+y)) / 2) * 2 + (x+y)

    (减去x+y和除以2后的整数)

3.公式失败的特殊情况

假设x ≥ 0y ≥ 0。该算法失败有两种特殊情况:

  • x == 1 and y == 0x == 0 and y == 11正确答案为时,算法错误返回3
  • x == y == 22当正确答案为时,算法错误返回4

因此,只是特殊情况下的那些。通过加入的结果2,如果值xy是其中的一个。


1
@tsh但这也是正确的x==y==0
user202729 '18

为什么max(x+y,x-y,y-x)
tsh

@tsh:否,请参见:x = -5,y =5。x+ y = 0,abs(xy)= 10,因此x + y <abs(xy)
新星

@Nova“假设x ≥ 0y ≥ 0”。
user202729 '18

4

Python 2,87个字节

f=lambda z,a={0}:1-({z}<=a)and-~f(z,{k+1j**i*(2-i/4*4+1j)for k in a for i in range(8)})

在线尝试!

将输入作为复数z = complex(tx, ty)


4

TI-Basic,86 54字节

基于@ user202729的旧解决方案

Input :abs(X->C:abs(Y->D:C+Ans
Ans+2int(.9+(S=1 or C=2 and D=2)-.5Ans+max({C/4,D/4,Ans/6

2

MATL,29个字节

`JEQ2J-htZjht_h@Z^2&sG=~}@Gg*

输入是一个具有整数的实部和虚部的复数。

代码效率很低。它的内存需求随输出呈指数增长。对于输出超过7的测试用例,它在TIO中超时。

在线尝试!


2

Haskell,79 72字节

p l|elem(0,0)l=0|r<-[-2..2]=1+p[(x+i,y+j)|(x,y)<-l,i<-r,j<-r,(i*j)^2==4]

在线尝试!

将输入作为数字对的单例列表

简单的蛮力。要获得大于8的结果,需要大量的时间和内存。从一个坐标的单元素列表(输入)开始,重复添加每个元素可以到达的所有位置,直到(0,0)此列表中为止。跟踪递归级别并将其作为结果返回。

编辑:-7字节感谢@Lynn。



1

JavaScript(ES6),90 78字节

f=(x,y)=>y<0?f(x,-y):x<y?f(y,x):x+y<3?4-x-y&3:x-3|y-1?x-4|y-3?f(x-2,y-1)+1:3:2

编辑:保存12个字节感谢@supercat指出,x<0就意味着是y<0x<y。说明:这是一个递归解决方案。前两个条件仅确保其他条件的正确象限。第三个条件为原点附近的坐标生成答案,而后两个条件处理其他两个特殊情况(比测试两个动作短1个字节):

0
32
2++
+2++
+++3+
++++++
(etc.)

+可以通过直接向原点移动然后递归来确定所有标记的正方形。


需要x<0考试吗?给定例如-3,6,x<y测试会将其转换为6,-3,y<0测试将转换为6,3,x<y测试将转换为3,6。
超级猫

@supercat实际上,正如Python所说的那样x>=y>=0……
Neil


1

果冻27 26 25 23字节

1,-pḤµ;UÆị
¢ṗS€;0i
0ç1#

在线尝试!

非常慢; TIO超时,超过6个输出。将一个复数作为输入。

说明

该代码使用复数,因为它在中间步骤中更短,并且看起来也更快。您还可以通过删除对使用Æi和更换00,0第二行。

1,-pḤµ;UÆị    Helper link. No arguments.
1,-             Get the pair [1,-1].
    Ḥ           Double each to get [2,-2].
   p            Cartesian product: get [[1,2],[1,-2],[-1,2],[-1,-2]].
     µ          Start a new chain with the list of pairs as argument.
       U        Reverse each pair.
      ;         Append the reversed pairs to the list.
        Æi      Convert each pair [real,imag] to a complex number.

¢ṗS€;0i    Helper link. Arguments: iterations, target
¢            Call the previous link to get knight moves as complex numbers.
 ṗ           Get the iterations-th Cartesian power of the list. This will
             yield 8^n tuples containing move sequences.
  S€         Sum each move sequence to get the resulting square.
    ;0       Add the starting square, since the zeroth iteration results
             in no move sequences.
      i      Find the target squares (1-based) index in the results, or 0.

0ç1#    Main link. Argument: target
0         Starting from 0,
   #      find the
  1       first number of iterations where
 ç        calling the previous link results in a nonzero result.
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.