i have this system of equations1=x⊕y⊕z
1=x⊕y⊕w
0=x⊕w⊕z
1=w⊕y⊕zI'm trying to implement gaussian elimination to solve this system as described here , replacing division,subtraction and multiplication by XOR, but it gives my wrong answer..the correct answer is (x,y,z,w)=(0,1,0,0) what am i doing wrong ?
public static void ComputeCoefficents(byte[,] X, byte[] Y)
{
int I, J, K, K1, N;
N = Y.Length;
for (K = 0; K < N; K++)
{
K1 = K + 1;
for (I = K; I < N; I++)
{
if (X[I, K] != 0)
{
for (J = K1; J < N; J++)
{
X[I, J] /= X[I, K];
}
//Y[I] /= X[I, K];
Y[I] ^= X[I, K];
}
}
for (I = K1; I < N; I++)
{
if (X[I, K] != 0)
{
for (J = K1; J < N; J++)
{
X[I, J] ^= X[K, J];
}
Y[I] ^= Y[K];
}
}
}
for (I = N - 2; I >= 0; I--)
{
for (J = N - 1; J >= I + 1; J--)
{
//Y[I] -= AndOperation(X[I, J], Y[J]);
Y[I] ^= (byte)(X[I, J]* Y[J]);
}
}
}
I think you're trying to apply Gaussian elimination mod 2 for this.
In general you can do Gaussian elimination mod k, if your equations are of the form
a_1 * x + b_1 * y + c_1 * z = d_1
a_2 * x + b_2 * y + c_2 * z = d_2
a_3 * x + b_3 * y + c_3 * z = d_3
a_4 * x + b_4 * y + c_4 * z = d_4
And in Z2 * is and and + is xor, so you can use Gausian elimination to solve equations of the form
x (xor) y (xor) z = 1
x (xor) y (xor) w = 1
x (xor) z (xor) w = 0
y (xor) z (xor) w = 1
Lets do this equation using Gausian elimination by hand.
The corresponding augmented matrix is:
1 1 1 0 | 1
1 1 0 1 | 1
1 0 1 1 | 0
0 1 1 1 | 1
1 1 1 0 | 1
0 0 1 1 | 0 (R2 = R2 + R1)
0 1 0 1 | 1 (R3 = R3 + R1)
0 1 1 1 | 1
1 1 1 0 | 1
0 1 1 1 | 1 (R2 = R4)
0 1 0 1 | 1
0 0 1 1 | 0 (R4 = R2)
1 0 0 1 | 0 (R1 = R1 + R2)
0 1 1 1 | 1
0 0 1 0 | 0 (R3 = R3 + R2)
0 0 1 1 | 0
1 0 0 1 | 0
0 1 0 1 | 1 (R2 = R2 + R3)
0 0 1 0 | 0
0 0 0 1 | 0 (R4 = R4 + R3)
1 0 0 0 | 0 (R1 = R1 + R4)
0 1 0 0 | 1 (R2 = R2 + R4)
0 0 1 0 | 0
0 0 0 1 | 0
Giving your solution of (x,y,z,w) = (0,1,0,0).
But this requires row pivoting - which I can't see in your code.
There's also some multiplications and divisions floating around in your code that probably dont need to be there. I'd expect the code to look like this: (You'll need to fix the TODOs).
public static void ComputeCoefficents(byte[,] X, byte[] Y) {
int I, J, K, K1, N;
N = Y.Length;
for (K = 0; K < N; K++) {
//First ensure that we have a non-zero entry in X[K,K]
if( X[K,K] == 0 ) {
for(int i = 0; i<N ; ++i ) {
if(X[i,K] != 0 ) {
for( ... ) //TODO: A loop to swap the entries
//TODO swap entries in Y too
}
}
if( X[K,K] == 0 ) {
// TODO: Handle the case where we have a zero column
// - for now we just move on to the next column
// - This means we have no solutions or multiple
// solutions
continue
}
// Do full row elimination.
for( int I = 0; I<N; ++I)
{
if( I!=K ){ //Don't self eliminate
if( X[I,K] ) {
for( int J=K; J<N; ++J ) { X[I,J] = X[I,J] ^ X[K,J]; }
Y[J] = Y[J] ^ Y[K];
}
}
}
}
//Now assuming we didnt hit any zero columns Y should be our solution.
}
Related
I'm playing with Levenshtein distance for getting a C# implementation which allows not only to tell whether two strings are similar, but also find a similar string (the needle) in a larger string (the haystack).
To this end, I tried to follow the advice at the bottom of this excellent post, but I'm getting some issues.
To start with, I adopted this implementation, changing it to fit my additional requirements. I also added some diagnostic dump support to let me understand the algorithm better, inspired by this other post.
My implementation returns an object with score and (when requested) index and length, and also a reference to the calculated matrix used for diagnostic purposes:
public class LevenshteinMatch
{
public int Score { get; }
public int Index { get; }
public int Length { get; }
public int[,] Matrix { get; set; }
public LevenshteinMatch(int score, int index = 0, int length = 0)
{
Score = score;
Index = index;
Length = length;
}
public override string ToString()
{
return $"{Score} #{Index}x{Length}";
}
}
Here is my implementation: the Distance method works "normally" if sub is false; otherwise, it finds a similar substring. DumpMatrix is just a diagnostic helper method.
public static class Levenshtein
{
public static string DumpMatrix(int[,] d, string a, string b)
{
if (d == null) throw new ArgumentNullException(nameof(d));
if (a == null) throw new ArgumentNullException(nameof(a));
if (b == null) throw new ArgumentNullException(nameof(b));
// # k i t t e n
// 00 01 02 03 04 05 06
// # 00 .. .. .. .. .. .. ..
// s 01 .. .. .. .. .. .. ..
// ...etc (sitting)
StringBuilder sb = new StringBuilder();
int n = a.Length;
int m = b.Length;
// b-legend
sb.Append(" # ");
for (int j = 0; j < m; j++) sb.Append(b[j]).Append(" ");
sb.AppendLine();
sb.Append(" 00 ");
for (int j = 1; j < m; j++) sb.AppendFormat("{0:00}", j).Append(' ');
sb.AppendFormat("{0:00} ", m).AppendLine();
// matrix
for (int i = 0; i <= n; i++)
{
// a-legend
if (i == 0)
{
sb.Append("# 00 ");
}
else
{
sb.Append(a[i - 1])
.Append(' ')
.AppendFormat("{0:00}", i)
.Append(' ');
}
// row of values
for (int j = 0; j <= m; j++)
sb.AppendFormat("{0,2} ", d[i, j]);
sb.AppendLine();
}
return sb.ToString();
}
private static LevenshteinMatch BuildMatch(string a, string b, int[,] d)
{
int n = a.Length;
int m = b.Length;
// take the min rightmost score instead of the bottom-right corner
int min = 0, rightMinIndex = -1;
for (int j = m; j > -1; j--)
{
if (rightMinIndex == -1 || d[n, j] < min)
{
min = d[n, j];
rightMinIndex = j;
}
}
// corner case: perfect match, just collect m chars from score=0
if (min == 0)
{
return new LevenshteinMatch(min,
rightMinIndex - n,
n);
}
// collect all the lowest scores on the bottom row leftwards,
// up to the length of the needle
int count = n, leftMinIndex = rightMinIndex;
while (leftMinIndex > -1)
{
if (d[n, leftMinIndex] == min && --count == 0) break;
leftMinIndex--;
}
return new LevenshteinMatch(min,
leftMinIndex - 1,
rightMinIndex + 1 - leftMinIndex);
}
public static LevenshteinMatch Distance(string a, string b,
bool sub = false, bool withMatrix = false)
{
if (a is null) throw new ArgumentNullException(nameof(a));
if (b == null) throw new ArgumentNullException(nameof(b));
int n = a.Length;
int m = b.Length;
int[,] d = new int[n + 1, m + 1];
if (n == 0) return new LevenshteinMatch(m);
if (m == 0) return new LevenshteinMatch(n);
for (int i = 0; i <= n; i++) d[i, 0] = i;
// if matching substring, leave the top row to 0
if (!sub)
{
for (int j = 0; j <= m; j++) d[0, j] = j;
}
for (int j = 1; j <= m; j++)
{
for (int i = 1; i <= n; i++)
{
if (a[i - 1] == b[j - 1])
{
d[i, j] = d[i - 1, j - 1]; // no operation
}
else
{
d[i, j] = Math.Min(Math.Min(
d[i - 1, j] + 1, // a deletion
d[i, j - 1] + 1), // an insertion
d[i - 1, j - 1] + 1 // a substitution
);
}
}
}
LevenshteinMatch match = sub
? BuildMatch(a, b, d)
: new LevenshteinMatch(d[n, m]);
if (withMatrix) match.Matrix = d;
return match;
}
}
To be more complete, here is the demo console program using it. This just prompts the user for the matching mode (substring or not) and the two strings, then calls the Distance method, dumps the resulting matrix, and shows the substring if required.
internal static class Program
{
private static string ReadLine(string defaultLine)
{
string s = Console.ReadLine();
return string.IsNullOrEmpty(s) ? defaultLine ?? s : s;
}
private static void Main()
{
Console.WriteLine("Fuzzy Levenshtein Matcher");
string a = "sitting", b = "kitten";
bool sub = false;
LevenshteinMatch match;
while (true)
{
Console.Write("sub [y/n]? ");
string yn = Console.ReadLine();
if (!string.IsNullOrEmpty(yn)) sub = yn == "y" || yn == "Y";
Console.Write(sub? $"needle ({a}): " : $"A ({a}): ");
a = ReadLine(a);
Console.Write(sub? $"haystack ({b}): " : $"B ({b}): ");
b = ReadLine(b);
match = Levenshtein.Distance(a, b, sub, true);
Console.WriteLine($"{a} - {b}: {match}");
Console.WriteLine(Levenshtein.DumpMatrix(match.Matrix, a, b));
if (sub) Console.WriteLine(b.Substring(match.Index, match.Length));
}
}
}
Now, for substring matches this works in a case like "aba" in "c abba c". Here is the matrix:
aba - c abba c: 1 #3x3
# c a b b a c
00 01 02 03 04 05 06 07 08
# 00 0 0 0 0 0 0 0 0 0
a 01 1 1 1 0 1 1 0 1 1
b 02 2 2 2 1 0 1 1 1 2
a 03 3 3 3 2 1 1 1 2 2
Yet, in other cases, e.g. "abas" in "ego sum abbas Cucaniensis", I fail to collect the min scores from the bottom row:
abas - ego sum abbas Cucaniensis: 1 #-2x15
# e g o s u m a b b a s C u c a n i e n s i s
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
# 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
a 01 1 1 1 1 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1
b 02 2 2 2 2 2 2 2 2 2 1 0 1 1 1 2 2 2 2 1 1 2 2 2 2 2 2
a 03 3 3 3 3 3 3 3 3 3 2 1 1 1 2 2 3 3 3 2 2 2 3 3 3 3 3
s 04 4 4 4 4 4 3 4 4 4 3 2 2 2 1 2 3 4 4 3 3 3 3 4 3 4 3
Here there is just a single score=1 in the bottom row. In the case of a perfect match (score=0) my code just takes the left N-characters (where N is the length of the needle) from the rightmost lowest score; but here I have scores greater than 0. Probably I've just misinterpreted the hints in the above post, as I'm new to the interals of this algorithm. Could anyone suggest the correct way of finding the needle's index and length in the haystack?
You start at the best score in the bottom row: the 1 at (13,4)
Then you find look at the predecessor states and transitions that could have got you there:
(12,4) - not possible, because it has a higher difference
(13,3) - not possible, because it has a higher difference
(12,3) - same difference and the characters match, so this works
From (12,3) you follow the same procedure to get to (11,2) and then (10,1)
At (10,1) the letters don't match, so you couldn't have come from (9,0). You could use either (10,0) for the similar string "bas", or you could use (9,1) then (8,0) for the similar string "abbas", both with distance 1.
I use a nested for loop to create a grid of hexagons. This creates a square grid:
for (int z = 0; z < gridSize; z++)
{
for (int x = 0; x < gridSize; x++)
{
// creates verts for a hexagon shape which later form a mesh
// x and z form the basis of the Vector3 position of the center
// of each hexagon
CreateCell(x, z);
}
}
I've drawn the start and end values for z & x on the image.
What I'd like is to have the grid itself also shaped hexagonally:
I think figured out the limits for x:
int greaterThan = Mathf.RoundToInt(gridSize/ 3) - 1;
int lessThan = width - greaterThan;
And that (I think) x should only be at it's min and max (0 & 6 in the examples) when z = gridSize / 2 rounded up, though I may well be wrong!
I tried putting a bunch if IFs in the loops but it quickly started to get overly complicated, I figure there must be a more 'mathsy' way to do it, but sadly I'm not mathsy!
Any idea how I can write a loop to form the required pattern?
If #AsfK's solution is not good enough, I'll give it a try as well:
private static void PrintHexLine(int z, int size)
{
if (z >= size)
{
z = 2 * size - 2 - z;
}
int start = size - z - 1;
int end = start + size + z;
for (int x = 0; x < start; x++)
{
Console.Write(" ");
}
for (int x = start; x < end; x++)
{
Console.Write("* ");
//Console.Write((x - start / 2) + " "); // position v1
//Console.Write((x - (start + 1) / 2) + " "); // position v2
}
Console.WriteLine();
}
public static void PrintHex(int size)
{
for (int z = 0; z < 2 * size - 1; z++)
{
PrintHexLine(z, size);
}
}
With such code PrintHex(4) results in
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * *
* * * * *
* * * *
And if you uncomment the position v1 line instead of the one that prints "* ", you'll get
2 3 4 5
1 2 3 4 5
1 2 3 4 5 6
0 1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5
2 3 4 5
similarly position v2
1 2 3 4
1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5 6
0 1 2 3 4 5
1 2 3 4 5
1 2 3 4
which looks like the x indices you want. Basing on your data I'm not really sure whether you need v1 or v2 variant. The v2 looks more consistent to me but it really depends on how your CreateCell(x, z); treats the x = 0 case.
P.S. obviously you can inline PrintHexLine call but it means having two different z variables that you should not mess up with and I think it is cleaner to move that in a separate method.
According your excepted picture the center is the long row (gridSize = 7).
floor(7/2) = 3 (/2 because the long row is in the center)
Now, gridSize - 3 = 4 ==> 4 items in your first row
Then each iterate add one till you have 7 items in one row.
Then do a minus...
it's the code (draw "*", not added spaces before and after..)
int gridSize = 7;
int center = 7/2;
int delta = 1;
for (int r = 0; r < gridSize; r++) {
for (int c = gridSize - center; c < gridSize + delta; c++){
System.out.print("*");
// location of c = c - delta (position)
}
System.out.println();
if (r < center)
delta++;
else
delta--;
}
Thanks to a hint from AsfK I solved it like this
int xL, xU, xMid, zM2;
xL = Mathf.FloorToInt(width / 3) - 1;
xU = (width - xL) + 1;
xMid = Mathf.FloorToInt(width / 2);
for (int z = 0; z < height; z++)
{
for (int x = xL; x < xU; x++)
{
CreateCell(x, z);
}
zM2 = z % 2;
if(z < xMid)
{
if (zM2 == 0)
{
xL--;
}
if (z > 0 && zM2 == 1)
{
xU++;
}
} else
{
if (zM2 == 1)
{
xL++;
}
if (zM2 == 0)
{
xU--;
}
if (z == width - 1)
{
xL--;
xU++;
}
}
}
Would be great if anyone can think of a more elegant solution!
I am trying to calculating e number by that
e = 1 + (1/1! + 1/2! + 1/3! + ..)
User going to select number of trials on that form.
form
int trialNumber = Convert.ToInt32(Math.Round(trialNumberForm.Value, 0));
int factorial = trialNumber;
float factResult = 0;
for (int i = 1; i < trialNumber; i++)
{
for (int b = 1; b < i; b++) //calculates x! here.
{
factorial = factorial * b;
}
factResult = factResult + (1 / factorial);
}
factResult++;
MessageBox.Show(factResult.ToString());
It calculates the result 1 which ever number you selected! I've tried to change variable type to float from double but that didn't fix it. How to act on numbers by formula which I wrote above?
You have no need in factorial (with its integer division and integer overflow problems) at all since
1/(n+1)! == (1/n!)/(n+1)
You can implement e computation as easy as
double factResult = 1; // turn double into float if you want
double item = 1; // turn double into float if you want
for (int i = 1; i < trialNumber; ++i)
factResult += (item /= i);
...
MessageBox.Show(factResult.ToString());
Outcomes:
trial number | e
-------------------------------
1 | 1
2 | 2
3 | 2.5
4 | 2.666666...
5 | 2.708333...
10 | 2.71828152557319
15 | 2.71828182845823
20 | 2.71828182845905
As #kabdulla and #ScottChamberlain said, you are doing integer division where you need a float division :
for (int b = 1; b < i; b++) //calculates x! here.
{
factorial = factorial * b;
}
factResult = factResult + (1 / factorial);
Should be
for (int b = 2; b < i; b++) //calculates x! here.
{
factorial = factorial * b;
}
factResult = factResult + (1.0 / factorial);
Plus I started the for loop at b = 2 because multiplying by 1 is useless.
For a given number n I have to print the following matrix (n = 3 example):
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3
the count of rows and columns should be (2 * n) - 1. I tried to find the pattern but couldn't figured it out. Any help would be helpful. Thanks
Something like this:
private static int[][] Matrix(int n) {
// Create arrays
int[][] result = Enumerable.Range(0, 2 * n - 1)
.Select(_ => new int[2 * n - 1])
.ToArray();
// Feed arrays
for (int i = 1; i <= n; ++i) {
int from = i - 1;
int to = 2 * n - i - 1;
int v = n - i + 1;
for (int j = from; j <= to; ++j) {
result[from][j] = v;
result[to][j] = v;
result[j][from] = v;
result[j][to] = v;
}
}
return result;
}
....
int n = 3;
String report = String.Join(Environment.NewLine, Matrix(n)
.Select(line => String.Join(" ", line)));
Console.Write(report);
Output for n = 3 is
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3
And for n = 4:
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
Here's a version that doesn't use any intermediate storage:
static void printMatrix(int n)
{
int x = 2*n - 1;
for (int i = 0, p = n; i < x; ++i, p += (i > x/2) ? 1 : -1)
{
for (int j = 0, q = n; j < x; ++j, q += (j > x/2) ? 1 : -1)
Console.Write(Math.Max(p, q) + " ");
Console.WriteLine();
}
}
This works as follows:
The outer loop (i) and inner loop (j) both go from 0 .. 2*n-1.
However, the values that we want to print (p and q) start at n and decrease until halfway across/down the matrix, at which point they start increasing again.
We can determine whether to increment or decrement these values by checking the loop variable to see if it is halfway across/down the matrix yet. If it is, we decrement, otherwise we increment.
That's what this is doing: p += (i > x/2) ? 1 : -1.
If i > x/2 then the value 1 will be used for the increment, otherwise -1 will be used for the increment (i.e. it will be decremented).
(Similarly for q.)
The final piece of the puzzle is that the value we want to use is actually the maximum of p and q. If you inspect the matrix, you will see that if you consider each row value and each column value, the maximum of each is used for the corresponding cell.
Hence the use of Math.Max(p, q) in the output.
Here a simpler solution less complicated and fastest here so far:
private static void printMatrix(int n)
{
// length of the matrix in one dimension
int length = (2 * n) - 1;
// iterate through y axis of the matrix
for (int i = 0; i < length; i++)
{
int value = n;
// iterate through x axis of the matrix
for (int j = 0; j < length; j++)
{
Console.Write(value);
if (i > j && i + j < length - 1)
{
value--;
}
else if (i <= j && i + j >= length - 1)
{
value++;
}
}
Console.WriteLine();
}
}
Explanation for the if statements
First take a look on the matrix like it would be an array and look at the indexes and values and what changes when iterating through the array in the two for statements whereas the value of i is for the y axis, from up to down and the value of j is for the x axis, from left to right.
// +1 and -1 means the changes of the values
0,0 0,1 0,2 0,3 0,4 // values of i,j (first is i, second is j)
[3] [3] [3] [3] [3] // printed value
1,0 1,1 1,2 1,3 1,4
[3] -1 [2] [2] [2] +1 [3]
2,0 2,1 2,2 2,3 2,4
[3] -1 [2] -1 [1] +1 [2] +1 [3]
3,0 3,1 3,2 3,3 3,4
[3] -1 [2] [2] [2] +1 [3]
4,0 4,1 4,2 4,3 4,4
[3] [3] [3] [3] [3]
As you can see, the value changes only in specific circumstances.
And this happens -1 if i > j and if i + j < length - 1, otherwise after index 3,1 you will have wrong values, after that it shouldn't subtract the value any more.
This two if statements lead us to the first statement in the code:
if (i > j && i + j < length - 1)
{
value--;
}
Now it also happens +1 if i + j >= length - 1 but that not other values like 3,1 also add +1 to the value it only increments it, if i <= j, which leads us to the second if-statement in the code:
else if (i <= j && i + j >= length - 1)
{
value++;
}
If none of these statements are true, the value simply stays the same as it should.
How can I rotate a 2D rectangular array of integers that has odd number of rows by 45 degrees?
So something like
int[] myArray = new int[,]
{
{1, 0 ,1},
{0, 1 ,0},
{0, 0 ,0},
}
into
int[] rotatedArray = new int[,]
{
{0, 1 ,0},
{0, 1 ,1},
{0, 0 ,0},
}
for any dimension (3x3, 5x5, 7x7, etc.).
5x5
0 0 0 0 0
2 0 0 0 0
1 1 1 1 1
0 0 0 0 0
0 0 0 0 0
into
1 2 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
5x5
0 0 0 3 0
0 0 0 3 0
0 0 0 3 0
0 0 0 3 0
0 0 0 3 0
into
0 0 0 0 0
0 0 0 0 3
0 0 0 3 0
0 0 3 3 0
0 3 0 0 0
This is a code written by me and a friend that solves this:
public static class ArrayExtensions
{
public static Point RoundIndexToPoint(int index, int radius)
{
if (radius == 0)
return new Point(0, 0);
Point result = new Point(-radius, -radius);
while (index < 0) index += radius * 8;
index = index % (radius * 8);
int edgeLen = radius * 2;
if (index < edgeLen)
{
result.X += index;
}
else if ((index -= edgeLen) < edgeLen)
{
result.X = radius;
result.Y += index;
}
else if ((index -= edgeLen) < edgeLen)
{
result.X = radius - index;
result.Y = radius;
}
else if ((index -= edgeLen) < edgeLen)
{
result.Y = radius - index;
}
return result;
}
public static T[,] Rotate45<T>(this T[,] array)
{
int dim = Math.Max(array.GetLength(0), array.GetLength(0));
T[,] result = new T[dim, dim];
Point center = new Point((result.GetLength(0) - 1) / 2, (result.GetLength(1) - 1) / 2);
Point center2 = new Point((array.GetLength(0) - 1) / 2, (array.GetLength(1) - 1) / 2);
for (int r = 0; r <= (dim - 1) / 2; r++)
{
for (int i = 0; i <= r * 8; i++)
{
Point source = RoundIndexToPoint(i, r);
Point target = RoundIndexToPoint(i + r, r);
if (!(center2.X + source.X < 0 || center2.Y + source.Y < 0 || center2.X + source.X >= array.GetLength(0) || center2.Y + source.Y >= array.GetLength(1)))
result[center.X + target.X, center.Y + target.Y] = array[center2.X + source.X, center2.Y + source.Y];
}
}
return result;
}
}
You can try this library:
Math.NET Project for matrices operations... http://numerics.mathdotnet.com/
This code appears to be useful too:
http://www.drunkenhyena.com/cgi-bin/view_net_article.pl?chapter=2;article=28#Rotation
Don't forget the DirectX managed and unmanaged namespaces and classes. Lots
and lots of good stuff there to check.
For example:
Matrix..::.Rotate Method (Single, MatrixOrder)
I think we have these rules:
Imagine the matrix as a set of "frames or boxes without centers" within each other like "Russian dolls".
Elements at the center of a side (top/left/right/bottom) move towards the nearest corner clockwise.
Corners move towards the next center clockwise.
Elements that are not corners nor centers move to the next spot (clockwise) that is the same distance from a corner as they currently are.
I've started writing some code but I don't think it's trivial and I haven't had time to test.
You can see my solution for the matrix rotation in codesignal