2
\$\begingroup\$

Construct a matrix with the following property:

  1. North-west to South East diagonals are squares.

  2. Matrix[i][j] + 1 = Matrix[j][i] for each i less than j.

Example of such m a matrix is here. Also, since it appears this matrix does not have a name, I have named my class "Sqaure Diagonal, Transpose Increment".

Looking for code review, best practices, clever optimzations etc.

public final class SquareDiagonalTransposeIncrement {

    private SquareDiagonalTransposeIncrement() {} 


    public static int[][] getSqaureDiagonalTransposeIncrementMatrix (int dimension) {
        if (dimension < 1) {
            throw new IllegalArgumentException("dimension: " + dimension + " should be greater than 0");
        }

        final int[][] m = new int[dimension][dimension];

        // set the diagonal
        for (int i = 0; i < dimension; i++) {
            m[i][i] = (i + 1) * (i + 1);  
        }


        /*
         * Definition of the quadrant.
         * 
         * - 0th quadrant means a quadrant square matrix from (0,0) to (0,0)
         * - 1st quadrant means a quadrant square matrix from (0,0) to (1,1) 
         * - 2nd quadrant means a quadrant square matrix from (0,0) to (2,2)
         * 
         */
        for (int quadrant = 0; quadrant < dimension - 1; quadrant++) {
            besiegeQuadrant(m, quadrant);
        }

        return m;
    }


    private static void besiegeQuadrant(int[][] m, int quadrant) {
        int value = m[quadrant][quadrant];

       // besiege the quadrant from the eastern and southern boundaries.
        for (int i = 0; i <= quadrant; i++) {
            m[i][quadrant + 1] = ++value; // eastern
            m[quadrant + 1][i] = ++value; // southern
        }
    }

    public static void main(String[] args) {
        int[][] m =  SquareDiagonalTransposeIncrement.getSqaureDiagonalTransposeIncrementMatrix (4);
        assertArrayEquals(new int[]{ 1, 2, 5, 10}, m[0]);
        assertArrayEquals(new int[]{ 3, 4, 7, 12}, m[1]);
        assertArrayEquals(new int[]{ 6, 8, 9, 14}, m[2]);
        assertArrayEquals(new int[]{11,13,15, 16}, m[3]);
    }
}
\$\endgroup\$
3
\$\begingroup\$

Throwing a different spin on the process, I think you are missing an alternate algorithm that produces the same result....

Here is a 'simple' loop that 'works'. It works because it uses a different 'rule' that is based on the pattern that your matrix creates.

The Pattern is obvious when you study the matrix from the bottom-right corner, and work backwards. The initial value is the square of the matrix size. Then you subtract 1 to the left, then another 1 above, and another 1 to the next left, and another 1 to the next above, etc.

private static final int[][] buildMagicMatrix(int size) {
    int value = size * size + 1;
    int[][] matrix = new int[size][size];
    for (int i = size - 1; i >= 0; i--) {
        matrix[i][i] = --value;
        for (int d = i - 1; d >= 0; d--) {
            matrix[i][d] = --value;
            matrix[d][i] = --value;
        }
    }
    return matrix;
}

Using this algorithm you produce results like:

Size 9
    1    2    5   10   17   26   37   50   65
    3    4    7   12   19   28   39   52   67
    6    8    9   14   21   30   41   54   69
   11   13   15   16   23   32   43   56   71
   18   20   22   24   25   34   45   58   73
   27   29   31   33   35   36   47   60   75
   38   40   42   44   46   48   49   62   77
   51   53   55   57   59   61   63   64   79
   66   68   70   72   74   76   78   80   81
\$\endgroup\$
2
\$\begingroup\$

I don't believe that your description uniquely defines the matrix. However, you can fill the upper-right triangle merely by pattern recognition. Starting from the diagonal going up, each column is a sequence descending by 2. From there, just apply the transpose-increment rule.

public static int[][] getSqaureDiagonalTransposeIncrementMatrix(int dim) {
    int[][] m = new int[dim][dim];

    // Fill diagonal and upper-right
    for (int row = 0, col = row; row < dim; row = ++col) {
        m[row][col] = (row + 1) * (row + 1);
        for (--row; row >= 0; --row) {
            m[row][col] = m[row + 1][col] - 2;
        }
    }
    // Fill the lower-left using the transpose-increment rule
    for (int row = 0; row < dim; ++row) {
        for (int col = 0; col < row; ++col) {
            m[row][col] = m[col][row] + 1;
        }
    }
    return m;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.