Still hacking away

This commit is contained in:
Tissevert 2022-08-30 22:39:09 +02:00
parent 71c405e5cd
commit 0a61d9a389
3 changed files with 110 additions and 74 deletions

View file

@ -1,82 +1,83 @@
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(getColor, zones, lines) {
return Strategy.map(
stepOfInclusion,
Strategy.tryEach([
findInclusion(lines.rows, zones, getColor),
findInclusion(lines.columns, zones, getColor),
findInclusion(zones, lines.rows, getRow),
findInclusion(zones, lines.columns, getColumn)
])
);
function find(solvingState) {
var inclusion = findInclusion(cellDimensionsByname(solvingState));
return Strategy.tryEach([
inclusion('rows', 'colors'),
inclusion('columns', 'colors'),
inclusion('colors', 'rows'),
inclusion('colors', 'columns')
]);
}
function findInclusion(subsets, supersets, property) {
return Strategy.tryEach(
quotient(subsets.map(getClasses(property)), sameSet)
.map(keepInclusion(subsets, supersets))
);
}
function keepInclusion(subsets, supersets) {
return function(set) {
return function() {
if(set.occurrences.length == set.specimen.length) {
var superset = set.specimen.map(function(i) {return supersets[i];});
var subset = set.specimen.map(function(i) {return subsets[i];});
empty = difference(superset, subset);
return empty.isEmpty() ? null : empty;
}
};
};
}
function stepOfInclusion(inclusion) {
function cellDimensionsByname(solvingState) {
return {
reason: 'inclusion',
empty: difference(inclusion.superset, inclusion.subset),
rows: {sets: solvingState.rows, property: getRow},
columns: {sets: solvingState.columns, property: getColumn},
colors: {sets: solvingState.colorZones, property: solvingState.getColor}
};
}
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);
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;
}
}
classes.push({specimen: element, occurrences: [i]});
groups.push({value: set, indices: [i]});
});
return classes;
}
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));
return groups;
}

View file

@ -1,14 +1,16 @@
import * as CellSet from Geometry.CellSet;
import getCellSets from Solver.State;
import * as Strategy from Solver.Strategy;
import {diagonal, plus} from Geometry.Vector;
import {diagonal, getColumn, getRow, plus} from Geometry.Vector;
return {
find: find
};
function find(zones, lines) {
var cellSets = zones.concat(lines.rows).concat(lines.columns);
function find(solvingState) {
var cellSets = getCellSets(solvingState);
return Strategy.map(
stepOfCell(cellSets),
stepOfCell,
Strategy.tryEach(cellSets.map(getSingleCellIn))
);
}
@ -16,27 +18,25 @@ function find(zones, lines) {
function getSingleCellIn(cellSet) {
return function() {
if(cellSet.size() == 1) {
return cellSet.getAll(function(v) {return v;})[0];
return cellSet.toList()[0];
}
};
}
function stepOfCell(cellSets) {
return function(cell) {
function stepOfCell(cell) {
return {
reason: 'singleCell',
empty: toEmpty(cell).intersection(cellSets),
star: CellSet.cells([cell])
};
empty: toEmpty(cell),
star: new CellSet.CellSet(cell)
};
}
function toEmpty(cell) {
var around = CellSet.rectangle(plus(cell, diagonal(-1)), diagonal(2));
around.remove(v);
return CellSet.union([
around,
CellSet.row(v.getRow()),
CellSet.column(v.getColumn())
var union = CellSet.union([
CellSet.rectangle(plus(cell, diagonal(-1)), diagonal(3)),
CellSet.row(getRow(cell)),
CellSet.column(getColumn(cell))
]);
union.remove(cell);
return union;
}

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