Problem Statement is :
Given 2 Dimensional array, print output for example
If 4 rows and 6 columns, output would be:
1 2 3 4 5 6
16 17 18 19 20 7
15 24 23 22 21 8
14 13 12 11 10 9
I tried it is looking like square within square but when I attempted this problem, I put so many while and if loops but didn't got exact answer. If row and columns increases how to handle it?
This is not homework. I was learning solving complex structure so I need to understand it by some guidance.
It's a square spiral.
You can read a bout it here: http://metacpan.org/pod/Math::PlanePath::SquareSpiral
There's an explanation for the formulas .
Here is what I came with.
Variables name may be upside/down, lot of thing to enhance, remove, modify but it was fun game.
public class Test {
public static void main(String[] args) {
int x = 2;
int y = 2;
int idx = 1;
int[][] array = new int[x][y];
int yUpIdx = y-1;
int yDownIdx = 0;
int xLeftIdx = 0;
int xRightIdx = x-1;
while (idx < x*y) {
for (int i = xLeftIdx; idx <= x*y && i <= xRightIdx; i++) {
array[i][yDownIdx] = idx++;
}
yDownIdx++;
for (int j = yDownIdx; idx <= x*y && j <= yUpIdx; j++) {
array[xRightIdx][j] = idx++;
}
xRightIdx--;
for (int i = xRightIdx; idx <= x*y && i>=xLeftIdx ; i--) {
array[i][yUpIdx] = idx++;
}
yUpIdx--;
for (int j = yUpIdx; idx <= x*y && j>=yDownIdx ; j--) {
array[xLeftIdx][j] = idx++;
}
xLeftIdx++;
}
for (int j = 0; j < y; j++) {
for (int i = 0 ; i < x; i++) {
if ((array[i][j]+"").length() < 2) System.out.print(" ");
System.out.print(array[i][j]+" ");
}
System.out.println("");
}
}
Another solution using the same "walk in a spiral" algo:
public class SpiralArray {
private int[][] cells;
private int rows;
private int cols;
private enum Direction {
LEFT,
DOWN,
RIGHT,
UP
}
public SpiralArray(int cols, int rows) {
this.cols = cols;
this.rows = rows;
cells = new int[cols][rows];
int count = 0;
Direction direction = Direction.RIGHT;
int x=0, y=0;
while (count++ < cols*rows) {
cells[x][y]=count;
switch (direction) {
case LEFT:
if ((--x<0) || (cells[x][y]>0)) {
y--;
x++;
direction = Direction.UP;
}
break;
case RIGHT:
if ((++x==cols) || (cells[x][y]>0)) {
y++;
x--;
direction = Direction.DOWN;
}
break;
case UP:
if ((--y<0) || (cells[x][y]>0)) {
x++;
y++;
direction = Direction.RIGHT;
}
break;
case DOWN:
if ((++y==rows) || (cells[x][y]>0)) {
x--;
y--;
direction = Direction.LEFT;
}
break;
}
}
}
int get(int i, int j) {
return cells[i][j];
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
for (int y=0; y<rows; y++) {
for (int x=0; x<cols; x++) {
sb.append(cells[x][y]).append("\t");
}
sb.append("\n");
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(new SpiralArray(6, 4));
}
}
I hope this idea can get you started:
void solve2DArray(bool[][] 2DArray, int i, int j, int numMoves)
{
2DArray[i][j] = true; // Mark current position as visited
// Perhaps a print statement here
if(right is not visited and can move right)
// move right
else if(down is not visited and can move down)
// move down
// ...
// ...
}
I'd probably create an NxM integer array, initialized to zero. Set nextNumber
to 1, position
to 0,0, and direction
to left-to-right
. Check the position
for being outside the array, and check the cell at position
for zero. If position
is OK and the cell is zero store nextNumber
there and increment nextNumber
. Then, based on direction
, increment position
.
If the cell at position
is non-zero, or one of the indices of position
is < 0 or >= the array size, you need to change direction. First back up position
by 1, using the existing direction. Then pick a new direction
that is 90 degrees from the current value, increment position
, and try again.
When you can't go any direction you're done -- print the array.
(Probably a few boundary conditions I mishandled above, but that's one basic algorithm.)
(Hint: Write a subroutine to increment/decrement position
based on direction
.)
I guess you can just create a worm that travels through your array:
public class Worm {
public static void main(String[] args) {
int[][] outArray = runWormRun(6, 4);
printArray(outArray);
}
private static void printArray(int[][] outArray) {
for (int j = 0; j < outArray[0].length; j++) {
for (int i = 0; i < outArray.length; i++) {
System.out.print(String.format("%02d ", outArray[i][j]));
}
System.out.println();
}
}
private static int[][] runWormRun(int w, int h) {
int[][] output = new int[w][h];
int counter = 0;
int wormX = 0, wormY = 0;
int minX = 0, maxX = w - 1, minY = 0, maxY = h - 1;
int dirX = 0, dirY = 1;
while (counter < w * h) {
output[wormX][wormY] = ++counter;
// let the worm walk
wormX += dirX;
wormY += dirY;
// update direction of worm for next iteration
if ((dirX != 0 && dirY != 1) && wormX == minX && wormY == minY) { // upper left border (and not yet rotated correctly
dirX = 0; dirY = 1; minY++;
}
if ((dirX != -1 && dirY != 0) && wormX == maxX && wormY == minY) { // upper right border
dirX = -1; dirY = 0; maxX--;
}
if ((dirX != 0 && dirY != -1) && wormX == maxX && wormY == maxY) { // lower right border
dirX = 0; dirY = -1; maxY--;
}
if ((dirX != 1 && dirY != 0) && wormX == minX && wormY == maxY) { // lower left border
dirX = 1; dirY = 0; minX++;
}
}
return output;
}
}
And yes, my worm travels in the other direction, because I want you to think a bit too and understand, what I was doing. Because I think that this is homework. (If that's true, would you please consider adding the "homework" tag to your question?)
EDIT: Ooops, does not exactly, what it should do. No time now, will look into that in the evening.
Another take:
public class Test {
enum Dir {
R(0,1), L(0,-1), D(1,0), U(-1,0);
public final int rowd, cold;
private Dir(int rowd, int cold) { this.rowd = rowd; this.cold = cold; }
public Dir next() { return values()[(ordinal()+1) % values().length]; }
}
static final int rows = 4, cols = 6;
static final int[][] grid = new int[rows][cols];
static int row, col = -1, step;
public static void main(String[] args) {
Dir dir = Dir.R;
moving: while (true) {
for (int i = 0; i < Dir.values().length; i++, dir = dir.next())
if (move(dir)) continue moving;
break;
}
for (int[] row : grid) System.out.println(Arrays.toString(row));
}
static boolean move(Dir dir) {
final int newRow = row+dir.rowd, newCol = col+dir.cold;
if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols
&& grid[newRow][newCol] == 0)
{
row = newRow; col = newCol; grid[row][col] = ++step; return true;
}
return false;
}
}
Square Spiral
Here is a compact solution in a single function that performs optimally (it only visits each location in the array exactly once):
static int anMoveXDir[] = { 1, 0, -1, 0 };
static int anMoveYDir[] = { 0, 1, 0, -1 };
static void DoSpiral(int *panGrid, int nWidth, int nHeight)
{
int nSideSel, nSideIdx, nMoveDir, nXPosn, nYPosn, nCounter;
int anSideLen[2];
anSideLen[0] = nWidth;
anSideLen[1] = nHeight - 1;
nMoveDir = 0; /* start off at (0, 0) in array, */
nXPosn = 0; /* facing east, and count from 1 */
nYPosn = 0;
nCounter = 1;
for (nSideSel = 0; anSideLen[nSideSel & 1]; anSideLen[nSideSel++ & 1]--)
for (nSideIdx = anSideLen[nSideSel & 1]; nSideIdx; nSideIdx--)
{
panGrid[(nYPosn * nWidth) + nXPosn] = nCounter++;
if (nSideIdx == 1)
nMoveDir = (nMoveDir + 1) & 3;
nXPosn += anMoveXDir[nMoveDir];
nYPosn += anMoveYDir[nMoveDir];
}
}
This algorithm works on the simple rule that given a rectangular or square array of width x
and height y
, then the walking the array to create a Square Spiral can be done using the following number of steps:
x + (y - 1) + (x - 1) + (y - 2) + (x - 2) + (y - 3) + (x - 3) + ... + 0
The function above simply follows the above sequence. It starts at the top-left of the array facing east, walks x
steps, turns right 90 degrees, walks (y - 1)
steps, turns right 90 degress, walks (x - 1)
steps, etc. etc. until either x
or y
is zero, whichever comes first.
You can test the function above by inserting it into the test program below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GRID_WIDTH 7
#define GRID_HEIGHT 11
void main()
{
int nXPosn, nYPosn;
int anGrid[GRID_WIDTH * GRID_HEIGHT];
int *pnValue;
DoSpiral(anGrid, GRID_WIDTH, GRID_HEIGHT);
for (pnValue = anGrid, nYPosn = 0; nYPosn < GRID_HEIGHT; nYPosn++, printf("\n"))
for (nXPosn = 0; nXPosn < GRID_WIDTH; printf("%4i", *pnValue++), nXPosn++);
}
The output will be as follows (for a 7x11 grid as indicated in the above program):
1 2 3 4 5 6 7
32 33 34 35 36 37 8
31 56 57 58 59 38 9
30 55 72 73 60 39 10
29 54 71 74 61 40 11
28 53 70 75 62 41 12
27 52 69 76 63 42 13
26 51 68 77 64 43 14
25 50 67 66 65 44 15
24 49 48 47 46 45 16
23 22 21 20 19 18 17
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.