Skip to content

Instantly share code, notes, and snippets.

@kirilloid
Created April 21, 2015 17:32
Show Gist options
  • Save kirilloid/11d079f2ebe10994ac3d to your computer and use it in GitHub Desktop.
Save kirilloid/11d079f2ebe10994ac3d to your computer and use it in GitHub Desktop.
Triangle puzzle
/*
0
1 1
1 1 1
1 1 1 1
1 1 1 1 1
|
v
1
0 0
0 0 0
0 0 0 0
0 0 0 0 0
xx.
xxx
.xx
*/
function countBits (n) {
n -= (n >> 1) & 0x55555555;
n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
return ((n + (n >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
function Field(size) {
var n = size*(size+1)/2;
this.size = size;
this.data = (1 << n) - 1;
this.set(0, 0, 0);
this.length = n - 1;
}
Field.prototype = {
_toBit: function(x, y) {
if (x < 0) return -1; // throw new RangeError("x should be non-negative");
if (y < 0) return -1; // throw new RangeError("y should be non-negative");
if (x >= this.size) return -1; // throw new RangeError("x should be less than size");
if (y >= this.size) return -1; // throw new RangeError("y should be less than size");
if (x > y) return -1; // throw new RangeError("position should be within triangle");
return y*(y+1)/2 + x;
},
get: function (x, y) {
var bit = this._toBit(x, y);
if (bit === -1) return -1;
var mask = 1 << bit;
return +!!(this.data & mask);
},
set: function (x, y, v) {
var mask = 1 << this._toBit(x, y);
if (v) {
this.data |= mask;
} else {
this.data &= ~mask;
}
},
store: function () {
return this.data;
},
load: function (data) {
this.data = data;
this.length = countBits(data);
},
check: function (x, y, dx, dy) {
return (
this.get(x+dx, y+dy) === 1 &&
this.get(x+dx*2, y+dy*2) === 0
);
},
move: function (x, y, dx, dy) {
this.set(x, y, 0);
this.set(x+dx, y+dy, 0);
this.set(x+dx*2, y+dy*2, 1);
this.length--;
return true;
},
tryMove: function (x, y, dx, dy) {
return this.check.apply(this, arguments) &&
this.move.apply(this, arguments);
},
toString: function () {
var x, y, i, s, a = [];
for (y = 0; y < this.size; y++) {
s = "";
for (x = this.size; x >= y; x--) s += " ";
for (x = 0; x <= y; x++) s += this.get(x, y) + " ";
a.push(s);
}
return a.join("\n");
}
};
var F = new Field(5),
d = [[-1,0],[-1,-1],[0,-1],[1,0],[1,1],[0,1]];
(function r (field) {
var x, y, i, moved = false;
F.load(field);
if (F.length === 1 && F.get(0, 0) === 1) return true;
for (y = 0; y < F.size; y++) {
for (x = 0; x <= y; x++) {
if (F.get(x, y) !== 1) continue;
for (i = 0; i < 6; i++) {
if (!F.tryMove(x, y, d[i][0], d[i][1])) continue;
moved = true;
if (r(F.store())) {
F.load(field);
console.log(F + '');
return true;
}
F.load(field);
}}}
if (!moved) return false; // no more moved;
}(F.store()));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment