You are given an m x n integer matrix grid​​​, where m and n are both even integers, and an integer k.

The matrix is composed of several layers, which is shown in the below image, where each color is its own layer:



A cyclic rotation of the matrix is done by cyclically rotating each layer in the matrix. To cyclically rotate a layer once, each element in the layer will take the place of the adjacent element in the counter-clockwise direction. An example rotation is shown below:

Return the matrix after applying k cyclic rotations to it.

&nbsp;
Example 1:

Input: grid = [[40,10],[30,20]], k = 1
Output: [[10,20],[40,30]]
Explanation: The figures above represent the grid at every state.


Example 2:
  

Input: grid = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]], k = 2
Output: [[3,4,8,12],[2,11,10,16],[1,7,6,15],[5,9,13,14]]
Explanation: The figures above represent the grid at every state.


&nbsp;
Constraints:


	m == grid.length
	n == grid[i].length
	2 &lt;= m, n &lt;= 50
	Both m and n are even integers.
	1 &lt;= grid[i][j] &lt;= 5000
	1 &lt;= k &lt;= 109

class Solution:
    def rotateGrid(self, grid: List[List[int]], k: int) -> List[List[int]]:
        n = len(grid)
        m = len(grid[0])
        
        i, j = 0, 0
        bottom, right = n-1, m-1 
        while i < n//2 and j < m//2:
            temp = []
            for x in range(j, right):
                temp.append(grid[i][x])
            for x in range(i, bottom):
                temp.append(grid[x][right])
            for x in range(right, j, -1):
                temp.append(grid[bottom][x])
            for x in range(bottom, i, -1):
                temp.append(grid[x][j])
                
            
            indx = 0
            for x in range(j, right):
                grid[i][x] = temp[(k + indx)%len(temp)]
                indx += 1
            for x in range(i, bottom):
                grid[x][right] = temp[(k + indx)%len(temp)]
                indx += 1
            for x in range(right, j, -1):
                grid[bottom][x] = temp[(k + indx)%len(temp)]
                indx += 1
            for x in range(bottom, i, -1):
                grid[x][j] = temp[(k + indx)%len(temp)]
                indx += 1
                
            i += 1
            j += 1
            bottom -= 1
            right -= 1
        return grid
class Solution {
    public int[][] rotateGrid(int[][] grid, int k) {
        int m = grid.length, n = grid[0].length, noOfLayers = Math.min(m/2, n/2); 
        // Peeling each layer one by one
        for(int layerNo = 0; layerNo < noOfLayers; layerNo++){
            // Please suggest if you have better way to find perimeter of matrix on a given layer!
            int perimeter = (m-(2*layerNo)) + (n-(2*layerNo)-1) + (m-(2*layerNo)-1) + (n-(2*layerNo)-2); 
            int[] layer = new int[perimeter]; // this out be use to store that particular layer
            readLayer(grid, layer, layerNo, m, n); // this will read the layer
            writeLayer(grid, layer, layerNo, m, n, k); // this will rotate it by k and write back the layer  
        }
        return grid;
    }
    
    public void readLayer(int[][] grid, int[] layer, int layerNo, int m, int n){
        int count = 0, r = layerNo, c = layerNo;
        m--; n--;
        // read left a -> c
        for(int i = layerNo; i < n - layerNo; i++) layer[count++] = grid[layerNo][i];
        // read down c -> i
        for(int i = layerNo; i < m - layerNo; i++) layer[count++] = grid[i][n-layerNo];
        // read right i -> g
        for(int i = n-layerNo; i > layerNo; i--) layer[count++] = grid[m-layerNo][i];
        // read up g -> a
        for(int i = m-layerNo; i > layerNo; i--) layer[count++] = grid[i][layerNo];
    }
    
