Add some BoardObj routines.
authorOleksandr Gavenko <gavenkoa@gmail.com>
Mon, 22 Sep 2014 21:29:21 +0300
changeset 93 c2bf15c3b80b
parent 92 1959a0505639
child 111 7b9d1bb9c471
Add some BoardObj routines.
2048.html
board.js
perf.html
--- a/2048.html	Mon Sep 22 20:57:50 2014 +0300
+++ b/2048.html	Mon Sep 22 21:29:21 2014 +0300
@@ -699,6 +699,7 @@
     ui.report = {};
 
     ui.report.stat = function() {
+      /* console.profile(); */
       var stats = [];
       var cnt = parseInt(document.getElementById('stat-count-limit').value);
       if (isNaN(cnt) || !isFinite(cnt) || cnt < 1)
@@ -824,6 +825,7 @@
       var tableDom = ui.dom.table(tbl, tblCols, { tableClass: 'report-by-maxval' });
       reportDom.appendChild(tableDom);
       reportsDom.insertBefore(reportDom, reportsDom.firstChild);
+      /* console.profileEnd(); */
     }
 
     var statisticBtn = document.getElementById('statistic');
@@ -834,6 +836,7 @@
     // Initialise game.
 
     ui.brdEngine = BoardArr2d; // TODO make user selectable
