Start implementing the solver

This commit is contained in:
Tissevert 2022-07-31 16:32:24 +02:00
parent 6e8d07e973
commit 43900cfb64
5 changed files with 156 additions and 12 deletions

View File

@ -5,22 +5,24 @@ function CellSet(definition) {
this.fromRectangle(definition);
} else if(definition.type == 'isochrome') {
this.fromIsochrome(definition);
} else if(definition.type == 'union') {
this.fromUnion(definition.sets);
}
}
CellSet.prototype.fromRectangle = function(definition) {
var xMax = definition.x + definition.width;
var yMax = definition.y + definition.height;
for(var i = definition.x; i < xMax; i++) {
for(var j = definition.y; j < yMax; j++) {
var iMax = definition.row + definition.height;
var jMax = definition.column + definition.width;
for(var i = definition.row; i < iMax; i++) {
for(var j = definition.column; j < jMax; j++) {
this.add(i, j);
}
}
};
CellSet.prototype.fromIsochrome = function(definition) {
var originColor = definition.data[definition.x][definition.y];
var queue = [{i: definition.x, j: definition.y}];
var originColor = definition.data[definition.row][definition.column];
var queue = [{i: definition.row, j: definition.column}];
while(queue.length > 0) {
var p = queue[0];
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) {
this.cells[id(i, j)] = true;
};
@ -49,15 +59,31 @@ CellSet.prototype.isEmpty = function() {
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) {
var coordinates = key.split(':');
f(coordinates[0], coordinates[1]);
result.push(f.apply(null, key.split(':')));
}
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 {
make: function(definition) {return new CellSet(definition);},
union: function(sets) {return new CellSet({type: 'union', sets: sets});}
};
function id(i, j) {

View File

@ -39,7 +39,7 @@ function makeRow(config) {
function clear() {
grid.data = generate(function() {return; });
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) {
cell(row, column).className = '';

View File

@ -14,9 +14,9 @@ function colorize(row, column, color) {
grid.missing.remove(row, column);
}
function paint(i0, j0) {
function paint(row, column) {
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);
}

View File

@ -1,3 +1,6 @@
import Grid;
import Solver;
return {
events: {
onEnter: onEnter,
@ -5,4 +8,5 @@ return {
};
function onEnter() {
console.log(Solver.step(Grid.get().data));
}

114
js/Solver.js Normal file
View 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));
}