Daniele
Daniele

Reputation: 4343

algorithm to generate a spiral matrix in java

Write a class that, given a positive integer N, creates and returns a square matrix NxN made out of integers that displays the numbers from 1 to n^2 in a spiral

n=4

In my class I got four methods, three of them are for the direction, while the spiral() method should put every number in the right spot

public static int[][] spiral(int n) {
    int[][] res;
    int i,j;
    int num;
    int direction;

    /** variables initializzazion */
    res=new int[n][n];
    i=0;
    j=0;
    res[i][j]=1;
    direction=0;


    for(num=2; num<=n*n; num++) {
        direction = updateDirection(direction, i, j, n);
        if ((direction==1) || (direction==3))
            i=updateRow(i, direction);
        else
            j=updateColoumn(j, direction);
        res[i][j]=num;
    }
    return res;
}

Sadly, when I try to run it I get an ArrayIndexOutOfBoundException that seems to be caused by the res[i][j]=1;.

How can I fix it so that the Array still starts from 1 and goes up to N*N?

Edit: Added updateDirection() method

to better understand this method have a look at this image:

updateDirection method

public static int updateDirection(int direction, int i, int j, int n) {

    /** if on the secondary diagonal direction is 1 or 3 */
    if(i+j==n-1)
        direction++;
    /** if on the lower half of the main diagonal, direction is 2 */
    if(i==j && j+j>=n)
        direction++;
    /** if on the row below the higher half of the main diagonal, direction is 0 */
    if(i==j+1 && i+j<n)
        direction++;
    /** in other cases, direction doesn't change */

    return direction%4;
    }

Edit2: This is my test method:

public static void testSpiral(){
    for(int n=0; n<=5; n++)
        System.out.println(Arrays.deepToString(spiral(n)));
}

Edit3: updateRow() and updateColoumn() methods added:

public static int updateRow(int i, int direction) {
    int res;
    if(direction==1)
        res=i+1; //moves from top to bottom
    else
        res = i-1; //moves from bottom to top
    return res;
}

public static int updateColoumn(int j, int direction){
    int res;
    if(direction==0)
        res=j+1; //moves from left to right
    else
        res=j-1; //moves from right to left
    return res;

Upvotes: 1

Views: 5006

Answers (3)

fuat
fuat

Reputation: 1842

You do not need a class. This function returns spiral matrix in clockwise. I hope i could help.

int[][] spiralNumbers(int n) {
    int[][] matrix = new int[n][n];
    for (int step = 0, a = 0, size; step < n/2; step++) {
        size = (n - step * 2 - 1);
        for (int i = 0, chunk, chunkIndex, chunkOffset; i < 4 * size; i++) {
            chunk = i / size;
            chunkIndex = i % size;
            chunkOffset = n - step - 1;
            switch (chunk) {
                case 0:
                    matrix[step][chunkIndex + step] = a+1;
                    break;
                case 1:
                    matrix[chunkIndex + step][chunkOffset] = a+1;
                    break;
                case 2:
                    matrix[chunkOffset][chunkOffset - chunkIndex] = a+1;
                    break;
                case 3:
                    matrix[chunkOffset - chunkIndex][step] = a+1;
                    break;
                default:
                    throw new IndexOutOfBoundsException();
            }
            a++;
        }
        if (n % 2 == 1) {
            matrix[n/2][n/2] = n * n;
        }
    }
    return matrix;
}

Upvotes: 1

Arturo Menchaca
Arturo Menchaca

Reputation: 15982

In testSpiral method you are starting the for loop in 0, so the array res is created with size 0.

When you try to set res[i][j] = 1 you are trying to access the first element in the array but there is none.

Just start the for in i=1:

public static void testSpiral(){
    for(int n=1; n<=5; n++)
        System.out.println(Arrays.deepToString(spiral(n)));
}

Upvotes: 2

gbtimmon
gbtimmon

Reputation: 4322

This may or may not do what you want. I think figuring out what it does might teach you a a lot.

import java.util.Arrays;

public class Spiral {

        static final int TEST_X = 5;
        static final int TEST_Y = 5; 
        static enum Direction {UP, DOWN, LEFT, RIGHT};

        public static void main( String ... args ){
            for( int i = TEST_X - 1; i > 0; i--) { 
                for ( int j = TEST_Y - 1 ; j > 0; j-- ){
                    int arr[][] = spiral(i,j);

                    for( int[] inner : Arrays.asList(arr))
                        System.out.println(Arrays.toString(inner));

                    System.out.println("############\n");
                }
            }
        }

        public static int[][] spiral( int rows, int cols ) { 
            if( cols <= 0 || rows <= 0 ){
                throw new IllegalArgumentException("Spiral requires dimensions greater than 0.");
            }
            int arr[][] = new int[rows][cols];

            int     count             = 1; 
            int     cur_col             = -1; 
            int     cur_row             = 0;
            int     consecutive_turns = 0;
            Direction dir             = Direction.RIGHT;


            while( true ) {

                if( consecutive_turns == 4)
                       return arr;

                switch( dir ){
                case RIGHT : 

                    if( cur_col + 1 == cols || arr[cur_row][cur_col + 1] > 0){ 

                        dir = Direction.DOWN;
                        consecutive_turns++;

                    } else {
                        consecutive_turns = 0;
                        cur_col++;
                        arr[cur_row][cur_col] = count;
                        count++;
                    }
                    break;

                case LEFT :

                    if( cur_col - 1 < 0 || arr[cur_row][cur_col - 1] > 0 ){
                        dir = Direction.UP;
                        consecutive_turns++;
                    } else {
                        consecutive_turns = 0;
                        cur_col--;
                        arr[cur_row][cur_col] = count;
                        count++;
                    }
                    break; 

                case UP : 

                    if( cur_row - 1 < 0 || arr[cur_row - 1][cur_col] > 0 ){
                        dir = Direction.RIGHT;
                        consecutive_turns++;
                    } else {
                        consecutive_turns = 0;
                        cur_row--;
                        arr[cur_row][cur_col] = count;
                        count++;
                    }
                    break; 

                case DOWN : 

                    if( cur_row + 1 == rows || arr[cur_row + 1][cur_col] > 0 ){
                        dir = Direction.LEFT;
                        consecutive_turns++;
                    } else {
                        consecutive_turns = 0;
                        cur_row++;
                        arr[cur_row][cur_col] = count;
                        count++;
                    }
                    break;

                default : 
                    System.err.println("The end has come!");
                    System.exit(1); 

                }
            }
        }
    }

Upvotes: 0

Related Questions