Implement hypothesis solver (no recursivity yet); solves all known grids

This commit is contained in:
Tissevert 2022-10-23 23:13:49 +02:00
parent e8d0db8b1d
commit 42dc3e394c
6 changed files with 81 additions and 56 deletions

View file

@ -1,12 +1,13 @@
import * as Vector from Geometry.Vector;
return {
make: make,
at: at,
asAFunction: asAFunction,
column: column,
generate: generate,
iter: iter,
make: make,
map: map,
row: row,
set: set,
square: square

View file

@ -40,7 +40,9 @@ function applyStep(solvingState) {
console.log(step);
['empty', 'star'].forEach(function(attribute) {
if(step[attribute] != undefined) {
step[attribute].iter(State.setCell(solvingState, attribute == 'star'));
//step[attribute].iter(State.setCells(solvingState, attribute == 'star'));
State.setCells(solvingState, attribute == 'star', step[attribute]);
// ?? why is curryfication needed above ? State.setCells(solvingState, attribute == 'star', step[attribute]);
}
});
};

View file

@ -1,21 +1,44 @@
import perimeter from Solver.SingleCell;
import getRange from Solver.SingleCell;
import CellSet from Geometry.CellSet;
import * as State from Solver.State;
import * as Strategy from Solver.Strategy;
return {
find: find
};
function find(solvingState) {
solvingState.missing.map(f(solvingState))
};
return Strategy.tryEach(
solvingState.missing.map(findContradiction(solvingState))
);
}
function f(solvingState) {
function findContradiction(solvingState) {
return function(cell) {
return function() {
var forked = State.fork(solvingState);
State.set(forked, cell, true);
}
State.setCells(forked, false, getRange(forked, cell));
return getContradiction(solvingState, forked, cell);
};
};
}
function checkContradiction(beforeState, afterState, cell) {
//TODO has one cellSet (color, row, column) become empty ? if it doesn't contain cell, it's a contradiction
function stepOfContradiction(cell, name, i) {
var step = {
reason: 'noStarLeft',
empty: new CellSet(cell),
};
step['in_' + name] = i;
return step;
}
function getContradiction(beforeState, afterState, cell) {
for(var name in beforeState.zones) {
var zones = beforeState.zones[name];
for(var i = 0; i < zones.length; i++) {
if(zones[i].size() > 0 && afterState.zones[name][i].size() < 1) {
return stepOfContradiction(cell, name, i);
}
}
}
}

View file

@ -8,7 +8,7 @@ return {
};
function find(solvingState) {
var inclusion = findInclusion(cellDimensionsByname(solvingState));
var inclusion = findInclusion(cellDimensionsByName(solvingState));
return Strategy.tryEach([
inclusion('rows', 'colors'),
inclusion('columns', 'colors'),
@ -17,11 +17,11 @@ function find(solvingState) {
]);
}
function cellDimensionsByname(solvingState) {
function cellDimensionsByName(solvingState) {
return {
rows: {sets: solvingState.rows, property: getRow},
columns: {sets: solvingState.columns, property: getColumn},
colors: {sets: solvingState.colorZones, property: solvingState.getColor}
rows: {sets: solvingState.zones.rows, property: getRow},
columns: {sets: solvingState.zones.columns, property: getColumn},
colors: {sets: solvingState.zones.colors, property: solvingState.getColor}
};
}

View file

@ -1,16 +1,21 @@
import * as CellSet from Geometry.CellSet;
import * as Strategy from Solver.Strategy;
import * as State from Solver.State;
import {diagonal, getColumn, getRow, plus} from Geometry.Vector;
return {
find: find,
perimeter: perimeter
getRange: getRange
};
function find(solvingState) {
return Strategy.tryEach(
State.zoneNames(solvingState).map(function(name) {
return Strategy.map(
stepOfCell(solvingState.missing),
Strategy.tryEach(solvingState.colorZones.map(getSingleCellIn))
stepOfCell(solvingState, name),
Strategy.tryEach(solvingState.zones[name].map(getSingleCellIn))
);
})
);
}
@ -22,21 +27,24 @@ function getSingleCellIn(cellSet) {
};
}
function stepOfCell(missing) {
function stepOfCell(solvingState, name) {
return function(cell) {
return {
reason: 'singleCell',
empty: perimeter(cell).intersection(missing),
set: name,
empty: getRange(solvingState, cell),
star: new CellSet.CellSet(cell)
};
};
}
function perimeter(cell) {
function getRange(solvingState, cell) {
var union = CellSet.union([
CellSet.rectangle(plus(cell, diagonal(-1)), diagonal(3)),
CellSet.row(getRow(cell)),
CellSet.column(getColumn(cell))
solvingState.zones.colors[solvingState.getColor(cell)],
solvingState.zones.rows[getRow(cell)],
solvingState.zones.columns[getColumn(cell)],
CellSet.rectangle(plus(cell, diagonal(-1)), diagonal(3))
.intersection(solvingState.missing)
]);
union.remove(cell);
return union;

View file

@ -4,12 +4,11 @@ import {asAFunction, iter, map, set, square} from Grid.Util;
import {diagonal, zero} from Geometry.Vector;
import * as CellSet from Geometry.CellSet;
var zoneNames = ['colors', 'rows', 'columns'];
return {
setCell: setCell,
fork: fork,
setCells: setCells,
start: start,
fork: fork
zoneNames: zoneNames
};
function start(coloring) {
@ -39,9 +38,9 @@ function getColors(grid) {
function fork(state) {
var zones = {};
zoneNames.forEach(function(name) {
for(var name in state.zones) {
zones[name] = state.zones[name].map(function(s) {return s.copy();});
});
}
return {
constellation: map(state.constellation, id),
getColor: state.getColor,
@ -50,30 +49,22 @@ function fork(state) {
};
}
function setCells(solvingState, value) {
return function(cellSet) {
for(var i = 0; i < zoneNames.length; i++) {
for(var j = 0; j < size; j++) {
f(solvingState.zones[field][j], cellSet)
}
}
var field = zoneNames[i];
var zone = solvingState.zones[field][j];
if(zone.size() > 0) {
var diff =
});
solvingState.colorZones
.concat(solvingState.rows)
.concat(solvingState.columns)
.concat(solvingState.missing)
.forEach(function(cellSet) {cellSet.remove(cell);});
solvingState.missing
function setCells(solvingState, value, cellSet) {
var forgetList = allZones(solvingState).concat(solvingState.missing);
cellSet.iter(function(cell) {
set(solvingState.constellation, cell, value);
forgetList.forEach(function(solverSet) {
solverSet.remove(cell);
});
});
}
function f(zone, cellSet) {
if(zone.size() > 0) {
var diff = zone.difference(cellSet);
if(diff.
function zoneNames(solvingState) {
return Object.keys(solvingState.zones);
}
function allZones(solvingState) {
return zoneNames(solvingState).flatMap(function(name) {
return solvingState.zones[name];
});
}