function pad(s, n) {
while(s.length < n)
s = " " + s;
return s;
}
// Create a matrix of [WxH] size.
function Matrix(w, h, data) {
if (Array.isArray(data)) {
if (data.length !== w * h)
throw new Error("Data.length has to match the size " + (w * h) + ".");
}
else {
var n = typeof data === "number" ? data : 0.0;
data = [];
for (var i = 0; i < w*h; i++) data.push(n);
}
this.w = w;
this.h = h;
this.data = data;
}
// Get value at [x, y]
Matrix.prototype.get = function(x, y) {
if (x < 0 || x >= this.w || y < 0 || y >= this.h)
throw new Error("Index [" + x + ", " + y + "] out of bounds");
return this.data[y * this.w + x];
}
// Set value at [x, y] and return the previous value.
Matrix.prototype.set = function(x, y, value) {
if (x < 0 || x >= this.w || y < 0 || y >= this.h)
throw new Error("Index [" + x + ", " + y + "] out of bounds");
var i = y * this.w + x;
var prev = this.data[i];
this.data[i] = value;
return prev;
}
// Log the matrix data.
Matrix.prototype.dump = function() {
var s = "["
var i = 0;
for (var y = 0; y < this.h; y++) {
for (var x = 0; x < this.w; x++, i++) {
s += pad("" + this.data[i], 2);
if (x !== this.w - 1)
s += ","
}
if (y !== this.h - 1)
s += ",\n ";
}
s += "]";
console.log(s);
}
// Shift, `dir` can be "cw" or "ccw".
Matrix.prototype.shift = function(dir) {
var instructions = {
cw : [1, 0, 0, 1,-1, 0, 0,-1],
ccw: [0, 1, 1, 0, 0,-1,-1, 0]
};
var inst = instructions[dir];
// A window, shrink by one from each side after the nested loop is done.
var minX = 0;
var minY = 0;
var maxX = this.w - 1;
var maxY = this.h - 1;
while (minX < maxX && minY < maxY) {
// Always start at the top-left corner and iterate.
var x0 = minX;
var y0 = minY;
var v0 = this.get(x0, y0);
var n = 0;
for (;;) {
var x1 = x0 + inst[n + 0];
var y1 = y0 + inst[n + 1];
if (x1 < minX || x1 > maxX || y1 < minY || y1 > maxY) {
n += 2;
x1 = x0 + inst[n + 0];
y1 = y0 + inst[n + 1];
}
v0 = this.set(x1, y1, v0);
// Last one.
if (x1 === minX && y1 === minY)
break;
x0 = x1;
y0 = y1;
}
minX++;
minY++;
maxX--;
maxY--;
}
}
var a = new Matrix(3, 3, [
1,2,3,
4,5,6,
7,8,9,
]);
a.dump();
a.shift("cw");
a.dump();
var b = new Matrix(4, 4, [
1 ,2 ,3 ,4 ,
5 ,6 ,7 ,8 ,
9 ,10,11,12,
13,14,15,16
]);
b.dump();
b.shift("ccw");
b.dump();