Implement hypothesis solver (no recursivity yet); solves all known grids
This commit is contained in:
parent
e8d0db8b1d
commit
42dc3e394c
6 changed files with 81 additions and 56 deletions
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue