我有以下数字网格,以0为中心,并以螺旋形式增加。我需要一个算法,它将以螺旋形式接收数字并返回x; y - 如何从0到达该数字的移动数量。例如,对于数字9,它将返回-2; -1。对于4,它将是1; 1。
25|26|... etc.
24| 9|10|11|12
23| 8| 1| 2|13
22| 7| 0| 3|14
21| 6| 5| 4|15
20|19|18|17|16
如果有助于算法更好的话,可以略微改变这种螺旋。 使用你喜欢的任何语言。我真的很感激数学解释。
谢谢。
答案 0 :(得分:4)
首先,我们需要确定我们所处的周期(距离中心的距离)和扇区(北,东,南或西)。然后我们可以确定数字的确切位置。
每个周期的第一个数字如下:1, 9, 25
这是一个二次序列:first(n) = (2n-1)^2 = 4n^2 - 4n + 1
与此相反的是周期数:cycle(i) = floor((sqrt(i) + 1) / 2)
周期的长度为:length(n) = first(n+1) - first(n) = 8n
该部门将是:
sector(i) = floor(4 * (i - first(cycle(i))) / length(cycle(i)))
最后,为了得到这个位置,我们需要从周期和扇区中第一个数字的位置进行推断。
把它们放在一起:
def first(cycle):
x = 2 * cycle - 1
return x * x
def cycle(index):
return (isqrt(index) + 1)//2
def length(cycle):
return 8 * cycle
def sector(index):
c = cycle(index)
offset = index - first(c)
n = length(c)
return 4 * offset / n
def position(index):
c = cycle(index)
s = sector(index)
offset = index - first(c) - s * length(c) // 4
if s == 0: #north
return -c, -c + offset + 1
if s == 1: #east
return -c + offset + 1, c
if s == 2: #south
return c, c - offset - 1
# else, west
return c - offset - 1, -c
def isqrt(x):
"""Calculates the integer square root of a number"""
if x < 0:
raise ValueError('square root not defined for negative numbers')
n = int(x)
if n == 0:
return 0
a, b = divmod(n.bit_length(), 2)
x = 2**(a+b)
while True:
y = (x + n//x)//2
if y >= x:
return x
x = y
示例:强>
>>> position(9)
(-2, -1)
>>> position(4)
(1, 1)
>>> position(123456)
(-176, 80)
答案 1 :(得分:0)
static int threshold=14, x=0, y=0;
public static void main(String[] args) {
int yChange=1, xChange=1, count=0;
while( !end(count) ){
for (int i = 0; i < yChange; i++) {
if( end(count) )return;
count++;
y--;
}
yChange++;
for (int i = 0; i < xChange; i++) {
if( end(count) )return;
count++;
x++;
}
xChange++;
for (int i = 0; i < yChange; i++) {
if( end(count) )return;
count++;
y++;
}
yChange++;
for (int i = 0; i < xChange; i++) {
if( end(count) )return;
count++;
x--;
}
xChange++;
}
}
public static boolean end(int count){
if(count<threshold){
return false;
}else{
System.out.println("count: "+count+", x: "+x+", y: "+y);
return true;
}
}