johnoscott
3/31/2018 - 1:40 AM

## [Matrix Rotation] Javascript implementation of 90degree clockwise rotation of nxn matrix

[Matrix Rotation] Javascript implementation of 90degree clockwise rotation of nxn matrix

``````const m1 = [
[5]
];

const m2 = [
[2,3],
[1,4]
];

const m3 = [
[3,4,5],
[2,9,6],
[1,8,7]
];

const m4 = [
[4, 5,  6,  7],
[3, 14, 15, 8],
[2, 13, 16, 9],
[1, 12, 11, 10]
];

const m5 = [
[5,6 ,7 ,8 , 9],
[4,19,20,21,10],
[3,18,25,22,11],
[2,17,24,23,12],
[1,16,15,14,13],
];

function test(m) {
const format = m => m.map(row => JSON.stringify(row))
.join('\n')
console.log('\n =======================');
console.log('Input: \n');
console.log(format(m));
console.log('\nClockwise Rotation: \n');
rotate(m);
console.log(format(m));
}

test(m1);
test(m2);
test(m3);
test(m4);
test(m5);
``````
``````/**
* @param {number[][]} matrix
* @return {void} Do not return anything, modify matrix in-place instead.
*/
var rotate = function(m) {

const debug = false;

// strategy :
// starting with the outer 'ring' of edges, rotate each cell in place
// and work inward until we reach the middle
// note: matrix is square (nxn) so an in-place rotation will work

// outer loop "i" is a starting offset of the top-left cell
// e.g. (0,0), (1,1), (2,2) ect
// limit is the center of the matrix
// so if dimension of the matrix is d, then loop limit is (i < (d-1) / 2);

const d = m[0].length; // dimension size of the matrix
const e = d-1; // index bounds of matrix
const row=0,col=1; // for clarity
debug && console.log(`dimension is \${d}x\${d}`)

// move cell a -> b
// a and b are cell references [ row,col ]
// which need to be accessed in reverse : row y first, then column x
const moveCell = (a,b,msg) => {
debug && console.log(`   move [\${a[row]},\${a[col]}]=\${m[a[row]][a[col]]} -> [\${b[row]},\${b[col]}] : \${msg} `)
m[b[row]][b[col]] = m[a[row]][a[col]];
}

const setCell = (a,val,msg) => {
debug && console.log(`   set [\${a[row]},\${a[col]}] -> \${val} : \${msg} `)
m[a[row]][a[col]] = val;
}

const getCell = (a,msg) => {
const val = m[a[row]][a[col]];
debug && console.log(`   get [\${a[row]},\${a[col]}] = \${val} : \${msg} `)
return val;
}

for (let i=0; i < (d-1) / 2; i++) {

const w = d - (i*2); // width of this ring

// const w = d - (i*2); // width of this ring

const colOffset = i;

debug && console.log(`\nrotate ring i=\${i} width=\${w} offset=\${colOffset}`);

// swap each cell in clockwise direction
// store the top edge value, then move left->top, bottom->left, right->bottom, then move saved top -> right
// bounds of this loop is the width of this ring -1 because the last cell of each edge is the first of the next edge
for (let j=0; j< w-1; j++) {

debug && console.log(`\n ~~ \${j} until \${w-1}`);

const top = [i, i+j];
const right = [i+j, e-i];
const bottom = [e-i,e-i-j];
const left = [e-i-j,i];

// temp store top
const tempTopVal = getCell(top, 'top');

// left -> top
moveCell(left, top , 'left -> top');

// bottom -> left
moveCell(bottom, left, 'bottom -> left');

// right -> bottom
moveCell(right, bottom, 'right -> bottom');

// saved top -> right
setCell(right, tempTopVal, 'top -> right');

}

}

// return m
};``````
``````<!doctype html>
<html lang="en">