given a spiral of numbers in which the numbers are arranged in the form of a triangle, i need to write a function that takes a number and returns the coordinates of this number
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
for example 17 the result is (-2, 2) in x and y
I already did a similar task, but there the spiral was square and the program received coordinates (x, y) as input and returned a number. in short, there I calculated the size of the square and the offset.
I will be glad for any help
TL;DR: Working code at the bottom
First consider how many numbers you have in each triangle:
So there is our pattern. Triangle i
contains 9i
numbers and the before we do anything else we need to divide our number by 9
and find the triangle root of the result (and round it down):
Once you figure out the right triangle, there are three things left to do:
This is trivial as the "last point" of triangle i
will always be (2i, i)
.
You already know that your triangle has i
-long edges so by taking the sum of your remainders (from the original divmod
and from rooting) and dividing it by 3 you can find the right edge.
This bit is trivial - you have 3 types of edges, horizontal, vertical and diagonal. Depending on the type you have to apply your "final residual value" to the "origin of the edge":
(-r, -r)
for the diagonal(0, r)
for the vertical(r, 0)
for the horizontalRelative to the max point of the previous triangle to get to the right edge you just have to apply a cumulative sum of these transpositions:
(-r, -r)
for the diagonal(-i, -i+r)
for the vertical(-i+r, 0)
for the horizontalPutting it all together
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