螺旋序列


29

背景

OEIS序列A272573在六角形网格上描述了一个螺旋,如下所示:

在六角形平铺上开始数字螺旋,初始六角形为a(1)=1。a(n)是不等于或先前不相邻的最小正整数。

序列开始

1, 2, 3, 4, 5, 6, 7, 4, 6, 8, 5, 9, 8, 10, 2, 11, ...

这是螺旋模式的说明: 在此处输入图片说明

  • a(11) != 1因为那样的话31它将在两个地方相邻。
  • a(11) != 2因为那样的话32它将在两个地方相邻。
  • a(11) != 3因为那样3会与自己相邻。
  • a(11) != 4因为那样的话34它将在两个地方相邻。
  • 因此a(11) = 5

挑战

面临的挑战是编写一个计算A272573的程序。这是,因此最短的代码获胜。


我看不到图像,因为它是在这里封锁,所以也许我失去了一些东西,但你的例子显示了一个(11)= 4,但在你的序列列表(11)5
Geobits

只是一个错误-感谢您抓住它。
彼得·卡吉

7
显然,此OEIS序列由您自己提交。真好 :)
Arnauld

n的极限是多少?有时间限制吗?
Setop

5
等待六角答案...
乔纳森·艾伦

Answers:


23

JavaScript的(ES6), 267 ... 206个  199字节

返回包含序列的ñ第一项的数组。

n=>(F=v=>++i<n?F([...v,(A=N[i]=[1,!j++||d+1,j%L?d:(j%=L*6)?++d:L++&&d++].map(k=>N[k=i-k].push(i)&&k),g=k=>v[E='every']((V,x)=>V-k|N[x][E](y=>A[E](z=>v[y]-v[z])))?k:g(-~k))()]):v)([L=1],N=[[i=j=d=0]])

在线尝试!

怎么样?

定义

按照惯例,我们将角单元称为与螺旋的上一层仅具有一个共同边的单元,将侧单元称为与螺旋的上一层具有共同的边的单元。正如Ourous 所建议的,我们还可以将它们分别视为1阶单元格和2阶单元格。

角落单元以黄色显示在下方。所有其他单元格都是辅助单元格(中央单元格除外,这是特例)。

细胞类型

关于小区邻居

我们实际上并不需要跟踪网格上单元的坐标。我们唯一需要知道的是在任何给定时间螺旋中每个单元的邻居单元列表。

在下图中,上一层的邻居以浅色阴影显示,当前层的其他邻居以深色阴影显示。

