如何在螺旋图案中找到给定数字的坐标?

问题描述

给定一个数字螺旋,其中数字以三角形的形式排列,我需要编写一个函数,该函数接受一个数字并返回该数字的坐标

           15
           16 14
           17 3  13
           18 4  2  12
           19 5  0> 1  11
           20 6  7  8  9  10
           21 22 23 24 25 26 27 28

例如 17 结果是 (-2,2) in x 和 y

我已经做了一个类似的任务,但螺旋是方形的,程序接收坐标 (x,y) 作为输入并返回一个数字。简而言之,我计算了正方形的大小和偏移量。

如果有任何帮助,我会很高兴

解决方法

TL;DR:底部的工作代码

首先考虑每个三角形中有多少个数字:

  • 第一个在每条边中包含 3 个数字
  • 第二个每条边包含 6 个数字
  • 第三条边的每条边包含 9 个数字

这就是我们的模式。三角形 i 包含 9i 数字,在我们做任何其他事情之前,我们需要将我们的数字除以 9 并找到结果的 triangle root(并将其四舍五入):

enter image description here

一旦你找出了直角三角形,剩下三件事要做:

  • 你需要找到起点

这是微不足道的,因为三角形 i 的“最后一点”将始终是 (2i,i)

  • 您需要找到正确的边缘

您已经知道您的三角形有 i 长的边,因此通过取余数的总和(来自原始 divmod 和生根)并将其除以 3,您可以找到正确的边.

  • 你需要在这条边上找到正确的点

这一点很简单 - 你有 3 种类型的边缘,水平、垂直和对角线。根据您必须将“最终残值”应用于“边缘原点”的类型:

  • (-r,-r) 为对角线
  • (0,r) 用于垂直
  • (r,0) 用于水平

相对于前一个三角形的最大点,您只需应用这些换位的累积总和即可到达右边缘:

  • (-r,-r) 为对角线
  • (-i,-i+r) 用于垂直
  • (-i+r,0) 用于水平

综合起来

def triangle_root(x):
    return int((8 * x + 1) ** 0.5 - 1) // 2

def spiral(v):
    # Identify the current triangle
    i = min(v,triangle_root(max(0,(v - 1) / 9)) + 1)
    # Compute the coordinates for the max value of this triangle
    xi,yi = 2 * i,i
    # Compute the point index in the current triangle
    # In other words,subtract the previous triangle max
    r = v - 9 * (i - 1) * i // 2
    # Compute the edge length for the current triangle
    length = 3 * max(1,i)
    # Compute the current edge and the location in that edge
    edge,r = divmod(r,length)
    # Apply the relevant transform depending on the edge
    if edge == 1: # vertical
        dx,dy = -length,r - length
    elif edge == 2: # horizontal
        dx,dy = r - length,0
    else: # diagonal
        dx,dy = -r,-r
    
    return xi + dx,yi + dy
,

没有代码,但我会从以下内容开始:

  1. 重新排列数字以了解三角形螺旋的结构
 0
 1  2
 3  4  5
 6  7  8  9
10 11 12 13 14
15 16 17 18 19 20
21 22 23 24 25 26 27 
...

请注意,如果我们将完整的线条排列回螺旋形式,我们将得到完整的三角形。

  1. 添加坐标(希望我理解正确。)
0   0                      0,0
1   1  2                   1,0    0,1
2   3  4  5               -1,2   -1,1  -1,0

3   6  7  8  9            -1,-1    0,-1   1,-1   2,-1
4  10 11 12 13 14          3,-1    2,0   1,1   0,2  -1,3 
5  15 16 17 18 19 20      -2,4   -2,3  -2,2  -2,1  -2,0  -2,-1

6  21 22 23 24 25 26 27   -2,-2    ...
...

我还在前面添加了一个行号r:三行在螺旋中形成一个完整的“转弯”。

您可以看到行内的坐标模式,这当然取决于它如何除以 3:

  • 可被 3 整除的行从 -r/3,-r/3 开始并递增 x
  • 余数为 1 的行从 2*(r-1)/3+1,-(r-1)/3 开始,减少 x,增加 y
  • 余数为 2 的行从 -(r+1)/3,2*(r+1)/3 开始递减 y
  1. 找出我们实际上在哪一行

n 中的最后一个数字 r 是“n = {sum i for i from 0 to r+1} = (r+1)(r+2)/2”。我们为 r 解决这个问题并得出:

r = -3/2 + sqrt(9/4 + 2n)

只有积极的解决方案是相关的。

如果我们插入一个数字 n,比如 12,我们会得到 r = 3.6,这意味着我们按预期位于第 4 行的某个位置,请检查行号。

  1. 把东西放在一起
  • 计算当前行号。
  • 通过减去前一行的最后一个数字来计算该行内的位置。 这通常是 n_prev = r*(r+1)/2,在带有 n_prev = 4*5/2 = 10 的示例中是 n=12。 该示例行中的位置为 pos = 12-10 = 2
  • 计算当前行号除以 3 的余数。例如,我们有 4 = 3*1 + 1
  • 现在通过选择适当的公式来计算坐标。例如,我们有行 4、余数 1 和位置 2,所以我们需要
[2*(r-1)/3+1,-(r-1)/3] + pos*[-1,1] = [2*3/3+1,-3/3] + [-2,2] = [1,1]

再次检查您的初始螺旋三角形。