pythonalgorithmspiral

how do I find a coordinates given a number in Spiral pattern?


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


Solution

  • 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):

    enter image description here

    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":

    Relative 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:

    Putting 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