牛羚的路径


23

打高尔夫球的程序或功能,使角马的nth位置在无限的棋盘上从第1平方开始,该棋盘以逆时针方向的正方形螺旋编号,在该位置,角马总是访问她能到达的,编号最小的正方形。尚未访问。1

灵感:被困骑士OEIS A316667

编辑:此序列现在在OEIS上为A323763

该代码可以产生第nth位置,前n位置,或生成不带输入的序列。

可以在n跳跃之后(或最多)随意提供其位置,但是如果是这样,请在您的答案中清楚说明,并确保输入n=0产生1(或[1]适当的话)。

这是,因此目标是以您选择的语言生成尽可能少的字节的工作代码。

注:角马被截留(很像骑士确实在他的2016th位置,方2084,和骆驼确实在他的3723rd,方7081)在她12899744968th在广场的位置12851850258。大于n可能未定义代码的行为。(感谢Deadcode提供了找到该代码C ++代码!)

详情

该板看起来像下面,并且可以无限期地继续:

101 100  99  98  97  96  95  94  93  92  91
102  65  64  63  62  61  60  59  58  57  90
103  66  37  36  35  34  33  32  31  56  89
104  67  38  17  16  15  14  13  30  55  88
105  68  39  18   5   4   3  12  29  54  87
106  69  40  19   6   1   2  11  28  53  86
107  70  41  20   7   8   9  10  27  52  85
108  71  42  21  22  23  24  25  26  51  84
109  72  43  44  45  46  47  48  49  50  83
110  73  74  75  76  77  78  79  80  81  82
111 112 113 114 115 116 117 118 119 120 121

角马是“GNU” 仙人棋子 -非标准棋子它们可以同时移动作为骑士(一(1,2) -leaper)和作为骆驼(一(1,3) -leaper)。
因此,她可以从1起始位置移动到以下任何位置:

  .   .   .   .   .   .   .   .   .   .   .
  .   .   .   .  35   .  33   .   .   .   .
  .   .   .   .  16   .  14   .   .   .   .
  .   .  39  18   .   .   .  12  29   .   .
  .   .   .   .   .  (1)  .   .   .   .   .
  .   .  41  20   .   .   .  10  27   .   .
  .   .   .   .  22   .  24   .   .   .   .
  .   .   .   .  45   .  47   .   .   .   .
  .   .   .   .   .   .   .   .   .   .   .

其中最低的是10而她还没有访问过该广场,因此10是序列中的第二项。

接下来,她可以从10移动到以下任何位置:

  .   .   .   .   .   .   .   .   .   .   .
  .   .   .   .   .   .  14   .  30   .   .
  .   .   .   .   .   .   3   .  29   .   .
  .   .   .   .   6   1   .   .   .  53  86
  .   .   .   .   .   .   . (10)  .   .   .
  .   .   .   .  22  23   .   .   .  51  84
  .   .   .   .   .   .  47   .  49   .   .
  .   .   .   .   .   .  78   .  80   .   .
  .   .   .   .   .   .   .   .   .   .   .

但是,她已经去过1广场,因此她的第三个位置是3广场,这是她尚未去过的最低点。


牛羚路径的前100术语是:

1, 10, 3, 6, 9, 4, 7, 2, 5, 8, 11, 14, 18, 15, 12, 16, 19, 22, 41, 17, 33, 30, 34, 13, 27, 23, 20, 24, 44, 40, 21, 39, 36, 60, 31, 53, 26, 46, 25, 28, 32, 29, 51, 47, 75, 42, 45, 71, 74, 70, 38, 35, 59, 56, 86, 50, 78, 49, 52, 80, 83, 79, 115, 73, 107, 67, 64, 68, 37, 61, 93, 55, 58, 54, 84, 48, 76, 43, 69, 103, 63, 66, 62, 94, 57, 87, 125, 82, 118, 77, 113, 72, 106, 148, 65, 97, 137, 91, 129, 85

11飞跃是骑士移动,因此前12学期与A316667相吻合。


评论不作进一步讨论;这个对话已经转移至聊天
Mego

Answers:


21

JavaScript(Node.js) 191 ... 166164 字节

@grimy节省了2个字节。

返回 N项。

n=>(g=(x,y)=>n--?g(Buffer('QPNP1O?O@242Q3C3').map(m=c=>g[i=4*((x+=c%6-2)*x>(y+=c%7-2)*y?x:y)**2,i-=(x>y||-1)*(i**.5+x+y)]|i>m||(H=x,V=y,m=i))&&H,V,g[m]=1):m+1)(1,2)

在线尝试!查看格式化的版本

怎么样?

螺旋指数

为了将坐标(x,y)转换为螺旋指数I,我们首先计算层L

L=max(|x|,|y|)

这使:

3210+1+2+333333333232222231321112303210123+13211123+23222223+33333333

