Constellations/js/Solver/Inclusion.js

84 lines
2.1 KiB
JavaScript

import * as CellSet from Geometry.CellSet;
import * as Strategy from Solver.Strategy;
import {getColumn, getRow} from Geometry.Vector;
import Set;
return {
find: find
};
function find(solvingState) {
var inclusion = findInclusion(cellDimensionsByname(solvingState));
return Strategy.tryEach([
inclusion('rows', 'colors'),
inclusion('columns', 'colors'),
inclusion('colors', 'rows'),
inclusion('colors', 'columns')
]);
}
function cellDimensionsByname(solvingState) {
return {
rows: {sets: solvingState.rows, property: getRow},
columns: {sets: solvingState.columns, property: getColumn},
colors: {sets: solvingState.colorZones, property: solvingState.getColor}
};
}
function getAll(property) {
return function(cellSet) {return new Set.Int(cellSet.map(property));};
}
function getSet(namedSet) {
return function(i) {return namedSet.sets[i];};
}
function findInclusion(cellDimensions) {
return function(subName, superName) {
var subDimension = cellDimensions[subName];
var superDimension = cellDimensions[superName];
var diff = difference(getSet(subDimension), getSet(superDimension));
return Strategy.map(
stepOfInclusion(subName, superName),
Strategy.tryEach(
group(subDimension.sets.map(getAll(superDimension.property))).map(diff)
)
);
}
}
function difference(getSubset, getSuperset) {
return function(group) {
return function() {
if(group.indices.length == group.value.size()) {
var empty = CellSet.union(group.value.map(getSuperset))
.difference(CellSet.union(group.indices.map(getSubset)));
return empty.size() > 0 ? {empty: empty, group: group} : null;
}
};
};
}
function stepOfInclusion(subName, superName) {
return function(diffedGroup) {
var step = {reason: 'inclusion', empty: diffedGroup.empty};
step[subName] = diffedGroup.group.indices;
step['in_' + superName] = diffedGroup.group.value.toList();
return step;
};
}
function group(sets) {
var groups = [];
sets.forEach(function(set, i) {
for(var g = 0; g < groups.length; g++) {
if(groups[g].value.equals(set)) {
groups[g].indices.push(i);
return;
}
}
groups.push({value: set, indices: [i]});
});
return groups;
}