Search code examples
pythonjavamatrixdiagonal

Filling matrix with characters so they form a neat cross, where every lesser diagonal is (char + 1)


Plot goal

The goal is to plot this pattern, where N is in [4,100] range. Main diagonals are always 'a', neighbours of a should be b, neighbours of b should be c and so on. If we have already iterated to z character - switch to a back.

Code below is an attempt to plot an easier pattern but diagonals go from bottom-left to top-right corners, I'm very bad at indices :\

Easy pattern

import java.util.*;

class Solution {

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int number = sc.nextInt();

        char[][] array = new char[number][number];

        char paint = 'a';

        for (int t = 0; t < (number * number - 2); t++) {
            for (int k = 0; k < number; k++) {
                for (int j = 0; j < number; j++) {
                    if (k + j == t) {
                        array[k][j] = paint;
//                        System.out.print(array[k][j] + " ");
                    }
                }

            }
            if (paint == 123) {
                paint = (char) 97;
            } else {
                paint += 1;
            }
            

        for (char[] row : array)
        {
            System.out.println(Arrays.toString(row));
        }
    }
}

plots for n = 5:

[a, b, c, d, e]
[b, c, d, e, f]
[c, d, e, f, g]
[d, e, f, g, h]
[e, f, g, h, i]

I figured the diagonals have equal sums of indices of every element that is located on said diagonal, however there is also another pattern that uses middle central cross, it acts as a line of symmetry but figuring out indices formula for matrix quadrants is way out of my league.

Any advice please?


Solution

  • That's a funny problem you have here. I think I came up with a solution, but first let me explain how I thought of it.

    Instead of dynamically change the character, I thought it was possible to simply loop over all the elements of the matrix, and decide the character based on some arithmetic.

    It seems, as you pointed out, that your matrix is actually highly symmetric, and that the four quadrants are related. That means you might go along half of your matrix only in both directions, and set four elements at once with the right character (one in each quadrant).

    Starting with an even size of the matrix for simplicity, you can find a formula that corresponds to the character at index i,j in the top left quadrant. That's the formula which defines indexLetter. Using symmetry, you can set each corresponding element in the other quadrants directly.

    If you want a matrix of odd size, well, that's almost the same, except you need to take (N+1)/2 instead of N/2.

    That gives next result:

    import java.util.*;
    
    class Solution {
    
        final static String alphabet = "abcdefghijklmnopqrstuvwxyz";
    
        public static void main(String[] args) {
    
            Scanner sc = new Scanner(System.in);
    
            int number = sc.nextInt();
    
            char[][] array = new char[number][number];
    
            for(int i = 0; i < Math.floor((number+1)/2); i++)
            {    
                for (int j = 0; j < Math.floor((number+1)/2); j++)
                {
                    //determine the index of the right character 
                    //using some arithmetics
    
                    //next number works for both even and odd inputed number
                    int nbLetters = (int)Math.floor((number+1)/2);
                    int indexLetter = Math.abs(j - i) % nbLetters;
                    
                    //set it back in all parts of the graphs
                    array[i][j] = alphabet.charAt(indexLetter);
                    array[i][number-j-1] =  alphabet.charAt(indexLetter);
                    array[number-i-1][j] =  alphabet.charAt(indexLetter);                
                    array[number-i-1][number-j-1] =  alphabet.charAt(indexLetter);
                }
            }
    
            //print it back
            for (char[] row : array)
            {
                System.out.println(Arrays.toString(row));
            }
        }
    }
    

    Note: if you want to take a size greater than 52, you have to adapt a little the previous answer by the way (adding a modulo somewhere I guess).