螺旋街区


19

如果我们采用自然数并将它们逆时针滚动成一个螺旋,那么我们将得到以下无限螺旋:

                  ....--57--56
                             |
36--35--34--33--32--31--30  55
 |                       |   |
37  16--15--14--13--12  29  54
 |   |               |   |   |
38  17   4---3---2  11  28  53
 |   |   |       |   |   |   |
39  18   5   0---1  10  27  52
 |   |   |           |   |   |
40  19   6---7---8---9  26  51
 |   |                   |   |
41  20--21--22--23--24--25  50
 |                           |
42--43--44--45--46--47--48--49

给定螺旋中的某个数字,您的任务是确定其邻居-意味着该元素的上方,左侧,右侧和下方。

如果我们看一看,27可以发现它具有以下邻居:

  • 以上: 28
  • 剩下: 10
  • 对: 52
  • 下面: 26

因此输出为: [28,10,52,26]

规则

  • 输入将是任何默认I / O格式的数字ñ0
  • 输出将是以任何(一致!)顺序的那个数字的4个邻居的列表/矩阵/ ..
  • 您可以使用以1而不是0开头的螺旋,但是应在答案中指定

例子

输出采用以下格式,[above,left,right,below]并使用基于0的螺线:

0  ->  [3,5,1,7]
1  ->  [2,0,10,8]
2  ->  [13,3,11,1]
3  ->  [14,4,2,0]
6  ->  [5,19,7,21]
16  ->  [35,37,15,17]
25  ->  [26,24,50,48]
27  ->  [28,10,52,26]
73  ->  [42,72,74,112]
101  ->  [100,146,64,102]
2000  ->  [1825,1999,2001,2183]
1000000  ->  [1004003,1004005,999999,1000001]

Answers:


6

R,156字节

function(n){g=function(h)c(0,cumsum(h((4*(0:(n+2)^2)+1)^.5%%4%/%1/2)))
x=g(sinpi)
y=g(cospi)
a=x[n]
b=y[n]
which(x==a&(y==b+1|y==b-1)|y==b&(x==a+1|x==a-1))}

在线尝试!

  • 发布了另一个R答案,因为它与@ngn略有不同
  • 1索引
  • 邻居总是按升序排序
  • 保存了6个字节,删除round和使用cospi(x)/sinpi(x)cos(x*pi)/sin(x*pi)半数(0.51.5等等)更精确
  • 保存了另一个字节,删除了y坐标上的减号,因为结果是相同的(只是上/下邻居被颠倒了)

说明:

如果我们看一下这些值的矩阵坐标,请考虑0放置在的第一个值x=0, y=0,它们是:

x = [0,  1,  1,  0, -1, -1, -1,  0,  1,  2,  2,  2,  2,  1,  0, ...] 
y = [0,  0,  1,  1,  1,  0, -1, -1, -1, -1,  0,  1,  2,  2,  2, ...]

x坐标遵循A174344 OEIS序列与递推公式:

a(1) = 0, a(n) = a(n-1) + sin(mod(floor(sqrt(4*(n-2)+1)),4)*pi/2)

y矩阵坐标使用相同的公式,但用cos代替sin和取反:

a(1) = 0, a(n) = a(n-1) - cos(mod(floor(sqrt(4*(n-2)+1)),4)*pi/2)

因此,在R中,我们可以将公式转换为该函数,并以sinpi/cospi参数为参数:

g=function(h)c(0,cumsum(h((4*(0:(n+2)^2)+1)^.5%%4%/%1/2)))

并生成两个坐标矢量(我们不取y坐标,因为我们得到相同的结果,只是向上/向下的邻居颠倒了):

x=g(sinpi)
y=g(cospi)

请注意,我们已经生成了(n+2)^2坐标,该坐标大于包含它们n及其邻居的最小必要坐标((floor(sqrt(n))+2)^2但更严格的界限是,但是“ golfy”更少)。

因此,既然我们有了所有的坐标,我们首先搜索a,b对应于我们的坐标n

a=x[n]
b=y[n]

最后,我们选择邻居的位置,即:

  • 上/下邻居 where x == a and y == b+1 or b-1
  • 左右邻居 where y == b and x == a+1 or a-1

使用:

which(x==a&(y==b+1|y==b-1)|y==b&(x==a+1|x==a-1))

“稍有不同” :)
ngm