然后,我们使用以下公式计算层中的位置P

P={2L+x+yif x>y(2L+x+y)if xy

这使:

3210+1+2+330123456210123471210125803210369+143234710+254567811+36789101112

最终指标I给出是:

I=4L2P

注意:以上公式给出了一个0索引的螺旋。

在JS代码中,我们实际上计算了4L2

i = 4 * (x * x > y * y ? x : y) ** 2

然后减去P

i -= (x > y || -1) * (i ** 0.5 + x + y)

牛羚的举动

给定当前位置(x,y),按以下顺序测试牛羚的16个可能的目标方块:

321x+1+2+3391128101761213y+1541415+220+331

我们通过应用16对带符号的值(dx,dy)来遍历它们。每对都编码为单个ASCII字符。

 ID | char. | ASCII code | c%6-2 | c%7-2 | cumulated
----+-------+------------+-------+-------+-----------
  0 |  'Q'  |     81     |   +1  |   +2  |  (+1,+2)
  1 |  'P'  |     80     |    0  |   +1  |  (+1,+3)
  2 |  'N'  |     78     |   -2  |   -1  |  (-1,+2)
  3 |  'P'  |     80     |    0  |   +1  |  (-1,+3)
  4 |  '1'  |     49     |   -1  |   -2  |  (-2,+1)
  5 |  'O'  |     79     |   -1  |    0  |  (-3,+1)
  6 |  '?'  |     63     |   +1  |   -2  |  (-2,-1)
  7 |  'O'  |     79     |   -1  |    0  |  (-3,-1)
  8 |  '@'  |     64     |   +2  |   -1  |  (-1,-2)
  9 |  '2'  |     50     |    0  |   -1  |  (-1,-3)
 10 |  '4'  |     52     |   +2  |   +1  |  (+1,-2)
 11 |  '2'  |     50     |    0  |   -1  |  (+1,-3)
 12 |  'Q'  |     81     |   +1  |   +2  |  (+2,-1)
 13 |  '3'  |     51     |   +1  |    0  |  (+3,-1)
 14 |  'C'  |     67     |   -1  |   +2  |  (+2,+1)
 15 |  '3'  |     51     |   +1  |    0  |  (+3,+1)

我们跟踪在m遇到的最小值,并在(H,V)跟踪相应单元格的坐标。

找到最佳候选者后,我们通过在对象g设置一个标志将其标记为已访问,这也是我们的主要递归函数。

在第一次迭代中,我们从x=1y=2。这确保了第一选择的小区是(0,0)和,它的为已访问被标记所述第一小区。


3
如此多的高尔夫运动,迫不及待地想要了解所有魔术的原理!
乔纳森·艾伦

您是否必须使用Buffer强制每个字符被解释为单个字节?
约拿

1
@Jonah尽管已弃用,但Buffer构造函数仍接受字符串。因此,是的,这是一种将其转换为字节列表的相对便宜的方法-与相对[..."string"].map(c=>do_something_with(c.charCodeAt()))
Arnauld

1
-2个字节的坐标编码:TIO
Grimmy

@Grimy做得好!
Arnauld

8

椰子337276字节

import math
def g((x,y))=
 A=abs(abs(x)-abs(y))+abs(x)+abs(y)
 int(A**2+math.copysign(A+x-y,.5-x-y)+1)
def f():
 p=x,y=0,0;s={p};z=[2,3,1,1]*2
 while 1:yield g(p);p=x,y=min(((a+x,b+y)for a,b in zip((1,1,2,-2,-1,-1,3,-3)*2,z+[-v for v in z])if(a+x,b+y)not in s),key=g);s.add(p)

返回值的生成器。可能会打更多的高尔夫球。(尤其是差分元组的序列。)取自此math.se答案的螺旋算法。

在线尝试!


1
for a,b in (-> for a,b in((也许您也可以打高尔夫球元组的三角洲元组)
乔纳森·艾伦

1
q元组不需要,而且拉链更短:当然,仍然可以打高尔夫球306个字节
Jonathan Allan

1
...这个284呢?编辑... 是278
乔纳森·艾伦

1
FWIW,这math.se答案XY ^互换,两者相对坐标系中这一挑战负(其中正X是正确的,Ÿ是向上)。并不是说由于对称性会有所不同,但是仍然如此。
Deadcode

1
0.5-> .5保存另一个字节;A**2-> A*A再加一。
乔纳森·艾伦

8

05AB1E77 65 58 57 52 字节

Xˆ0UF3D(Ÿ0KãʒÄ1¢}εX+}Dε·nàDtyÆ+yO·<.±*->}D¯KßDˆkèU}¯

-6个字节 @Arnauld通过使用他的公式的端口获得了。

输出第一个 ñ+1个 值(十进制)的列表。

