Constellations/js/Solver.js
2022-08-11 09:58:57 +02:00

114 lines
2.7 KiB
JavaScript

import * as CellSet from Geometry.CellSet;
return {
step: step
};
function step(grid) {
var zones = getZones(grid);
var lines = getLines(grid.length);
var rowClusters = checkRowsInclusions(grid);
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 lines.rows[row];})
);
});
}
return rowClusters;
}
function getZones(grid) {
var zones = {};
for(var row = 0; row < grid.length; row++) {
for(var column = 0; column < grid[row].length; column++) {
var color = grid[row][column];
if(zones[color] == undefined) {
zones[color] = CellSet.make(
{type: 'isochrome', row: row, column: column, grid: grid}
);
}
}
}
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 getLines(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(grid) {
var colorsByRow = [];
for(var row = 0; row < grid.length; row++) {
colorsByRow.push(
quotient(grid[row], function(c0, c1) {return c0 == c1;}).map(
function(colorClass) {return colorClass.specimen;}
)
);
}
return colorsByRow;
}
function checkRowsInclusions(grid) {
var colorsByRow = getColorsByRow(grid);
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));
}