最初に、どのサイクル (中心からの距離) とセクター (北、東、南、または西) を決定する必要があります。次に、数値の正確な位置を決定できます。
各サイクルの最初の数値は次のとおりです。1, 9, 25
これは 2 次シーケンスです。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)