@ngm:嗯...由于您使用的rosetta代码对我来说相当“晦涩”,我以某种方式以与OEIS序列不同但相似的方式生成矩阵的位置索引:D
digEmAll

4

Perl 6的94 83个字节

{my \ s = 0,| [+] flat((1,i ...)Zxx flat(1..Inf Z 1..Inf)); map {first:k,s [$ _] + $ ^ d,s},i,-1,1,-i}

{my \s=0,|[\+] flat((1,*i...*)Zxx(1,1.5...*));map {first :k,s[$_]+$^d,s},i,-1,1,-i}

在线尝试!

s是螺旋坐标的懒惰,无限列表,用复数表示。它是由其他两个无限列表构成的:1, *i ... *创建列表1, i, -1, -i ...1, 1.5 ... *列出清单1, 1.5, 2, 2.5, 3, 3.5 ...。将这两个列表与列表复制一起压缩会生成从每个螺旋坐标到下一个螺旋坐标的步骤列表1, i, -1, -1, -i, -i, 1, 1, 1, i, i, i ...。(列表复制运算符的右侧参数的小数部分将被丢弃。)[\+]对此列表进行三角加法减法()(并将0粘贴到前面)会生成螺旋坐标的列表。

最后,从复数开始s[$_]$_是给函数的唯一的参数),我们查找索引(first :k其中从该数字将抵消复数的螺旋)i-11,和-i


4

Brain-Flak,238个字节

((){[()]<((({}[((()))]<>)<<>{((([{}]({}))([{}]{})())[()]){({}[()])<>}{}}>)<<>({}<(((({}{})()){}<>({}))()())<>>)<>>()())<>{{}((()()()[({})]){}<>({}<{}>))(<>)}>}{}){<>((((())()())()())()())(<>)}{}{({}[()]<<>({}<>)<>({}<({}<({}<>)>)>)<>>)}<>

在线尝试!

输出按左,上,右,下的顺序。

说明

# If n is nonzero:
((){[()]<

  ((

    # Push 1 twice, and push n-1 onto other stack.
    ({}[((()))]<>)

    # Determine how many times spiral turns up to n, and whether we are on a corner.
    # This is like the standard modulus algorithm, but the "modulus" used
    # increases as 1, 1, 2, 2, 3, 3, ...
    <<>{((([{}]({}))([{}]{})())[()]){({}[()])<>}{}}>

  # Push n-1: this is the number behind n in the spiral.
  )<

    # While maintaining the "modulus" part of the result:
    <>({}<

      # Push n+2k+1 and n+2k+3 on top of n-1, where k is 3 more than the number of turns.
      # n+2k+1 is always the number to the right in the direction travelled.
      # If we are on a corner, n+2k+3 is the number straight ahead.
      (((({}{})()){}<>({}))()())<>

    >)<>

  # Push n+1.  If we are on a corner, we now have left, front, right, and back
  # on the stack (from top to bottom)
  >()())

  # If not on a corner:
  <>{{}

    # Remove n+2k+3 from the stack entirely, and push 6-2k+(n+1) on top of the stack.
    ((()()()[({})]){}<>({}<{}>))

  (<>)}

>}{})

# If n was zero instead:
{

  # Push 1, 3, 5, 7 on right stack, and implicitly use 1 (from if/else code) as k.
  <>((((())()())()())()())

(<>)}{}

# Roll stack k times to move to an absolute reference frame
# (switching which stack we're on each time for convenience)
{({}[()]<<>({}<>)<>({}<({}<({}<>)>)>)<>>)}<>

非常令人印象深刻!我想您不会像其他人那样产生整个螺旋,是吗?
ბიმო

3

MATL,15字节

2+1YLtG=1Y6Z+g)

输入和输出基于1。

输出按该顺序给出左,下,上和右邻居。

在线尝试!或者验证除最后两个外的所有测试用例,它们在TIO上超时。

2+      % Implicit input: n. Add 2. This is needed so that
        % the spiral is big enough
1YL     % Spiral with side n+2. Gives a square matrix
t       % Duplicate
G=      % Compare with n, element-wise. Gives 1 for entry containing n
1Y6     % Push 3×3 mask with 4-neighbourhood
Z+      % 2D convolution, keeping size. Gives 1 for neighbours of the
        % entry that contained n
g       % Convert to logical, to be used as an index
)       % Index into copy of the spiral. Implicit display

