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(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( 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; } } groups.push({value: set, indices: [i]}); }); return groups; }