如果满足以下条件,则一个单元在先前的单元中有2个邻居

  • 它是新层(如8)的第一个边单元
  • 或者它是一个角单元,但不是该层的最后一个单元(例如9

2个邻居

如果满足以下条件,则一个单元在先前的单元中具有3个邻居

  • 它是一个边单元,但不是该层的第一个(如10
  • 或它是当前层的最后一个角单元格(如19

3个邻居

小区邻居的实现

1个一世ñ一种[ñ]

1个-1个

[                    //
  1,                 // the previous cell is always a neighbor of the current cell
  !j++ || d + 1,     // if this is not the first cell of the layer, the cell at -(d + 1)
                     // is a neighbor (otherwise, we insert 1 twice; doing it that way
                     // saves bytes and having duplicate neighbors is not a problem)
  j % L ?            // if this is a side-cell:
    d                //   the cell at -d is a neighbor
  :                  // else (corner-cell):
    (j %= L * 6) ?   //   if this is not the last cell:
      ++d            //     insert the dummy duplicate neighbor at -(d + 1); increment d
    :                //   else (last cell):
      L++ && d++     //     the cell at -d is a neighbor; increment L; increment d
]                    //

在上面的代码中:

  • 大号1个
  • Ĵ1个6×大号
  • d

map()ķ一世-ķ

.map(k =>
  N[k = i - k].push(i) && k
)

查找序列的下一项

ķ

ñv[ñ]

( g =                 // g = recursive function taking
  k =>                // the candidate value k
    v.every((V, x) => // for each previous cell of value V at position x, make sure that:
      V - k           //   V is not equal to k
      |               //   OR
      N[x].every(y => //   for each neighbor y of x:
        A.every(z =>  //     for each neighbor z of the current cell:
          v[y] - v[z] //       the value of y is not equal to the value of z
        )             //     end
      )               //   end
    )                 // end
    ?                 // if the above conditions are fulfilled:
      k               //   stop recursion and return k
    :                 // else:
      g(-~k)          //   try again with k + 1
)()                   // initial call to g with k undefined (this will cause V - k to be
                      // evaluated as NaN and force the 1st iteration to fail)

很好的解释。一项可能的改进:无需横向滚动即可使代码块中的说明完全可见(与打高尔夫球的代码无关)。在Firefox中查看,第一个解释代码块中有5个隐藏列,在第二个解释代码块中有6个隐藏列。
trichoplax

@trichoplax谢谢您的评论和建议。您能否指定您正在使用哪个版本的Firefox,以及在哪个平台上使用?我总是尝试格式化解释块的格式,以便不需要水平滚动。我现在正在使用Firefox 65 / Win10,并且没有任何隐藏的列。
Arnauld

到家后将检查Firefox的版本,但这可能是因为我在Fedora上。将检查另一个操作系统,并让您知道
trichoplax

1
似乎确实因操作系统而异。当我有机会收集一些证据(如果还没有的话)时,将在MSE上提出该问题
trichoplax

1
我已经在MSE上提出了这个问题。如果有人看到显示水平滚动条的其他OS /浏览器组合,请随时进行编辑。
trichoplax

7

干净284个 279 272 262字节

import StdEnv
l=[0,-1,-1,0,1,1]
c(u,v)(p,q)=(u-p)^2+(v-q)^2<2||(u-p)*(q-v)==1
$[h:t]m=hd[[e: $t[(h,e):m]]\\e<-[1..]|and[e<>j\\(u,v)<-m|c h u,(p,q)<-m|q==v,(i,j)<-m|c p i]]

$(scan(\(a,b)(u,v)=(a-u,b-v))(0,0)[(i,j)\\n<-[1..],i<-[1,1:l]&j<-l,_<-[max(~j<<i)1..n]])[]

在线尝试!

永远生成序列。

六角映射

大多数代码都以唯一的方式映射到六边形以进行(x,y)坐标映射,因此只有一个简单的函数即可确定适用于所有点映射的邻接关系。

映射的点如下所示:

              ---
        --- < 2,-2> ---       x-axis ___.X'
  --- < 1,-2> === < 2,-1> ---  /__.X'
< 0,-2> === < 1,-1> === < 2, 0>'
  === < 0,-1> === < 1, 0> ===
<-1,-1> === < 0, 0> === < 1, 1>
  === <-1, 0> === < 0, 1> ===
<-2, 0> === <-1, 1> === < 0, 2>.__
  --- <-2, 1> === <-1, 2> ---  \  'Y.___
        --- <-2, 2> ---       y-axis    'Y.
              ---

从那里,确定邻接关系很简单,并且在以下情况之一时发生:

  • x1 == x2abs(y1-y2) == 1
  • y1 == y2abs(x1-x2) == 1
  • y1 == y2 - 1x2 == x1 - 1
  • y1 == y2 + 1x2 == x1 + 1
  • x1 == x2y1 == y2

点生成

请注意,以螺旋方式遍历六角形时,每一层的差异都会重现n

  1. n 步骤 (1,0)
  2. n-1 步骤 (1,-1)
  3. n 步骤 (0,-1)
  4. n 步骤 (-1,0)
  5. n 步骤 (-1,1)
  6. n 步骤 (0,1)

通过采用此序列的前缀总和,可以按正确的顺序生成点:

scan(\(a,b)(u,v)=(a-u,b-v))(0,0)[(i,j)\\n<-[1..],i<-[1,1:l]&j<-l,_<-[max(~j<<i)1..n]]

汇集在一起

从问题中实际找到序列的代码就是:

$[h:t]m=hd[[e: $t[(h,e):m]]\\e<-[1..]|and[e<>j\\(u,v)<-m|c h u,(p,q)<-m|q==v,(i,j)<-m|c p i]]

反过来主要是通过 and[r<>j\\(u,v)<-m|c h u,(p,q)<-m|q==v,(i,j)<-m|c p i]

该过滤器通过以下方式从m(已映射点的列表)中获取点:

  • 忽略等于任何自然数 j
  • 对于与之相邻的每个(i,j)地方ip
  • 对于每个(p,q)q等于v
  • 对于每一个(u,v),其中u邻近于所述当前点
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.