2
1YL-MATLAB有spiral功能吗?MATLAB什么时候变成了Mathematica?
sundar-恢复莫妮卡

是的,我在看完1YL的含义后就开始使用它了,这Rosetta代码条目是我唯一可以确认它是MATLAB的东西,而不仅仅是MATL便利函数的地方。我开始认为这可能是您添加到MATL打高尔夫球的东西,直到我看到该条目。
sundar-恢复莫妮卡

@sundar Weird不再记录
Luis

3

R,172字节

function(x,n=2*x+3,i=cumsum(rep(rep(c(1,n,-1,-n),l=2*n-1),n-seq(2*n-1)%/%2))){F[i]=n^2-1:n^2
m=matrix(F,n,n,T)
j=which(m==x,T)
c(m[j[1],j[2]+c(-1,1)],m[j[1]+c(-1,1),j[2]])}

在线尝试!

这是R,因此答案显然是0索引。

大部分工作是创建矩阵。受以下代码启发的代码:https : //rosettacode.org/wiki/Spiral_matrix#R


2

JavaScript(ES6),165个字节

用打印索引alert()

f=(n,x=w=y=n+2)=>y+w&&[0,-1,0,1].map((d,i)=>(g=(x,y,A=Math.abs)=>(k=A(A(x)-A(y))+A(x)+A(y))*k+(k+x+y)*(y>=x||-1))(x+d,y+~-i%2)-n||alert(g(x,y)))|f(n,x+w?x-1:(y--,w))

在线尝试!

怎么样?

Xÿž一世Xÿ

一种Xÿ=||X|-|ÿ||+|X|+|ÿ|
小号Xÿ={1个如果 ÿX-1个如果 ÿ<X
一世Xÿ=一种Xÿ2+一种Xÿ+X+ÿ×小号Xÿ

(根据math.stackexchange的答案改编)


使用较小的数字似乎可以正常工作,但是使用2000这样的较大数字进行测试时出现错误。tio.run:RangeError: Maximum call stack size exceeded错误和浏览器控制台错误:InternalError: too much recursion。难道我做错了什么?
夜间2

1
4ñ2

2

Python 2中177个 164 1 46 144字节

def f(n):N=int(n**.5);S=N*N;K=S+N;F=4*N;return[n+[F+3,[-1,1-F][n>K]][n>S],n+[F+5,-1][n>K],n+[[1,3-F][n<K],-1][0<n==S],n+[F+7,1][n<K]][::1-N%2*2]

在线尝试!

u,l,r,d直接从计算n


1

PHP(> = 5.4),208字节

<?$n=$argv[1];for(;$i++<($c=ceil(sqrt($n))+($c%2?2:3))**2;$i!=$n?:$x=-$v,$i!=$n?:$y=+$h,${hv[$m&1]}+=$m&2?-1:1,$k++<$p?:$p+=$m++%2+$k=0)$r[-$v][+$h]=$i;foreach([0,1,0,-1]as$k=>$i)echo$r[$x+$i][$y+~-$k%2].' ';

要运行它:

php -n -d error_reporting=0 <filename> <n>

例:

php -n -d error_reporting=0 spiral_neighbourhoods.php 2001

在线尝试!

笔记:

  • -d error_reporting=0选项用于不输出通知/警告。
  • 此螺旋从1开始。

怎么样?

我正在使用二维数组中此答案的修改版本生成螺旋。

我根据n带有公式的输入来确定螺旋的大小,以便始终在螺旋中获得额外的一轮数字(保证上方/下方/左侧/右侧的存在)。额外的一轮数字表示二维数组的+2高度和+2宽度。

因此,如果n将位于最大尺寸为的螺旋中3*3,则生成的螺旋将为5*5

螺旋大小是c*c其中c = ceil(sqrt(n)) + k,如果ceil(sqrt(n))为奇数,则k是2,并且如果ceil(sqrt(n))是偶数,则k是3。

例如,以上公式将得出以下结果:

  • 如果那样的n = 1c = 3,螺旋尺寸将是3*3
  • 如果那样的n <= 9c = 5,螺旋尺寸将是5*5
  • 如果那样的n <= 25c = 7,螺旋尺寸将是7*7
  • 如果那样的n <= 49c = 9,螺旋尺寸将是9*9
  • 等等 ...

生成螺旋时,我存储xyn生成,然后生成,然后输出其上/下/左/右的元素。

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.