问题
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