# Ring wise Matrix Rotation

## Introduction

Matrices have always been of interest in the field of encryption, specifically matrix rotations which leads to a symmetric as well as asymmetric cryptography. To learn more about regular matrix rotation please check my recent posts on the subject. This however is a fancy Ring wise Matrix Rotation and is no where related to the regular rotation of matrices.

## Problem Statement

You are given a M*N grid with the restriction that the minimum of M and N is an even number. Rotate each of the rings by a distance K. We can choose the direction of rotation to be either clockwise or anti-clockwise. The application logic won't change much. Here is a diagrammatic representation of what we are trying to achieve. Why do we talk about the minimum of M and N to be even? If the minimum is an odd number, we will land up in the below situation, at the end we will have a line which needs to be rotated. Defining the rotation of a line ? Seems unfair :) Or if you think you know what you mean by rotating a line, you can distinctly handle that last one iteration.

## The Approach behind this solution

The solution seems very simple, here I try to define it in words:
1. Extract out the layer starting at coordinates (i,i).
2. Convert it into one dimensional string. Let say the length of the string is L.
3. Rotate the string by K to the left or L-K to the right.
4. Put it back in the grid.
5. Repeat till the complete grid is rotated.
Seems fun, here is how to implement each of the step in code.

## Source Code

Extracting a Layer (i,i) and converting to String
```static String walk(long[][] c, int idx) {
int i = idx, j = idx;
StringBuilder sb = new StringBuilder();
while (j < c[i].length - idx) {
sb.append(c[i][j] + " ");
j++;
}
j--;
i++;
while (i < c.length - idx - 1) {
sb.append(c[i][j] + " ");
i++;
}
while (j >= idx) {
sb.append(c[i][j] + " ");
j--;
}
j++;
i--;
while (i > idx) {
sb.append(c[i][j] + " ");
i--;
}
return sb.toString();
}
```
Rotating the String by specified number and putting it back in the grid Few things to take care while rotating. If we need to rotate by 0 spaces or L spaces, we better do nothing.
```static void rotate(long[][] c, int idx, int r, long[] C) {
// do not rotate if r is zero or equal to the length of the string.
if (r == 0 || r % C.length == 0)
return;

r = r % C.length;
long[] d = new long[C.length];
for (int i = 0; i < C.length; i++) {
d[i] = C[(i + r) % C.length];
}

// put it back to the grid
int i = idx, j = idx;
int count = 0;
while (j < c[i].length - idx) {
c[i][j] = d[count++];
j++;
}
j--;
i++;
while (i < c.length - idx - 1) {
c[i][j] = d[count++];
i++;
}
while (j >= idx) {
c[i][j] = d[count++];
j--;
}
j++;
i--;
while (i > idx) {
c[i][j] = d[count++];
i--;
}
}```

## The Catch

When we rotate one layer, every subsequent inner layer will have lesser rows and columns to rotate. The rows and columns reduce by 2. This means the caller loop must run for half the Min(M,N) . Once we reach this index, by the virtue of symmetry we would have considered all the rows and columns and rotated them as well. Here is the caller code:
```public static void main(String[] args) {

int M = 4, N = 7, rotate = 20;
long c[][] = new long[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16},{17,18,19,20},{21,22,23,24},{25,26,27,28}};
int min = Math.min(M, N);
int C = min/2;

for (int i = 0; i < C; i++) {
String walk = walk(c, i);
if (walk.length() > 0) {
String[] split = walk.split(" ");
long[] L = new long[split.length];
for (int k = 0; k < split.length; k++) {
L[k] = Long.parseLong(split[k]);
}

rotate(c, i, rotate, L);
}
}
}```
You may include another piece of code to print the 2 D grid. Please find the complete code @github repo