Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm to reflect octant of a square matrix all seven ways

In a square matrix of even dimension s there are s/4(s/2+1) types of squares which can be reflected seven different ways around the matrix. For example, a 10 x 10 matrix has the unique squares colored in the figure below:

octant

These 15 squares can be reflected around the horizontal, vertical and diagonal axes of the matrix in 7 different ways.

Assuming there are unique values assigned to each type of such element of an n x n array where n is an even number, what is the most efficient way to populate the matrix (in C or Java)? In other words, given a list of 15 values in any structure you wish, you need to populate the rest of the 10 x 10 array with the 15 values by reflections. What is the fastest algorithm to do this?

As an example, here is my first try at this (note that it uses one-based arrays):

public static int[][] valueSquare = new int[11][11];
public static int[][] valueSquareType = {
        { 0, 40,  2, 12, 15, 20 },
        { 0,  2,  1,  4,  8, 12 },
        { 0, 12,  4, 25, 20, 15 },
        { 0, 15,  8, 20, 22, 18 },
        { 0, 20, 12, 15, 18,  0 },
};
static {
    for( int x = 1; x <= 5; x++ ) for( int y = 1; y <= 5; y++ ) valueSquare[ 11 - x ][ y ] = valueSquareType[x][y];
    for( int x = 1; x <= 5; x++ ) for( int y = 1; y <= 5; y++ ) valueSquare[ 11 - x ][ 11 - y ] = valueSquareType[x][y];
    for( int x = 1; x <= 5; x++ ) for( int y = 1; y <= 5; y++ ) valueSquare[ x ][ 11 - y ] = valueSquareType[x][y];
}

One objection to this is that it has a redundant starter array which is reflected 3 ways, instead of a minimal starter array reflected 7 ways. Ideally, I would like a starter array, with just the 15 key values. Also, the looping in my try may not be the fastest approach.

like image 298
Tyler Durden Avatar asked Jun 01 '15 14:06

Tyler Durden


1 Answers

Assuming this is what you mean:

enter image description here

Given the black area in the upper left, then we just need to iterate all elements (i, j) in that area and compute their location in the other areas after mirroring (diagonals overlap so I marked them as gray, but the formulas consider them too and you can apply them to the given diagonal elements too):

Assuming 0-indexing

(i, j) -> (i, n - j - 1)          # red area
       -> (j, n - i - 1)          # yellow area
       -> (j, i)                  # teal area
       -> (n - i - 1, j)          # green area
       -> (n - i - 1, n - j - 1)  # blue area
       -> (n - j - 1, n - i - 1)  # pink area
       -> (n - j - 1, i)          # orange area

So iterate each given black element and copy it to the 7 positions in the other areas. Example:

#include <iostream>

using namespace std;

int v[6][6] = {
        { 0, 3,  2, 12, 15, 20 },
        { 0,  2,  1,  4,  8, 12 },
        { 0, 12,  4, 25, 20, 15 },
        { 0, 15,  8, 20, 22, 18 },
        { 0, 20, 12, 15, 18,  0 },
};


int main()
{
    int n = 6;
    // iterate given black area:
    for (int i = 0; i < n / 2; ++i)
    {
        for (int j = i; j < n / 2; ++j)
        {
            v[i][n - j - 1] = v[i][j]; // copy to red
            v[j][n - i - 1] = v[i][j]; // copy to yellow
            v[j][i] = v[i][j]; // copy to teal
            v[n - i - 1][j] = v[i][j]; // copy to green
            v[n - i - 1][n - j - 1] = v[i][j]; // copy to blue
            v[n - j - 1][n - i - 1] = v[i][j]; // copy to pink
            v[n - j - 1][i] = v[i][j]; // copy to orange;
        }
    }

    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            cout << v[i][j] << " ";
        }
        cout << endl;
    }



    return 0;
}

Output:

0 3 2 2 3 0
3 2 1 1 2 3
2 1 4 4 1 2
2 1 4 4 1 2
3 2 1 1 2 3
0 3 2 2 3 0

Which seems to be what you're after.

like image 127
IVlad Avatar answered Sep 24 '22 02:09

IVlad