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 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) {
return Strategy.map( var inclusion = findInclusion(cellDimensionsByname(solvingState));
stepOfInclusion, return Strategy.tryEach([
Strategy.tryEach([ inclusion('rows', 'colors'),
findInclusion(lines.rows, zones, getColor), inclusion('columns', 'colors'),
findInclusion(lines.columns, zones, getColor), inclusion('colors', 'rows'),
findInclusion(zones, lines.rows, getRow), inclusion('colors', 'columns')
findInclusion(zones, lines.columns, getColumn) ]);
])
);
} }
function findInclusion(subsets, supersets, property) { function cellDimensionsByname(solvingState) {
return Strategy.tryEach( return {
quotient(subsets.map(getClasses(property)), sameSet) rows: {sets: solvingState.rows, property: getRow},
.map(keepInclusion(subsets, supersets)) columns: {sets: solvingState.columns, property: getColumn},
); colors: {sets: solvingState.colorZones, property: solvingState.getColor}
};
} }
function keepInclusion(subsets, supersets) { function getAll(property) {
return function(set) { 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() { 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));
} }

View File

@ -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),
empty: toEmpty(cell).intersection(cellSets), star: new CellSet.CellSet(cell)
star: CellSet.cells([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
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);
}