2022-08-10 21:12:39 +02:00
|
|
|
import * as CellSet from Geometry.CellSet;
|
2022-07-31 16:32:24 +02:00
|
|
|
|
|
|
|
return {
|
|
|
|
step: step
|
|
|
|
};
|
|
|
|
|
2022-08-06 20:15:53 +02:00
|
|
|
function step(grid) {
|
|
|
|
var zones = getZones(grid);
|
|
|
|
var lines = getLines(grid.length);
|
|
|
|
var rowClusters = checkRowsInclusions(grid);
|
2022-07-31 16:32:24 +02:00
|
|
|
if(rowClusters.length > 0) {
|
|
|
|
rowClusters.forEach(function(rowCluster) {
|
|
|
|
rowCluster.toClear = difference(
|
|
|
|
rowCluster.colors.map(function(color) {return zones[color];}),
|
2022-08-06 20:15:53 +02:00
|
|
|
rowCluster.rows.map(function(row) {return lines.rows[row];})
|
2022-07-31 16:32:24 +02:00
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return rowClusters;
|
|
|
|
}
|
|
|
|
|
2022-08-06 20:15:53 +02:00
|
|
|
function getZones(grid) {
|
2022-07-31 16:32:24 +02:00
|
|
|
var zones = {};
|
2022-08-06 20:15:53 +02:00
|
|
|
for(var row = 0; row < grid.length; row++) {
|
|
|
|
for(var column = 0; column < grid[row].length; column++) {
|
|
|
|
var color = grid[row][column];
|
2022-07-31 16:32:24 +02:00
|
|
|
if(zones[color] == undefined) {
|
|
|
|
zones[color] = CellSet.make(
|
2022-08-06 20:15:53 +02:00
|
|
|
{type: 'isochrome', row: row, column: column, grid: grid}
|
2022-07-31 16:32:24 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-06 20:15:53 +02:00
|
|
|
function getLines(size) {
|
2022-07-31 16:32:24 +02:00
|
|
|
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);}),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-08-06 20:15:53 +02:00
|
|
|
function getColorsByRow(grid) {
|
2022-07-31 16:32:24 +02:00
|
|
|
var colorsByRow = [];
|
2022-08-06 20:15:53 +02:00
|
|
|
for(var row = 0; row < grid.length; row++) {
|
2022-07-31 16:32:24 +02:00
|
|
|
colorsByRow.push(
|
2022-08-06 20:15:53 +02:00
|
|
|
quotient(grid[row], function(c0, c1) {return c0 == c1;}).map(
|
2022-07-31 16:32:24 +02:00
|
|
|
function(colorClass) {return colorClass.specimen;}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return colorsByRow;
|
|
|
|
}
|
|
|
|
|
2022-08-06 20:15:53 +02:00
|
|
|
function checkRowsInclusions(grid) {
|
|
|
|
var colorsByRow = getColorsByRow(grid);
|
2022-07-31 16:32:24 +02:00
|
|
|
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));
|
|
|
|
}
|