javaarraysspiral

2D Array Spiral Matrix Pattern with different rows and columns


.. Hello, guys. I have to implement 2D Array in Spiral Matrix Pattern, but the requirement is to get the rows and columns from user input. Using Oracle documents i got to the point that the program result is successful while the rows and columns are equal, but the tests are mostly with different rows and columns.

Task description:

Please, proceed to Spiral class and implement its static method:

int[][] spiral(int rows, int columns) Return a two-dimensional array coming in the form of a table and containing numbers from 1 up to rows * cols. The size of the table will be specified by the given parameters. Numbers fill the "table" clockwise from the top-level corner in a spiral manner.

For example, for parameter values (3, 4), the output array should be:

 1  2  3  4
10 11 12  5
 9  8  7  6

The code that i implement is this:

class Spiral {
    
    static int[][] spiral(int rows, int columns) {

        int[][] matrix = new int[rows][columns];
        int row = 0;
        int col = 0;
        int horizontal = columns - 1;
        int vertical = rows - 1;
        int rotations = 1;
        char move = 'r';

        for(int i = 1; i < rows * columns + 1; i++) {
            matrix[row][col] = i;

            switch(move) {
                case 'r':
                    col += 1;
                    break;
                case 'l':
                    col -= 1;
                    break;
                case 'u':
                    row -= 1;
                    break;
                case 'd':
                    row += 1;
                    break;
            }

            if(i == horizontal) {
                horizontal += vertical;
                
                if(rotations != 2) {
                    rotations = 2;
                }
                else {
                    rotations = 1;
                    vertical -= 1;
                }

                switch(move) {
                    case 'r':
                        move = 'd';
                        break;
                    case 'd':
                        move = 'l';
                        break;
                    case 'l':
                        move = 'u';
                        break;
                    case 'u':
                        move = 'r';
                        break;
                }
            } 
        }
        return matrix;
    }
}

But how i already said, it works only when the rows and columns are equal. When i try with different values in rows and columns i get exception "index out of bounds". My thoughts are probably the problem comes from rotations condition, but i really can't solve this problem. If somebody can help, thanks in advance.


Solution

  • Instead of using a switch-case, you can use a couple directional matrices for tracking movement. You can take advantage of modulo arithmetic for advancing to the next directional index.

    If the next position is in-bounds, set the position. If it is out of bounds or has already been seen, change direction.

    Note: I would avoid starting the loop with int i = 1, you can always add 1 to i when you are setting the value.

    package org.example;
    
    public class Spiral {
        public static void main(String[] args) {
            System.out.println("Spiral Matrix: 3 rows, 4 columns:");
            print(spiral(3, 4));
    
            System.out.println("\nSpiral Matrix: 6 rows, 9 columns:");
            print(spiral(6, 9));
        }
    
        // Based on: https://www.geeksforgeeks.org/print-a-given-matrix-in-spiral-form/
        static final int[] DIR_ROW = { 0, 1, 0, -1 }, DIR_COL = { 1, 0, -1, 0 };
        static int[][] spiral(int rows, int columns) {
           int[][] result = new int[rows][columns];
            if (rows == 0) return result;
            boolean[][] seen = new boolean[rows][columns];
            int x = 0, y = 0, di = 0;
            for (int i = 0; i < rows * columns; i++) {
                result[x][y] = i + 1; // Set value
                seen[x][y] = true; // Mark as seen
                int cr = x + DIR_ROW[di], cc = y + DIR_COL[di]; // Bounds checking
                if (0 <= cr && cr < rows && 0 <= cc && cc < columns && !seen[cr][cc]) {
                    x = cr;
                    y = cc;
                } else {
                    di = (di + 1) % 4; // Next direction index
                    x += DIR_ROW[di];
                    y += DIR_COL[di];
                }
            }
            return result;
        }
    
        static void print(int[][] matrix) {
            for (int r = 0; r < matrix.length; r++) {
                for (int c = 0; c < matrix[r].length; c++) {
                    System.out.printf("%2d", matrix[r][c]);
                    if (c < matrix[r].length - 1) {
                        System.out.print(" ");
                    }
                }
                System.out.println();
            }
        }
    }
    

    Output

    Spiral Matrix: 3 rows, 4 columns:
     1  2  3  4
    10 11 12  5
     9  8  7  6
    
    Spiral Matrix: 6 rows, 9 columns:
     1  2  3  4  5  6  7  8  9
    26 27 28 29 30 31 32 33 10
    25 44 45 46 47 48 49 34 11
    24 43 54 53 52 51 50 35 12
    23 42 41 40 39 38 37 36 13
    22 21 20 19 18 17 16 15 14