I know how to traverse every element of a 2D array, using array[i % n, i / n]
when i=0 < n*m for an,m array. Is there a handy formula to traverse the boundary elements of a 2D array only?
for example, for 2D, given a matrix
only 'a' is traversed. Wish i could illustrate for 3d but hope this clears it up
Assuming clockwise or anticlockwise traversal, Maybe something like, for 1st index:
for n = 5, m = 3.
0 1 2 3 4
11 5
10 9 8 7 6
For i = 0 to 2m + 2n - 5
[ max( i - max( i - (n-1), 0) - max( i - (m+n-2), 0 ), 0) ]
column index first increase from 0 to n-1
Then it stays constant at n-1 upto i = n+m-2
Then it decreases along with i to 0 upto i = 2n + m - 3
Then again it stays constant at 0 upto 2n + 2m - 5.
The graph is:
n-1_________
/ \
/ \
/ \__________
0 n-1 n+m-2 2n+m-3 2n+2m-5
For second index: The graph is:
_______
/ \
/ \
____/ \
0 n n+m 2n+m 2n+2m
You can form similar expression using i.
This is what I came up with for 2D: (it's Java, but to convert to C#, you should only have to replace System.out.print
and Math.ceil
with the C# equivalents)
int n = 5, m = 3;
for (int i = 0; i < 2*(m+n); i++)
{
int x1 = i/(m+2*n),
x2 = (i%(m+n))%n,
x3 = (int)Math.ceil(((m+i)%(m+n)) / m / (1.0*n));
System.out.print(x1*(n-1) + x2 * x3 + " ");
int y1 = i/(m+n) - i/(m+2*n),
y2 = x2,
y3 = (int)Math.ceil((i%(m+n)) / n / (1.0*m));
System.out.println(y1*(m-1) + y2 * y3);
}
The above can of course be written as a single statement that accesses the array if you wish.
Note that, because of (i%(m+n))%n
, this only works if n > m
. The simplest work-around for this is probably to stick this into a function that takes 4 parameters x,y,m,n
, which can easily be swapped depending on whether m
or n
is larger.
Output:
0 0
1 0
2 0
3 0
4 0
0 0
0 1
0 2
0 2
1 2
2 2
3 2
4 2
4 0
4 1
4 2
As you can see, it does repeat 4 corner cells, if that's okay.
Let's see what each xi
looks like (without the Math.ceil
and /(1.0*m)
or /(1.0*n)
):
i x1 x2 x3 y1 y2 y3
0 0 0 1 0 0 0
1 0 1 1 0 1 0
2 0 2 1 0 2 0
3 0 3 2 0 3 0
4 0 4 2 0 4 0
5 0 0 0 0 0 1
6 0 1 0 0 1 1
7 0 2 0 0 2 1
8 0 0 1 1 0 0
9 0 1 1 1 1 0
10 0 2 1 1 2 0
11 0 3 2 1 3 0
12 0 4 2 1 4 0
13 1 0 0 0 0 1
14 1 1 0 0 1 1
15 1 2 0 0 2 1
The Math.ceil
and /(1.0*m)
or /(1.0*n)
is just there to change x3
and y3
to 1 where they're > 1 (which will happen if the applicable limit ( m
or n
) is greater than the other limit ( n
or m
).
The above table can then be used to get the desired traversal by multiplying the first with the limit-1
and adding the product of the second and the third, as can be seen in the print
statements in the code.
Figuring out that the above table would be useful, how to generate it and how to use it was just a matter of playing around a bit.
Yeah, I'm not figuring that out for 3D.
As you can see, something slightly longer is way more readable:
int n = 5, m = 3;
int x = 0, y = 0;
int xInc = 1, yInc = 0;
while (true)
{
System.out.println(x + " " + y);
// got to right, go down
if (x == n-1 && xInc == 1)
{
xInc = 0;
yInc = 1;
}
// got to bottom, go left
else if (y == m-1 && yInc == 1)
{
xInc = -1;
yInc = 0;
}
// got to left, go up
else if (x == 0 && xInc == -1)
{
xInc = 0;
yInc = -1;
}
// got to top, stop
else if (y == 0 && yInc == -1)
{
break;
}
x += xInc;
y += yInc;
}
Output:
0 0
1 0
2 0
3 0
4 0
4 1
4 2
3 2
2 2
1 2
0 2
0 1
0 0
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.