Start implementing the solver
This commit is contained in:
parent
6e8d07e973
commit
43900cfb64
5 changed files with 156 additions and 12 deletions
|
@ -5,22 +5,24 @@ function CellSet(definition) {
|
||||||
this.fromRectangle(definition);
|
this.fromRectangle(definition);
|
||||||
} else if(definition.type == 'isochrome') {
|
} else if(definition.type == 'isochrome') {
|
||||||
this.fromIsochrome(definition);
|
this.fromIsochrome(definition);
|
||||||
|
} else if(definition.type == 'union') {
|
||||||
|
this.fromUnion(definition.sets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CellSet.prototype.fromRectangle = function(definition) {
|
CellSet.prototype.fromRectangle = function(definition) {
|
||||||
var xMax = definition.x + definition.width;
|
var iMax = definition.row + definition.height;
|
||||||
var yMax = definition.y + definition.height;
|
var jMax = definition.column + definition.width;
|
||||||
for(var i = definition.x; i < xMax; i++) {
|
for(var i = definition.row; i < iMax; i++) {
|
||||||
for(var j = definition.y; j < yMax; j++) {
|
for(var j = definition.column; j < jMax; j++) {
|
||||||
this.add(i, j);
|
this.add(i, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CellSet.prototype.fromIsochrome = function(definition) {
|
CellSet.prototype.fromIsochrome = function(definition) {
|
||||||
var originColor = definition.data[definition.x][definition.y];
|
var originColor = definition.data[definition.row][definition.column];
|
||||||
var queue = [{i: definition.x, j: definition.y}];
|
var queue = [{i: definition.row, j: definition.column}];
|
||||||
while(queue.length > 0) {
|
while(queue.length > 0) {
|
||||||
var p = queue[0];
|
var p = queue[0];
|
||||||
this.add(p.i, p.j);
|
this.add(p.i, p.j);
|
||||||
|
@ -33,6 +35,14 @@ CellSet.prototype.fromIsochrome = function(definition) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CellSet.prototype.fromUnion = function(sets) {
|
||||||
|
for(var i = 0; i < sets.length; i++) {
|
||||||
|
for(var key in sets[i].cells) {
|
||||||
|
this.cells[key] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CellSet.prototype.add = function(i, j) {
|
CellSet.prototype.add = function(i, j) {
|
||||||
this.cells[id(i, j)] = true;
|
this.cells[id(i, j)] = true;
|
||||||
};
|
};
|
||||||
|
@ -49,15 +59,31 @@ CellSet.prototype.isEmpty = function() {
|
||||||
return Object.keys(this.cells).length < 1;
|
return Object.keys(this.cells).length < 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
CellSet.prototype.iter = function(f) {
|
CellSet.prototype.map = function(f) {
|
||||||
|
var result = [];
|
||||||
for(var key in this.cells) {
|
for(var key in this.cells) {
|
||||||
var coordinates = key.split(':');
|
result.push(f.apply(null, key.split(':')));
|
||||||
f(coordinates[0], coordinates[1]);
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CellSet.prototype.iter = function(f) {
|
||||||
|
this.map(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
CellSet.prototype.difference = function(cellSet) {
|
||||||
|
var newCellSet = new CellSet();
|
||||||
|
this.iter(function(i, j) {
|
||||||
|
if(!cellSet.contains(i, j)) {
|
||||||
|
newCellSet.add(i, j);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return newCellSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
make: function(definition) {return new CellSet(definition);},
|
make: function(definition) {return new CellSet(definition);},
|
||||||
|
union: function(sets) {return new CellSet({type: 'union', sets: sets});}
|
||||||
};
|
};
|
||||||
|
|
||||||
function id(i, j) {
|
function id(i, j) {
|
||||||
|
|
|
@ -39,7 +39,7 @@ function makeRow(config) {
|
||||||
function clear() {
|
function clear() {
|
||||||
grid.data = generate(function() {return; });
|
grid.data = generate(function() {return; });
|
||||||
grid.missing = CellSet.make(
|
grid.missing = CellSet.make(
|
||||||
{type: 'rectangle', x: 0, y: 0, width: 8, height: 8}
|
{type: 'rectangle', row: 0, column: 0, width: 8, height: 8}
|
||||||
);
|
);
|
||||||
iter(function(row, column) {
|
iter(function(row, column) {
|
||||||
cell(row, column).className = '';
|
cell(row, column).className = '';
|
||||||
|
|
|
@ -14,9 +14,9 @@ function colorize(row, column, color) {
|
||||||
grid.missing.remove(row, column);
|
grid.missing.remove(row, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
function paint(i0, j0) {
|
function paint(row, column) {
|
||||||
var cellSet = CellSet.make(
|
var cellSet = CellSet.make(
|
||||||
{type: 'isochrome', x: i0, y: j0, data: Grid.get().data}
|
{type: 'isochrome', row: row, column: column, data: Grid.get().data}
|
||||||
);
|
);
|
||||||
cellSet.iter(colorize);
|
cellSet.iter(colorize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
import Grid;
|
||||||
|
import Solver;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
events: {
|
events: {
|
||||||
onEnter: onEnter,
|
onEnter: onEnter,
|
||||||
|
@ -5,4 +8,5 @@ return {
|
||||||
};
|
};
|
||||||
|
|
||||||
function onEnter() {
|
function onEnter() {
|
||||||
|
console.log(Solver.step(Grid.get().data));
|
||||||
}
|
}
|
||||||
|
|
114
js/Solver.js
Normal file
114
js/Solver.js
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
import CellSet;
|
||||||
|
|
||||||
|
return {
|
||||||
|
step: step
|
||||||
|
};
|
||||||
|
|
||||||
|
function step(matrix) {
|
||||||
|
var zones = getZones(matrix);
|
||||||
|
var grid = getGrid(matrix.length);
|
||||||
|
var rowClusters = checkRowsInclusions(matrix);
|
||||||
|
if(rowClusters.length > 0) {
|
||||||
|
rowClusters.forEach(function(rowCluster) {
|
||||||
|
rowCluster.toClear = difference(
|
||||||
|
rowCluster.colors.map(function(color) {return zones[color];}),
|
||||||
|
rowCluster.rows.map(function(row) {return grid.rows[row];})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return rowClusters;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getZones(matrix) {
|
||||||
|
var zones = {};
|
||||||
|
for(var row = 0; row < matrix.length; row++) {
|
||||||
|
for(var column = 0; column < matrix[row].length; column++) {
|
||||||
|
var color = matrix[row][column];
|
||||||
|
if(zones[color] == undefined) {
|
||||||
|
zones[color] = CellSet.make(
|
||||||
|
{type: 'isochrome', row: row, column: column, data: matrix}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return zones;
|
||||||
|
}
|
||||||
|
|
||||||
|
function line(type, size, i) {
|
||||||
|
if(type == 'row') {
|
||||||
|
return CellSet.make(
|
||||||
|
{type: 'rectangle', row: i, column: 0, width: size, height: 1}
|
||||||
|
);
|
||||||
|
} else if(type == 'column') {
|
||||||
|
return CellSet.make(
|
||||||
|
{type: 'rectangle', row: 0, column: i, width: 1, height: size}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGrid(size) {
|
||||||
|
var empty = Array.from({length: size});
|
||||||
|
return {
|
||||||
|
rows: empty.map(function(x, i) {return line('row', size, i);}),
|
||||||
|
columns: empty.map(function(x, i) {return line('column', size, i);}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColorsByRow(matrix) {
|
||||||
|
var colorsByRow = [];
|
||||||
|
for(var row = 0; row < matrix.length; row++) {
|
||||||
|
colorsByRow.push(
|
||||||
|
quotient(matrix[row], function(c0, c1) {return c0 == c1;}).map(
|
||||||
|
function(colorClass) {return colorClass.specimen;}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return colorsByRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkRowsInclusions(matrix) {
|
||||||
|
var colorsByRow = getColorsByRow(matrix);
|
||||||
|
var colorSets = quotient(colorsByRow, sameColorsSet);
|
||||||
|
return colorSets.reduce(function(commands, colorSet) {
|
||||||
|
if(colorSet.occurrences.length == colorSet.specimen.length) {
|
||||||
|
commands.push({
|
||||||
|
reason: 'rowsInColors',
|
||||||
|
rows: colorSet.occurrences,
|
||||||
|
colors: colorSet.specimen
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return commands;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
function quotient(elements, equivalence) {
|
||||||
|
var classes = [];
|
||||||
|
elements.forEach(function(element, i) {
|
||||||
|
for(var c = 0; c < classes.length; c++) {
|
||||||
|
if(equivalence(element, classes[c].specimen)) {
|
||||||
|
classes[c].occurrences.push(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classes.push({specimen: element, occurrences: [i]});
|
||||||
|
});
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sameColorsSet(s0, s1) {
|
||||||
|
if(s0.length != s1.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var o0 = {};
|
||||||
|
s0.forEach(function(x) {o0[x] = true;});
|
||||||
|
for(var i = 0; i < s1.length; i++) {
|
||||||
|
if(!o0[s1[i]]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function difference(setsFrom, setsSubstracted) {
|
||||||
|
return CellSet.union(setsFrom).difference(CellSet.union(setsSubstracted));
|
||||||
|
}
|
Loading…
Reference in a new issue