Still hacking away
This commit is contained in:
parent
71c405e5cd
commit
0a61d9a389
3 changed files with 110 additions and 74 deletions
|
@ -1,82 +1,83 @@
|
||||||
import * as CellSet from Geometry.CellSet;
|
import * as CellSet from Geometry.CellSet;
|
||||||
import * as Strategy from Solver.Strategy;
|
import * as Strategy from Solver.Strategy;
|
||||||
import {getColumn, getRow} from Geometry.Vector;
|
import {getColumn, getRow} from Geometry.Vector;
|
||||||
|
import Set;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
find: find
|
find: find
|
||||||
};
|
};
|
||||||
|
|
||||||
function find(getColor, zones, lines) {
|
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(
|
return Strategy.map(
|
||||||
stepOfInclusion,
|
stepOfInclusion(subName, superName),
|
||||||
Strategy.tryEach([
|
Strategy.tryEach(
|
||||||
findInclusion(lines.rows, zones, getColor),
|
group(subDimension.sets.map(getAll(superDimension.property))).map(diff)
|
||||||
findInclusion(lines.columns, zones, getColor),
|
)
|
||||||
findInclusion(zones, lines.rows, getRow),
|
|
||||||
findInclusion(zones, lines.columns, getColumn)
|
|
||||||
])
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function findInclusion(subsets, supersets, property) {
|
function difference(getSubset, getSuperset) {
|
||||||
return Strategy.tryEach(
|
return function(group) {
|
||||||
quotient(subsets.map(getClasses(property)), sameSet)
|
|
||||||
.map(keepInclusion(subsets, supersets))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function keepInclusion(subsets, supersets) {
|
|
||||||
return function(set) {
|
|
||||||
return function() {
|
return function() {
|
||||||
if(set.occurrences.length == set.specimen.length) {
|
if(group.indices.length == group.value.size()) {
|
||||||
var superset = set.specimen.map(function(i) {return supersets[i];});
|
var empty = CellSet.union(group.value.map(getSuperset))
|
||||||
var subset = set.specimen.map(function(i) {return subsets[i];});
|
.difference(CellSet.union(group.indices.map(getSubset)));
|
||||||
empty = difference(superset, subset);
|
return empty.size() > 0 ? {empty: empty, group: group} : null;
|
||||||
return empty.isEmpty() ? null : empty;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepOfInclusion(inclusion) {
|
function stepOfInclusion(subName, superName) {
|
||||||
return {
|
return function(diffedGroup) {
|
||||||
reason: 'inclusion',
|
var step = {reason: 'inclusion', empty: diffedGroup.empty};
|
||||||
empty: difference(inclusion.superset, inclusion.subset),
|
step[subName] = diffedGroup.group.indices;
|
||||||
|
step['in_' + superName] = diffedGroup.group.value.toList();
|
||||||
|
return step;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function quotient(elements, equivalence) {
|
function group(sets) {
|
||||||
var classes = [];
|
var groups = [];
|
||||||
elements.forEach(function(element, i) {
|
sets.forEach(function(set, i) {
|
||||||
for(var c = 0; c < classes.length; c++) {
|
for(var g = 0; g < groups.length; g++) {
|
||||||
if(equivalence(element, classes[c].specimen)) {
|
if(groups[g].value.equals(set)) {
|
||||||
classes[c].occurrences.push(i);
|
groups[g].indices.push(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
classes.push({specimen: element, occurrences: [i]});
|
groups.push({value: set, indices: [i]});
|
||||||
});
|
});
|
||||||
return classes;
|
return groups;
|
||||||
}
|
|
||||||
|
|
||||||
function getClasses(property) {
|
|
||||||
return function(cellSet) {
|
|
||||||
return Array.from(quotient(
|
|
||||||
cellSet.getAll(property), function(a, b) {return a == b;})
|
|
||||||
.map(function(equivClass) {return equivClass.specimen;})
|
|
||||||
).sort();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function sameSet(s0, s1) {
|
|
||||||
for(var i = 0; i < s0.length; i++) {
|
|
||||||
if(i >= s1.length || s0[i] != s1[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function difference(supersets, subsets) {
|
|
||||||
return CellSet.union(supersets).difference(CellSet.union(subsets));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
|
import * as CellSet from Geometry.CellSet;
|
||||||
|
import getCellSets from Solver.State;
|
||||||
import * as Strategy from Solver.Strategy;
|
import * as Strategy from Solver.Strategy;
|
||||||
import {diagonal, plus} from Geometry.Vector;
|
import {diagonal, getColumn, getRow, plus} from Geometry.Vector;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
find: find
|
find: find
|
||||||
};
|
};
|
||||||
|
|
||||||
function find(zones, lines) {
|
function find(solvingState) {
|
||||||
var cellSets = zones.concat(lines.rows).concat(lines.columns);
|
var cellSets = getCellSets(solvingState);
|
||||||
return Strategy.map(
|
return Strategy.map(
|
||||||
stepOfCell(cellSets),
|
stepOfCell,
|
||||||
Strategy.tryEach(cellSets.map(getSingleCellIn))
|
Strategy.tryEach(cellSets.map(getSingleCellIn))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,27 +18,25 @@ function find(zones, lines) {
|
||||||
function getSingleCellIn(cellSet) {
|
function getSingleCellIn(cellSet) {
|
||||||
return function() {
|
return function() {
|
||||||
if(cellSet.size() == 1) {
|
if(cellSet.size() == 1) {
|
||||||
return cellSet.getAll(function(v) {return v;})[0];
|
return cellSet.toList()[0];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepOfCell(cellSets) {
|
function stepOfCell(cell) {
|
||||||
return function(cell) {
|
|
||||||
return {
|
return {
|
||||||
reason: 'singleCell',
|
reason: 'singleCell',
|
||||||
empty: toEmpty(cell).intersection(cellSets),
|
empty: toEmpty(cell),
|
||||||
star: CellSet.cells([cell])
|
star: new CellSet.CellSet(cell)
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function toEmpty(cell) {
|
function toEmpty(cell) {
|
||||||
var around = CellSet.rectangle(plus(cell, diagonal(-1)), diagonal(2));
|
var union = CellSet.union([
|
||||||
around.remove(v);
|
CellSet.rectangle(plus(cell, diagonal(-1)), diagonal(3)),
|
||||||
return CellSet.union([
|
CellSet.row(getRow(cell)),
|
||||||
around,
|
CellSet.column(getColumn(cell))
|
||||||
CellSet.row(v.getRow()),
|
|
||||||
CellSet.column(v.getColumn())
|
|
||||||
]);
|
]);
|
||||||
|
union.remove(cell);
|
||||||
|
return union;
|
||||||
}
|
}
|
||||||
|
|
35
js/Solver/State.js
Normal file
35
js/Solver/State.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import * as CellSet from Geometry.CellSet;
|
||||||
|
|
||||||
|
return {
|
||||||
|
getCellSets: getCellSets,
|
||||||
|
start: start
|
||||||
|
};
|
||||||
|
|
||||||
|
function start(coloring) {
|
||||||
|
var empty = Array.from({length: size});
|
||||||
|
return {
|
||||||
|
constellation: square(size),
|
||||||
|
getColor: asAFunction(coloring),
|
||||||
|
missing: CellSet.rectangle(zero(), diagonal(size)),
|
||||||
|
colorZones: getZones(coloring),
|
||||||
|
rows: empty.map(function(_, i) {return CellSet.row(i);}),
|
||||||
|
columns: empty.map(function(_, i) {return CellSet.column(i);})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getZones(grid) {
|
||||||
|
var zones = Array.from({length: size});
|
||||||
|
iter(grid, function(color, cell) {
|
||||||
|
if(zones[color] == undefined) {
|
||||||
|
zones[color] = new CellSet.CellSet();
|
||||||
|
}
|
||||||
|
zones[color].add(cell);
|
||||||
|
});
|
||||||
|
return zones;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCellSets(solvingState) {
|
||||||
|
return solvingState.colorZones
|
||||||
|
.concat(solvingState.rows)
|
||||||
|
.concat(solvingState.columns);
|
||||||
|
}
|
Loading…
Reference in a new issue