... mathを使用できるのに、座標を計算するためだけに0 からnまで反復する必要はありません。
スパイラルが訪れた一連の正方形は次のとおりです。
13
14 5 24
15 6 1 12 23
16 7 2 0 4 11 22
17 8 3 10 21
18 9 20
19
これは「輪」に分けることができます。最初は数字の 0 です。次に、サイズ 4 のリングです。
1
2 4
3
次に、サイズ 8 の 2 つ目のリング:
5
6 12
7 11
8 10
9
次に、サイズ 12 の 3 つ目のリング:
13
14 24
15 23
16 22
17 21
18 20
19
等々。r番目の環のサイズは 4 rで、2( r − 1) r + 1 から 2 r ( r + 1) までの数値が含まれます。
では、どのリングに数字nが含まれているのでしょうか? それは 2 r ( r + 1) ≥ nとなるような最小のrであり、次の 2 次式を使用して見つけることができます。
2 r ( r + 1) ≥ n
∴ 2 r 2 + 2 r − n ≥ 0
∴ r ≥ (−2 + √(4 + 8 n )) / 4
∴ r ≥ ½(−1 + √(1 + 2 n ))
したがって、必要な rは
r = ceil(0.5 * (−1.0 + sqrt(1.0 + 2.0 * n)))
これで、必要な座標を計算するのに十分な情報が得られます。
public spiral_coords(int n) {
if (n == 0) {
return Coords(0, 0);
}
// r = ring number.
int r = (int)(ceil(0.5 * (-1.0 + sqrt(1.0 + 2.0 * n))));
// n is the k-th number in ring r.
int k = n - 2 * (r - 1) * r - 1;
// n is the j-th number on its side of the ring.
int j = k % r;
if (k < r) {
return Coords(-j, r - j);
} else if (k < 2 * r) {
return Coords(-r - j, -j);
} else if (k < 3 * r) {
return Coords(j, -r - j);
} else {
return Coords(r - j, j);
}
}