Skip to content

Instantly share code, notes, and snippets.

@johnoscott
Last active March 31, 2018 01:47
Show Gist options
  • Save johnoscott/f7bd77bc020fdefe31fb025558ce9ded to your computer and use it in GitHub Desktop.
Save johnoscott/f7bd77bc020fdefe31fb025558ce9ded to your computer and use it in GitHub Desktop.
[Matrix Rotation] Javascript implementation of 90degree clockwise rotation of nxn matrix
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>GistRun</title>
<!--<link rel="stylesheet" href="styles.css">-->
</head>
<body>
<h1>Hello world!</h1>
<script src="rotate-matrix.js"></script>
<script src="run.js"></script>
</body>
</html>
/**
* @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
};
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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment