99 lines
2.2 KiB
JavaScript
99 lines
2.2 KiB
JavaScript
import {diagonal, isSmaller, key, plus, ofKey, zero} from Geometry.Vector;
|
|
import {at, generate} from Grid.Util;
|
|
|
|
function CellSet(definition) {
|
|
definition = definition || {};
|
|
this.cells = {};
|
|
if(definition.type == 'rectangle') {
|
|
this.fromRectangle(definition.origin, definition.offset);
|
|
} else if(definition.type == 'isochrome') {
|
|
this.fromIsochrome(definition.grid, definition.origin);
|
|
} else if(definition.type == 'union') {
|
|
this.fromUnion(definition.sets);
|
|
}
|
|
}
|
|
|
|
CellSet.prototype.fromRectangle = function(origin, maxOffset) {
|
|
generate(
|
|
maxOffset.row,
|
|
maxOffset.column,
|
|
function(offset) {
|
|
this.add(plus(origin, offset));
|
|
}.bind(this)
|
|
);
|
|
};
|
|
|
|
CellSet.prototype.fromIsochrome = function(grid, origin) {
|
|
var originColor = at(grid, origin);
|
|
var queue = [origin];
|
|
while(queue.length > 0) {
|
|
var cell = queue.shift();
|
|
this.add(cell);
|
|
for(var d = -1; d < 2; d += 2) {
|
|
[plus(cell, vertical(d)), plus(cell, horizontal(d))].forEach(
|
|
gateKeeper(this, grid, queue, originColor)
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
CellSet.prototype.fromUnion = function(sets) {
|
|
for(var i = 0; i < sets.length; i++) {
|
|
for(var k in sets[i].cells) {
|
|
this.cells[k] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
CellSet.prototype.add = function(v) {
|
|
this.cells[key(v)] = true;
|
|
};
|
|
|
|
CellSet.prototype.remove = function(v) {
|
|
delete this.cells[key(v)];
|
|
};
|
|
|
|
CellSet.prototype.contains = function(v) {
|
|
return !!this.cells[key(v)];
|
|
};
|
|
|
|
CellSet.prototype.isEmpty = function() {
|
|
return Object.keys(this.cells).length < 1;
|
|
};
|
|
|
|
CellSet.prototype.map = function(f) {
|
|
var result = [];
|
|
for(var k in this.cells) {
|
|
result.push(f(ofKey(k)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
CellSet.prototype.iter = function(f) {
|
|
this.map(f);
|
|
}
|
|
|
|
CellSet.prototype.difference = function(cellSet) {
|
|
var newCellSet = new CellSet();
|
|
this.iter(function(v) {
|
|
if(!cellSet.contains(v)) {
|
|
newCellSet.add(v);
|
|
}
|
|
});
|
|
return newCellSet;
|
|
}
|
|
|
|
return {
|
|
make: function(definition) {return new CellSet(definition);},
|
|
union: function(sets) {return new CellSet({type: 'union', sets: sets});}
|
|
};
|
|
|
|
function gateKeeper(cellSet, grid, queue, originColor) {
|
|
return function(cell) {
|
|
if(isSmaller(zero(), cell) && isSmaller(cell, diagonal(grid.length-1))
|
|
&& !cellSet.contains(cell)
|
|
&& at(grid, cell) == originColor) {
|
|
queue.push(cell);
|
|
}
|
|
}
|
|
}
|