Back to all solutions

#1914 - Cyclically Rotating a Grid

Problem Description

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.

Solution

/**
 * @param {number[][]} grid
 * @param {number} k
 * @return {number[][]}
 */
var rotateGrid = function(grid, k) {
  const rows = grid.length;
  const cols = grid[0].length;
  const result = grid.map(row => [...row]);

  for (let layer = 0; layer < Math.min(rows, cols) / 2; layer++) {
    rotateLayer(layer, layer, rows - 1 - layer, cols - 1 - layer, k);
  }

  return result;

  function rotateLayer(top, left, bottom, right, rotations) {
    if (top >= bottom || left >= right) return;

    const perimeter = 2 * (bottom - top + right - left);
    const effectiveRotations = rotations % perimeter;
    if (effectiveRotations === 0) return;

    const elements = [];
    for (let i = top; i <= bottom; i++) elements.push(grid[i][left]);
    for (let j = left + 1; j <= right; j++) elements.push(grid[bottom][j]);
    for (let i = bottom - 1; i >= top; i--) elements.push(grid[i][right]);
    for (let j = right - 1; j > left; j--) elements.push(grid[top][j]);

    const offset = (perimeter - effectiveRotations) % perimeter;
    let index = offset;

    for (let i = top; i <= bottom; i++) {
      result[i][left] = elements[index % perimeter];
      index++;
    }
    for (let j = left + 1; j <= right; j++) {
      result[bottom][j] = elements[index % perimeter];
      index++;
    }
    for (let i = bottom - 1; i >= top; i--) {
      result[i][right] = elements[index % perimeter];
      index++;
    }
    for (let j = right - 1; j > left; j--) {
      result[top][j] = elements[index % perimeter];
      index++;
    }
  }
};