问题描述
给定一个数字螺旋,其中数字以三角形的形式排列,我需要编写一个函数,该函数接受一个数字并返回该数字的坐标
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(并将其四舍五入):
一旦你找出了直角三角形,剩下三件事要做:
- 你需要找到起点
这是微不足道的,因为三角形 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
,
没有代码,但我会从以下内容开始:
- 重新排列数字以了解三角形螺旋的结构
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
...
请注意,如果我们将完整的线条排列回螺旋形式,我们将得到完整的三角形。
- 添加坐标(希望我理解正确。)
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
- 找出我们实际上在哪一行
行 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 行的某个位置,请检查行号。
- 把东西放在一起
- 计算当前行号。
- 通过减去前一行的最后一个数字来计算该行内的位置。
这通常是
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]
再次检查您的初始螺旋三角形。