    public void writeLayer(int[][] grid, int[] layer, int layerNo, int m, int n, int k){
         m--; n--;
        int len = layer.length, count = k; 
        // write left a -> c
        for(int i = layerNo; i < n - layerNo; i++){
            count %= len; // reason if goes out of length start back from 0
            grid[layerNo][i] = layer[count++];
        }
        // write down c -> i
        for(int i = layerNo; i < m - layerNo; i++){
            count %= len;
            grid[i][n-layerNo] = layer[count++];
        } 
        // write right i -> g
        for(int i = n-layerNo; i > layerNo; i--){
            count %= len;
            grid[m-layerNo][i] = layer[count++];
        }
        // write up g -> a
        for(int i = m-layerNo; i > layerNo; i--){
            count %= len;
            grid[i][layerNo] = layer[count++];
        } 
    }
    
   
}
const vector<pair<int, int>> directions{{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

class Solution
{
protected:
    int n, m;

    int whichLayer(int x, int y) {
        if (x < 0 || y < 0 || x >= n || y >= m) return -1;
        int i = min(x, n - x - 1);
        int j = min(y, m - y - 1);
        return min(i, j);
    }

    void nextPos(int x, int y, int dir, int& nx, int& ny) {
        nx = x + directions[dir].first;
        ny = y + directions[dir].second;
    }

    // Go to next position in the current layer (in clockwise order)
    void advancePosition(int& x, int& y, int& d) {
        int nx, ny;
        nextPos(x, y, d, nx, ny);
        if (whichLayer(nx, ny) != whichLayer(x, y)) {
            // Change direction
            d = (d + 1) % 4;
            nextPos(x, y, d, nx, ny);
        }
        x = nx; y = ny;
    }

public:
    vector<vector<int>> rotateGrid(vector<vector<int>>& grid, int k)
    {
        // Check validity of the arguments
        if (grid.empty()) throw invalid_argument("empty grid");
        m = grid.size();
        n = grid[0].size();
        if (n == 0) throw invalid_argument("empty grid");
        if (k < 0) throw invalid_argument("negative k not accepted");

        // Trivial case
        if (k == 0) return grid;

        const int L = min(n, m) / 2;
        for (int l = 0; l < L; l++) {
            vector<int> v;

            // Flatten a layer from grid into a vector
            int j = l, i = l; // start position
            int d = 0; // direction
            do {
                v.push_back(grid[j][i]);
                advancePosition(i, j, d);
            } while (!(i == l && j == l)); // until the start position is reached

            // Unflatten rotated vector back into the grid
            j = l; i = l; // start position
            d = 0; // direction
            int off = k % v.size();
            do {
                grid[j][i] = v[off];
                off = (off + 1) % v.size();
                advancePosition(i, j, d);
            } while (!(i == l && j == l)); // until the start position is reached
        }

        return grid;
    }
};
var rotateGrid = function(grid, k) {
    const m = grid.length;
    const n = grid[0].length;
    
    let startRow = 0;
    let endRow = m - 1;
    
    let startCol = 0;
    let endCol = n - 1;
    
    while (startRow <= endRow && startCol <= endCol) {
        let currRowStart = startRow;
        let currRowEnd = endRow;

        let currColStart = startCol;
        let currColEnd = endCol;

        const vals = [];

        // Top
        for (let col = currColStart; col <= currColEnd; ++col) {
            const val = grid[currRowStart][col];
            vals.push(val);
        }
        ++currRowStart;

        // Right
        for (let row = currRowStart; row <= currRowEnd; ++row) {
            const val = grid[row][currColEnd];
            vals.push(val);
        }
        --currColEnd;

        // Bottom
        for (let col = currColEnd; col >= currColStart; --col) {
            const val = grid[currRowEnd][col];
            vals.push(val);
        }
        --currRowEnd;

        // Left
        for (let row = currRowEnd; row >= currRowStart; --row) {
            const val = grid[row][currColStart];
            vals.push(val);
        }
        ++currColStart;

        const size = vals.length;
        const remK = k % size;

        const movedVals = [];

        for (let i = 0; i < size; ++i) {
            const movedIdx = (i + remK) % size;
            movedVals[i] = vals[movedIdx];
        }

        let i = 0;

        currRowStart = startRow;
        currRowEnd = endRow;

        currColStart = startCol;
        currColEnd = endCol;

        // Top
        for (let col = currColStart; col <= currColEnd; ++col) {
            grid[currRowStart][col] = movedVals[i++];
        }
        ++currRowStart;

        // Right
        for (let row = currRowStart; row <= currRowEnd; ++row) {
            grid[row][currColEnd] = movedVals[i++];
        }
        --currColEnd;

        // Bottom
        for (let col = currColEnd; col >= currColStart; --col) {
            grid[currRowEnd][col] = movedVals[i++];
        }
        --currRowEnd;

        // Left
        for (let row = currRowEnd; row >= currRowStart; --row) {
            grid[row][currColStart] = movedVals[i++];
        }
        ++currColStart;

        // update the boundaries for the next layer
        startRow = currRowStart;
        endRow = currRowEnd;

        startCol = currColStart;
        endCol = currColEnd;
    }
    
   return grid;
};
Cyclically Rotating a Grid