+    // ui.brdEngine = BoardObj; // TODO make user selectable
 
     if (localStorage.val2048) {
       try {
--- a/board.js	Mon Sep 22 20:57:50 2014 +0300
+++ b/board.js	Mon Sep 22 21:29:21 2014 +0300
@@ -764,3 +764,196 @@
             brd[i][j] = this.brd[4*i + j];
     return brd;
 }
+BoardObj.prototype.equals = function(brd) {
+    var self = this.brd;
+    return self.aa == brd.aa && self.ad == brd.ad && self.da == brd.da && self.dd == brd.dd
+        && self.ab == brd.ab && self.ac == brd.ac
+        && self.ba == brd.ba && self.ca == brd.ca
+        && self.bd == brd.bd && self.cd == brd.cd
+        && self.db == brd.db && self.dc == brd.dc
+        && self.bb == brd.bb && self.bc == brd.bc && self.cb == brd.cb && self.cc == brd.cc;
+};
+BoardObj.prototype.copy = function(brd) {
+    var self = this.brd;
+    if ( ! brd) {
+        var newBrd = new Object(BoardObj.prototype);
+        newBrd.brd = { aa: self.aa, ab: self.ab, ac: self.ac, ad: self.ad,
+                       ba: self.ba, bb: self.bb, bc: self.bc, bd: self.bd,
+                       ca: self.ca, cb: self.cb, cc: self.cc, cd: self.cd,
+                       da: self.da, db: self.db, dc: self.dc, dd: self.dd };
+        return newBrd;
+    }
+    brd.aa = self.aa; brd.ab = self.ab; brd.ac = self.ac; brd.ad = self.ad;
+    brd.ba = self.ba; brd.bb = self.bb; brd.bc = self.bc; brd.bd = self.bd;
+    brd.ca = self.ca; brd.cb = self.cb; brd.cc = self.cc; brd.cd = self.cd;
+    brd.da = self.da; brd.db = self.db; brd.dc = self.dc; brd.dd = self.dd;
+    return brd;
+}
+BoardObj.prototype.free = function() {
+    var cnt = 0;
+    var brd = this.brd;
+    if (brd.aa === 0) cnt++; if (brd.ab === 0) cnt++; if (brd.ac === 0) cnt++; if (brd.ad === 0) cnt++;
+    if (brd.ba === 0) cnt++; if (brd.bb === 0) cnt++; if (brd.bc === 0) cnt++; if (brd.bd === 0) cnt++;
+    if (brd.ca === 0) cnt++; if (brd.cb === 0) cnt++; if (brd.cc === 0) cnt++; if (brd.cd === 0) cnt++;
+    if (brd.da === 0) cnt++; if (brd.db === 0) cnt++; if (brd.dc === 0) cnt++; if (brd.dd === 0) cnt++;
+    return cnt;
+}
+BoardObj.prototype.score = function() {
+    var score = 0;
+    var brd = this.brd;
+    var v = brd.aa;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.ab;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.ac;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.ad;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.ba;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.bb;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.bc;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.bd;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.ca;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.cb;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.cc;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.cd;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.da;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.db;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.dc;
+    if (v > 1) score += (v-1)*(1 << v);
+    var v = brd.dd;
+    if (v > 1) score += (v-1)*(1 << v);
+    return score;
+}
+BoardObj.prototype.max = function() {
+    var brd = this.brd;
+    var max = brd.aa;
+    max = Math.max(max, brd.ab);
+    max = Math.max(max, brd.ac);
+    max = Math.max(max, brd.ad);
+    max = Math.max(max, brd.ba);
+    max = Math.max(max, brd.bb);
+    max = Math.max(max, brd.bc);
+    max = Math.max(max, brd.bd);
+    max = Math.max(max, brd.ca);
+    max = Math.max(max, brd.cb);
+    max = Math.max(max, brd.cc);
+    max = Math.max(max, brd.cd);
+    max = Math.max(max, brd.da);
+    max = Math.max(max, brd.db);
+    max = Math.max(max, brd.dc);
+    max = Math.max(max, brd.dd);
+    return max;
+}
+BoardObj.prototype.find = function(val) {
+    var xy = [];
+    var brd = this.brd;
+    if (brd.aa === val) xy.push([0,0]); if (brd.ab === val) xy.push([0,1]); if (brd.ac === val) xy.push([0,2]); if (brd.ad === val) xy.push([0,3]);
+    if (brd.ba === val) xy.push([1,0]); if (brd.bb === val) xy.push([1,1]); if (brd.bc === val) xy.push([1,2]); if (brd.bd === val) xy.push([1,3]);
+    if (brd.ca === val) xy.push([2,0]); if (brd.cb === val) xy.push([2,1]); if (brd.cc === val) xy.push([2,2]); if (brd.cd === val) xy.push([2,3]);
+    if (brd.da === val) xy.push([3,0]); if (brd.db === val) xy.push([3,1]); if (brd.dc === val) xy.push([3,2]); if (brd.dd === val) xy.push([3,3]);
+    return xy;
+}
+BoardObj.prototype.atEdge = function(val) {
+    var brd = this.brd;
+    return (brd.aa === val) || (brd.ab === val) || (brd.ac === val) || (brd.ad === val)
+        || (brd.ba === val) || (brd.bd === val)
+        || (brd.ca === val) || (brd.cd === val)
+        || (brd.da === val) || (brd.db === val) || (brd.dc === val) || (brd.dd === val);
+}
+BoardObj.prototype.atCorner = function(val) {
+    var brd = this.brd;
+    return (brd.aa === val) || (brd.ad === val) || (brd.da === val) || (brd.dd === val);
+}
+
+BoardObj.prototype.canRight = function() {
+    var brd = this.brd;
+    var f0 = brd.aa, f1 = brd.ab, f2 = brd.ac, f3 = brd.ad;
+    if (f2 > 0 && (f2 === f3 || f3 === 0)) return true;
+    if (f1 > 0 && (f1 === f2 || f2 === 0)) return true;
+    if (f0 > 0 && (f0 === f1 || f1 === 0)) return true;
+    var f0 = brd.ba, f1 = brd.bb, f2 = brd.bc, f3 = brd.bd;
+    if (f2 > 0 && (f2 === f3 || f3 === 0)) return true;
+    if (f1 > 0 && (f1 === f2 || f2 === 0)) return true;
+    if (f0 > 0 && (f0 === f1 || f1 === 0)) return true;
+    var f0 = brd.ca, f1 = brd.cb, f2 = brd.cc, f3 = brd.cd;
+    if (f2 > 0 && (f2 === f3 || f3 === 0)) return true;
+    if (f1 > 0 && (f1 === f2 || f2 === 0)) return true;
+    if (f0 > 0 && (f0 === f1 || f1 === 0)) return true;
+    var f0 = brd.da, f1 = brd.db, f2 = brd.dc, f3 = brd.dd;
+    if (f2 > 0 && (f2 === f3 || f3 === 0)) return true;
+    if (f1 > 0 && (f1 === f2 || f2 === 0)) return true;
+    if (f0 > 0 && (f0 === f1 || f1 === 0)) return true;
+    return false;
+}
+BoardObj.prototype.canLeft = function() {
+    var brd = this.brd;
+    var f0 = brd.aa, f1 = brd.ab, f2 = brd.ac, f3 = brd.ad;
+    if (f1 > 0 && (f1 === f0 || f0 === 0)) return true;
+    if (f2 > 0 && (f2 === f1 || f1 === 0)) return true;
+    if (f3 > 0 && (f3 === f2 || f2 === 0)) return true;
+    var f0 = brd.ba, f1 = brd.bb, f2 = brd.bc, f3 = brd.bd;
+    if (f1 > 0 && (f1 === f0 || f0 === 0)) return true;
+    if (f2 > 0 && (f2 === f1 || f1 === 0)) return true;
+    if (f3 > 0 && (f3 === f2 || f2 === 0)) return true;
+    var f0 = brd.ca, f1 = brd.cb, f2 = brd.cc, f3 = brd.cd;
+    if (f1 > 0 && (f1 === f0 || f0 === 0)) return true;
+    if (f2 > 0 && (f2 === f1 || f1 === 0)) return true;
+    if (f3 > 0 && (f3 === f2 || f2 === 0)) return true;
+    var f0 = brd.da, f1 = brd.db, f2 = brd.dc, f3 = brd.dd;
+    if (f1 > 0 && (f1 === f0 || f0 === 0)) return true;
+    if (f2 > 0 && (f2 === f1 || f1 === 0)) return true;
+    if (f3 > 0 && (f3 === f2 || f2 === 0)) return true;
+    return false;
+}
+BoardObj.prototype.canUp = function() {
+    var brd = this.brd;
+    var f0 = brd.aa, f1 = brd.ba, f2 = brd.ca, f3 = brd.da;
+    if (f1 > 0 && (f1 === f0 || f0 === 0)) return true;
+    if (f2 > 0 && (f2 === f1 || f1 === 0)) return true;
+    if (f3 > 0 && (f3 === f2 || f2 === 0)) return true;
+    var f0 = brd.ab, f1 = brd.bb, f2 = brd.cb, f3 = brd.db;
+    if (f1 > 0 && (f1 === f0 || f0 === 0)) return true;
+    if (f2 > 0 && (f2 === f1 || f1 === 0)) return true;
+    if (f3 > 0 && (f3 === f2 || f2 === 0)) return true;
+    var f0 = brd.ac, f1 = brd.bc, f2 = brd.cc, f3 = brd.dc;
+    if (f1 > 0 && (f1 === f0 || f0 === 0)) return true;
+    if (f2 > 0 && (f2 === f1 || f1 === 0)) return true;
+    if (f3 > 0 && (f3 === f2 || f2 === 0)) return true;
+    var f0 = brd.ad, f1 = brd.bd, f2 = brd.cd, f3 = brd.dd;
+    if (f1 > 0 && (f1 === f0 || f0 === 0)) return true;
+    if (f2 > 0 && (f2 === f1 || f1 === 0)) return true;
+    if (f3 > 0 && (f3 === f2 || f2 === 0)) return true;
+    return false;
+}
+BoardObj.prototype.canDown = function() {
+    var brd = this.brd;
+    var f0 = brd.aa, f1 = brd.ba, f2 = brd.ca, f3 = brd.da;
+    if (f2 > 0 && (f2 === f3 || f3 === 0)) return true;
+    if (f1 > 0 && (f1 === f2 || f2 === 0)) return true;
+    if (f0 > 0 && (f0 === f1 || f1 === 0)) return true;
+    var f0 = brd.ab, f1 = brd.bb, f2 = brd.cb, f3 = brd.db;
+    if (f2 > 0 && (f2 === f3 || f3 === 0)) return true;
+    if (f1 > 0 && (f1 === f2 || f2 === 0)) return true;
+    if (f0 > 0 && (f0 === f1 || f1 === 0)) return true;
+    var f0 = brd.ac, f1 = brd.bc, f2 = brd.cc, f3 = brd.dc;
+    if (f2 > 0 && (f2 === f3 || f3 === 0)) return true;
+    if (f1 > 0 && (f1 === f2 || f2 === 0)) return true;
+    if (f0 > 0 && (f0 === f1 || f1 === 0)) return true;
+    var f0 = brd.ad, f1 = brd.bd, f2 = brd.cd, f3 = brd.dd;
+    if (f2 > 0 && (f2 === f3 || f3 === 0)) return true;
+    if (f1 > 0 && (f1 === f2 || f2 === 0)) return true;
+    if (f0 > 0 && (f0 === f1 || f1 === 0)) return true;
+    return false;
+}
+
--- a/perf.html	Mon Sep 22 20:57:50 2014 +0300
+++ b/perf.html	Mon Sep 22 21:29:21 2014 +0300
@@ -83,81 +83,46 @@
     /* var N = 1000*1000; */
     var N = 1000*1000;
 
-    function arrNew() {
-      return [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
-    }
-    function arrGet(brd, i, j) {
-      return brd[i*4+j];
-    }
-    function arrSet(brd, i, j, val) {
-      brd[i*4+j] = val;
-    }
     function arrPrint(brd) {
       for (var i = 0; i < 4; i++) {
         for (var j = 0; j < 4; j++) {
-          ui.set(i, j, brd[i*4+j]);
+          ui.set(i, j, brd[i][j]);
         }
       }
     }
-    function arrRotLeft(from, to) {
-      for (var i = 0; i < 4; i++) {
-        for (var j = 0; j < 3; j++) {
-          to[i*4+j+1] = from[i*4+j];
-        }
-        to[i*4] = from[i*4+3];
-      }
-    }
-    function arrRotLeft_2(from, to) {
-      to[1] = from[0]; to[2] = from[1]; to[3] = from[2]; to[0] = from[3];
-      to[4+1] = from[4+0]; to[4+2] = from[4+1]; to[4+3] = from[4+2]; to[4+0] = from[4+3];
-      to[8+1] = from[8+0]; to[8+2] = from[8+1]; to[8+3] = from[8+2]; to[8+0] = from[8+3];
-      to[12+1] = from[12+0]; to[12+2] = from[12+1]; to[12+3] = from[12+2]; to[12+0] = from[12+3];
-    }
-
-    var L = arrNew();
-    L[2*4+3] = 5;
-    for (var i = 0; i < 4; i++) {
-      arrSet(L, i, 3-i, i+1);
-    }
-    var R = arrNew();
 
     /* Example of plain performance calculation. */
-    var tsFrom = new Date().getTime();
-    for (var i = 0; i < N; i++) {
-      arrRotLeft(L, R);
-      arrRotLeft(R, L);
-    }
-    var tsTo = new Date().getTime();
-    arrPrint(L);
-    console.log("arrRotLeft: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
-
-    perf("arrRotLeft", function() {
-      arrRotLeft(this.L, this.R);
-      arrRotLeft(this.R, this.L);
-    }, N, {L: L, R: R});
-    arrPrint(L);
-
-    perf("arrRotLeft_2", function() {
-      arrRotLeft_2(this.L, this.R);
-      arrRotLeft_2(this.R, this.L);
-    }, N, {L: L, R: R});
-    arrPrint(L);
-
+    // var tsFrom = new Date().getTime();
+    // var i;
+    // (function() {
+    //   var brd = new BoardArr();
+    //   for (i = 0; i < N; i++) {
+    //     brd = brd.copy();
+    //   }
+    // })();
+    // var tsTo = new Date().getTime();
+    // console.log("BoardArr.prototype.copy|new: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
 
     perf("BoardArr.prototype.copy|new", function() {
       this.brd = this.brd.copy();
     }, N, {brd: new BoardArr()});
+    perf("BoardArr2d.prototype.copy|new", function() {
+      this.brd = this.brd.copy();
+    }, N, {brd: new BoardArr2d()});
+    perf("BoardObj.prototype.copy|new", function() {
+      this.brd = this.brd.copy();
+    }, N, {brd: new BoardObj()});
+
     perf("BoardArr.prototype.copy|from-to", function() {
       this.from.copy(this.to);
     }, N, {from: new BoardArr(), to: new BoardArr()});
-
-
-    perf("BoardArr2d.prototype.copy|new", function() {
-      this.brd = this.brd.copy();
-    }, N, {brd: new BoardArr2d()});
     perf("BoardArr2d.prototype.copy|from-to", function() {
       this.from.copy(this.to);
     }, N, {from: new BoardArr2d(), to: new BoardArr2d()});
+    perf("BoardObj.prototype.copy|from-to", function() {
+      this.from.copy(this.to);
+    }, N, {from: new BoardObj(), to: new BoardObj()});
+
     perf("BoardArr2d.prototype.shiftLeft_unrolled", function() {
       this.from.shiftLeft_unrolled(this.to);
       var swap = this.from; this.from = this.to, this.to = swap;
@@ -166,242 +131,6 @@
       this.from.shiftLeft_mostly_unrolled(this.to);
       var swap = this.from; this.from = this.to, this.to = swap;
     }, N, {from: new BoardArr2d(), to: new BoardArr2d()});
-
-    function arr2New() {
-      return [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
-    }
-    function arr2Get(brd, i, j) {
-      return brd[i][j];
-    }
-    function arr2Set(brd, i, j, val) {
-      brd[i][j] = val;
-    }
-    function arr2Print(brd) {
-      for (var i = 0; i < 4; i++) {
-        for (var j = 0; j < 4; j++) {
-          ui.set(i, j, brd[i][j]);
-        }
-      }
-    }
-    function arr2RotLeft(from, to) {
-      for (var i = 0; i < 4; i++) {
-        for (var j = 0; j < 3; j++) {
-          to[i][j+1] = from[i][j];
-        }
-        to[i][0] = from[i][3];
-      }
-    }
-    function arr2RotLeft_2(from, to) {
-      to[0][1] = from[0][0]; to[0][2] = from[0][1]; to[0][3] = from[0][2]; to[0][0] = from[0][3];
-      to[1][1] = from[1][0]; to[1][2] = from[1][1]; to[1][3] = from[1][2]; to[1][0] = from[1][3];
-      to[2][1] = from[2][0]; to[2][2] = from[2][1]; to[2][3] = from[2][2]; to[2][0] = from[2][3];
-      to[3][1] = from[3][0]; to[3][2] = from[3][1]; to[3][3] = from[3][2]; to[3][0] = from[3][3];
-    }
-    function arr2ShiftRight(from, to) {
-      for (var i = 0; i < 4; i++) {
-        if (from[i][2] == from[i][3]) {
-          to[i][3] = from[i][3] + 1;
-          if (from[i][0] == from[i][1]) {
-            to[i][2] = from[i][1] + 1;
-            to[i][1] = 0;
-          } else {
-            to[i][2] = from[i][1];
-            to[i][1] = from[i][0];
-          }
-          to[i][0] = 0;
-        } else {
-          to[i][3] = from[i][3];
-          if (from[i][1] == from[i][2]) {
-            to[i][2] = from[i][2] + 1;
-            to[i][1] = from[i][0];
-            to[i][0] = 0;
-          } else {
-            to[i][2] = from[i][2];
-            if (from[i][0] == from[i][1]) {
-              to[i][1] = from[i][1] + 1;
-              to[i][0] = 0;
-            } else {
-              to[i][1] = from[i][1];
-              to[i][0] = from[i][0];
-            }
-          }
-        }
-      }
-    }
-    function arr2ShiftLeft(from, to) {
-      for (var i = 3; i >= 0; i--) {
-        if (from[i][0] == from[i][1]) {
-          to[i][0] = from[i][0] + 1;
-          if (from[i][2] == from[i][3]) {
-            to[i][1] = from[i][2] + 1;
-            to[i][2] = 0;
-          } else {
-            to[i][1] = from[i][2];
-            to[i][2] = from[i][3];
-          }
-          to[i][3] = 0;
-        } else {
-          to[i][0] = from[i][0];
-          if (from[i][1] == from[i][2]) {
-            to[i][1] = from[i][1] + 1;
-            to[i][2] = from[i][3];
-            to[i][3] = 0;
-          } else {
-            to[i][1] = from[i][1];
-            if (from[i][2] == from[i][3]) {
-              to[i][2] = from[i][2] + 1;
-              to[i][3] = 0;
-            } else {
-              to[i][2] = from[i][2];
-              to[i][3] = from[i][3];
-            }
-          }
-        }
-      }
-    }
-    function arr2ShiftUp(from, to) {
-      for (var j = 3; j >= 0; j--) {
-        if (from[0][j] == from[1][j]) {
-          to[0][j] = from[0][j] + 1;
-          if (from[2][j] == from[3][j]) {
-            to[1][j] = from[2][j] + 1;
-            to[2][j] = 0;
-          } else {
-            to[1][j] = from[2][j];
-            to[2][j] = from[3][j];
-          }
-          to[3][j] = 0;
-        } else {
-          to[0][j] = from[0][j];
-          if (from[1][j] == from[2][j]) {
-            to[1][j] = from[1][j] + 1;
-            to[2][j] = from[3][j];
-            to[3][j] = 0;
-          } else {
-            to[1][j] = from[1][j];
-            if (from[2][j] == from[3][j]) {
-              to[2][j] = from[2][j] + 1;
-              to[3][j] = 0;
-            } else {
-              to[2][j] = from[2][j];
-              to[3][j] = from[3][j];
-            }
-          }
-        }
-      }
-    }
-    function arr2ShiftDown(from, to) {
-      for (var j = 0; j < 4; j++) {
-        if (from[2][j] == from[3][j]) {
-          to[3][j] = from[3][j] + 1;
-          if (from[0][j] == from[1][j]) {
-            to[2][j] = from[1][j] + 1;
-            to[1][j] = 0;
-          } else {
-            to[2][j] = from[1][j];
-            to[1][j] = from[0][j];
-          }
-          to[0][j] = 0;
-        } else {
-          to[3][j] = from[3][j];
-          if (from[1][j] == from[2][j]) {
-            to[2][j] = from[2][j] + 1;
-            to[1][j] = from[0][j];
-            to[0][j] = 0;
-          } else {
-            to[2][j] = from[2][j];
-            if (from[0][j] == from[1][j]) {
-              to[1][j] = from[1][j] + 1;
-              to[0][j] = 0;
-            } else {
-              to[1][j] = from[1][j];
-              to[0][j] = from[0][j];
-            }
-          }
-        }
-      }
-    }
-    var L = arr2New();
-    L[2][3] = 5;
-    for (var i = 0; i < 4; i++) {
-      arr2Set(L, i, 3-i, i+1);
-    }
-
-    var R = arr2New();
-    var tsFrom = new Date().getTime();
-    for (var i = 0; i < N; i++) {
-      arr2RotLeft(L, R);
-      arr2RotLeft(R, L);
-    }
-    var tsTo = new Date().getTime();
-    /* arr2Print(L); */
-    console.log("arr2RotLeft: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
-
-    var tsFrom = new Date().getTime();
-    for (var i = 0; i < N; i++) {
-      arr2RotLeft_2(L, R);
-      arr2RotLeft_2(R, L);
-    }
-    var tsTo = new Date().getTime();
-    /* arr2Print(L); */
-    console.log("arr2RotLeft_2: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
-
-
-    var objMap = [["aa", "ab", "ac", "ad"], ["ba", "bb", "bc", "bd"], ["ca", "cb", "cc", "cd"], ["da", "db", "dc", "dd"]];
-    function objNew() {
-      return { aa: 0, ab: 0, ac: 0, ad: 0,
-               ba: 0, bb: 0, bc: 0, bd: 0,
-               ca: 0, cb: 0, cc: 0, cd: 0,
-               da: 0, db: 0, dc: 0, dd: 0 };
-    }
-    function objGet(brd, i, j) {
-      return brd[objMap[i][j]];
-    }
-    function objSet(brd, i, j, val) {
-      brd[objMap[i][j]] = val;
-    }
-    function objPrint(brd) {
-      ui.set(0, 0, brd.aa); ui.set(0, 1, brd.ab); ui.set(0, 2, brd.ac); ui.set(0, 3, brd.ad);
-      ui.set(1, 0, brd.ba); ui.set(1, 1, brd.bb); ui.set(1, 2, brd.bc); ui.set(1, 3, brd.bd);
-      ui.set(2, 0, brd.ca); ui.set(2, 1, brd.cb); ui.set(2, 2, brd.cc); ui.set(2, 3, brd.cd);
-      ui.set(3, 0, brd.da); ui.set(3, 1, brd.db); ui.set(3, 2, brd.dc); ui.set(3, 3, brd.dd);
-    }
-    function objRotLeft(from, to) {
-      to.ab = from.aa; to.ac = from.ab; to.ad = from.ac; to.aa = from.ad;
-      to.bb = from.ba; to.bc = from.bb; to.bd = from.bc; to.ba = from.bd;
-      to.cb = from.ca; to.cc = from.cb; to.cd = from.cc; to.ca = from.cd;
-      to.db = from.da; to.dc = from.db; to.dd = from.dc; to.da = from.dd;
-    }
-    function objRotLeft_2(from, to) {
-      to["ab"] = from["aa"]; to["ac"] = from["ab"]; to["ad"] = from["ac"]; to["aa"] = from["ad"];
-      to["bb"] = from["ba"]; to["bc"] = from["bb"]; to["bd"] = from["bc"]; to["ba"] = from["bd"];
-      to["cb"] = from["ca"]; to["cc"] = from["cb"]; to["cd"] = from["cc"]; to["ca"] = from["cd"];
-      to["db"] = from["da"]; to["dc"] = from["db"]; to["dd"] = from["dc"]; to["da"] = from["dd"];
-    }
-    var L = objNew();
-    L.cd = 5;
-    for (var i = 0; i < 4; i++) {
-      objSet(L, i, 3-i, i+1);
-    }
-
-    var R = objNew();
-    var tsFrom = new Date().getTime();
-    for (var i = 0; i < N; i++) {
-      objRotLeft(L, R);
-      objRotLeft(R, L);
-    }
-    var tsTo = new Date().getTime();
-    objPrint(L);
-    console.log("objRotLeft: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
-
-    var tsFrom = new Date().getTime();
-    for (var i = 0; i < N; i++) {
-      objRotLeft_2(L, R);
-      objRotLeft_2(R, L);
-    }
-    var tsTo = new Date().getTime();
-    objPrint(L);
-    console.log("objRotLeft_2: %f ms, %d u/s", tsTo-tsFrom, 2*i/(tsTo - tsFrom)*1000);
   </script>
 
   <script>