在线尝试ï在页脚中删除.0可以使输出更紧凑,但是可以随意删除以查看实际结果)。

代码说明:

Xˆ             # Put integer 1 in the global_array (global_array is empty by default)
0U             # Set variable `X` to 0 (`X` is 1 by default)
F              # Loop the (implicit) input amount of times:
 3D          #  Push the list in the range [-3,3]: [-3,-2,-1,0,1,2,3]
     0K        #  Remove the 0: [-3,-2,-1,1,2,3]
       ã       #  Cartesian product with itself, creating each possible pair: [[3,3],[3,2],[3,1],[3,-1],[3,-2],[3,-3],[2,3],[2,2],[2,1],[2,-1],[2,-2],[2,-3],[1,3],[1,2],[1,1],[1,-1],[1,-2],[1,-3],[-1,3],[-1,2],[-1,1],[-1,-1],[-1,-2],[-1,-3],[-2,3],[-2,2],[-2,1],[-2,-1],[-2,-2],[-2,-3],[-3,3],[-3,2],[-3,1],[-3,-1],[-3,-2],[-3,-3]]
        ʒ   }  #  Filter this list of pairs by:
         Ä     #   Where the absolute values of the pair
          1¢   #   Contains exactly one 1
               #  (We now have the following pairs left: [[3,1],[3,-1],[2,1],[2,-1],[1,3],[1,2],[1,-2],[1,-3],[-1,3],[-1,2],[-1,-2],[-1,-3],[-2,1],[-2,-1],[-3,1],[-3,-1]])
 εX+}          #  Add the variable `X` (previous coordinate) to each item in the list
 D             #  Duplicate this list of coordinates
  ε            #  Map each `x,y`-coordinate to:
   ·           #   Double both the `x` and `y` in the coordinate
    n          #   Then take the square of each
     à         #   And then pop and push the maximum of the two
   Dt          #   Duplicate this maximum, and take its square-root
     yÆ        #   Calculate `x-y`
       +       #   And add it to the square-root
   yO          #   Calculate `x+y`
     ·         #   Double it
      <        #   Decrease it by 1
             #   And pop and push its signum (-1 if < 0; 0 if 0; 1 if > 0)
   *           #   Multiply these two together
    -          #   And subtract it from the duplicated maximum
   >           #   And finally increase it by 1 to make it 1-based instead of 0-based
  }D           #  After the map: Duplicate that list with values
    ¯K         #  Remove all values that are already present in the global_array
      ß        #  Pop the list of (remaining) values and push the minimum
       Dˆ      #  Duplicate this minimum, and pop and add the copy to the global_array
         k     #  Then get its index in the complete list of values
          è    #  And use that index to get the corresponding coordinate
           U   #  Pop and store this coordinate in variable `X` for the next iteration
             # After the outer loop: push the global_array (which is output implicitly)

一般说明:

我们将所有结果(以及因此已经遇到的值)保存在中global_array,该结果最初以开头[1]
我们持有当前Xÿ-变量中的坐标X,该变量最初是[0,0]

我们可以根据当前坐标到达的列表 Xÿ-坐标为:

[[x+3,y+1], [x+3,y-1], [x+2,y+1], [x+2,y-1], [x+1,y+3], [x+1,y+2], [x+1,y-2], [x+1,y-3], [x-1,y+3], [x-1,y+2], [x-1,y-2], [x-1,y-3], [x-2,y+1], [x-2,y-1], [x-3,y+1], [x-3,y-1]]

我在上面的代码说明中提到的列表包含了我们可以跳转到的这些值,之后是当前 Xÿ(存储在变量中X)被添加。

然后将基于这些计算螺旋值 Xÿ-坐标。通过对给定使用以下公式来完成此操作Xÿ-坐标:

Ť=一种X2X22ÿ2
[R=Ť-X-ÿ+Ťs一世GñüX+ÿ2-1个+1个

@Arnauld在他的答案中使用的是相同的公式,但是写成不同的方式是利用05AB1E的内建函数来生成double,square,-1,+ 1等。

(如果您只想看一下代码的螺旋部分,请在线尝试。)

在获得所有值之后,我们可以达到给定的值 Xÿ-坐标,我们删除中已经存在的所有值,global_array然后获得(剩余)值中的最小值。
然后将此最小值添加到中global_array,并将变量X替换为Xÿ-此最小值的坐标。

在循环input次数之后,程序将输出该global_array结果。


1
FWIW,是我自己的公式公式,可将坐标转换为螺旋指数。它短了5个字节,但产生浮点数。(我不知道这是不是一个问题。)
Arnauld

(注意 ÿ 在你的代码是 -ÿ在我的网站上。)
Arnauld

@Arnauld谢谢,这样可以节省5个额外的字节。:)编辑:您已经在第一条评论中提到了。; p
凯文·克鲁伊森
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.