Algorithms – Fastest Way to Check if Two Square 2D Arrays Are Rotationally and Reflectively Distinct

algorithmsmath

The best idea I have so far is to rotate first array by {0, 90, 180, 270} degrees and reflect it horizontally or/and vertically. We basically get 16 variations [1] of first array and compare them with second array. if none of them matches the two arrays are rotationally and reflectively distinct.

I am wondering if there is more optimal solution than this brute-force approach?

[1]

0deg, no reflection
0deg, reflect over x
0deg, reflect over y
0deg, reflect over x and y
90deg, no reflection
...

Best Answer

Break this into two problems:

  1. How would you compare two square arrays - I'll call these matrices - that cannot be rotated or reflected, and
  2. How would you compare an item that can be rotated and reflect against another item

Implementing the first problem with a naive approach gives a very simple answer - walk the matrices in parallel, stopping once you find non-equal values. If you walk the entire matrix without non-equal values then the matrices are equal. To walk the matrix, loop through columns, inner loop through each row, and compare values. Note that walking the matrix allows us to enumerate over all items in the matrix as if they were a single linear collection.

For the second problem, there are eight different ways to rotate and reflect a matrix. There are four corners to be used as a starting point, and an algorithm can walk from each corner in two directions (i.e. horizontally or vertically). Thus we will need to perform 'problem 1' over each of the eight perspectives of the original matrix.

How would I implement this? We can walk the eight matrices in parallel or sequentially; I'll implement this sequentially as potentially faster (if the first matrix checked is a match, no other checks are required) but more importantly it will be simpler.

Each of the eight matrices to check should be represented by a walking function f(x) to retrieve the xth value. For instance, in an n by n square array A,

f1(x) = A[x % n, x / n]; // walking rows first, then columns
f2(x) = A[x / n, x % n]; // walking columns first, then rows

// using a different starting point
f3(x) = A[n - (x / n), x % n];
f4(x) = A[n - (x % n), x / n];

and so on. Now simply,

foreach walking function
    foreach value in walking function
        if value not equal to corresponding value in target 
            next walking function
    return true // not non-equal values found
return false // none of the functions matched