Find the position nth element of a rectangular tiled spiral?

十年热恋 提交于 2019-11-30 12:57:25

问题


What is an algorithm to get the nth element of a rectangular tiled spiral?

Here is n:

[ 20  ][ 21  ][ 22  ][ 23  ][ 24  ]
[ 19  ][  6  ][  7  ][  8  ][  9  ]
[ 18  ][  5  ][  0  ][  1  ][ 10  ]
[ 17  ][  4  ][  3  ][  2  ][ 11  ]
[ 16  ][ 15  ][ 14  ][ 13  ][ 12  ]

and here are the corresponding coordinates for n:

[-2,2 ][-1,2 ][ 0,2 ][ 1,2 ][ 2,2 ]
[-2,1 ][-1,1 ][ 0,1 ][ 1,1 ][ 2,1 ]
[-2,0 ][-1,0 ][ 0,0 ][ 1,0 ][ 2,0 ]
[-2,-1][-1,-1][ 0,-1][ 1,-1][ 2,-1]
[-2,-2][-1,-2][ 0,-2][ 1,-2][ 2,-2]

If given n, how to calculate the coordinates?


回答1:


Here is an code in JavaScript. It calculates position for 2D matrix starting with number 1 in a middle (0, 0)

13  12  11  10  25
14   3   2   9  24
15   4   1   8  23
16   5   6   7  22
17  18  19  20  21

/**
 * Finds coordinates (position) of the number
 * 
 * @param {Number} n - number to find position/coordinates for
 * @return {Number[]} - x and y coordinates of the number
 */
function position(n) {
    const k = Math.ceil((Math.sqrt(n) - 1) / 2);
    let t = 2 * k + 1;
    let m = Math.pow(t, 2);

    t -= 1;

    if (n >= m - t) {
        return [k - (m - n), -k];
    }

    m -= t;

    if (n >= m - t) {
        return [-k, -k + (m - n)];
    }

    m -= t;

    if (n >= m - t) {
        return [-k + (m - n), k];
    }

    return [k, k - (m - n - t)];
}



回答2:


Here's a short and sweet answer using just simple math in pseudocode. No conditionals and no iteration. Given tileNum for the tile number:

intRoot=int(sqrt(tileNum));

x=(round(intRoot/2)*(-1^(intRoot+1)))+((-1^(intRoot+1))*(((intRoot*(intRoot+1))-tileNum)-abs((intRoot*(intRoot+1))-tileNum))/2);

y=(round(intRoot/2)*(-1^intRoot))+((-1^(intRoot+1))*(((intRoot*(intRoot+1))-tileNum)+abs((intRoot*(intRoot+1))-tileNum))/2);

Here's a fiddle to see it in action.




回答3:


First, find out which ring your desired element is in (hint: until you get to the outer ring, your spiral is made up of nested squares), then which side (of the 4) it is on, then you're just left with its position on that side.




回答4:


Similar questions exist already... See my non-looping version. You may need to swap and/or negate X/Y coordinates and change the 100's to 0's depending on what orientation and origin you want.

There's also more canonical looping versions.




回答5:


As nobody answered, there is a solution:

def square_spiral(total_steps):
    position = (0,0)
    direction = (1,0)
    turn_steps = [floor(((x+2)**2)/4) for x in range(n+2)]
    for step in range(total_steps):
        if (step in turn_steps):
            direction = (-direction[1],direction[0])
        position = tuple(a+b for a,b in zip(position,direction))
    return position

This simulates a walk through the desired path. You start at position (0,0), walk 1 step to the right, 1 step down, 3 steps left, 3 steps up, and so on, following the spiral. To code this, notice that we are changing our direction on steps of numbers 1, 2, 4, 6, 9, 12, 16, 20 and so on. https://oeis.org/ reveals this is the quarter-square integer sequence. So all we need is a loop where each iteration simulates a step, adding the direction to the position and turning it 90º when the step count is part of the sequence.




回答6:


Here's my solution in javascript using inverse sum of 8 and edge numbering

Complexity : O(1) no iteration loop

function spiral(n) {
    // given n an index in the squared spiral
    // p the sum of point in inner square
    // a the position on the current square
    // n = p + a

    var r = Math.floor((Math.sqrt(n + 1) - 1) / 2) + 1;

    // compute radius : inverse arithmetic sum of 8+16+24+...=
    var p = (8 * r * (r - 1)) / 2;
    // compute total point on radius -1 : arithmetic sum of 8+16+24+...

    en = r * 2;
    // points by edge

    var a = (1 + n - p) % (r * 8);
    // compute de position and shift it so the first is (-r,-r) but (-r+1,-r)
    // so square can connect

    var pos = [0, 0];
    switch (Math.floor(a / (r * 2))) {
        // find the face : 0 top, 1 right, 2, bottom, 3 left
        case 0:
            {
                pos[0] = a - r;
                pos[1] = -r;
            }
            break;
        case 1:
            {
                pos[0] = r;
                pos[1] = (a % en) - r;

            }
            break;
        case 2:
            {
                pos[0] = r - (a %en);
                pos[1] = r;
            }
            break;
        case 3:
            {
                pos[0] = -r;
                pos[1] = r - (a % en);
            }
            break;
    }
    console.log("n : ", n, " r : ", r, " p : ", p, " a : ", a, "  -->  ", pos);
    return pos;
}

Demo : Fiddle



来源:https://stackoverflow.com/questions/10094745/find-the-position-nth-element-of-a-rectangular-tiled-spiral

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!