@logic-pad/core
Version:
60 lines (59 loc) • 2.14 kB
JavaScript
import Z3Module from './z3Module.js';
import { Point } from 'grilops';
import { instance as cellCountInstance, } from '../../../rules/cellCountRule.js';
import { Color } from '../../../primitives.js';
export default class CellCountModule extends Z3Module {
constructor() {
super(...arguments);
Object.defineProperty(this, "id", {
enumerable: true,
configurable: true,
writable: true,
value: cellCountInstance.id
});
}
encode(grid, ctx) {
const rules = grid.rules.filter(rule => rule.id === this.id);
// optimizations
if (rules.length === 0) {
return;
}
const colorMap = new Map();
for (const rule of rules) {
if (colorMap.has(rule.color)) {
if (colorMap.get(rule.color) !== rule.count) {
ctx.solver.add(ctx.ctx.Bool.val(false));
return;
}
}
else {
colorMap.set(rule.color, rule.count);
}
}
for (const [color, count] of colorMap.entries()) {
const { min, max } = grid.getColorCount(color);
if (min > count || max < count) {
ctx.solver.add(ctx.ctx.Bool.val(false));
return;
}
}
if (colorMap.has(Color.Light) && colorMap.has(Color.Dark)) {
if (colorMap.get(Color.Light) + colorMap.get(Color.Dark) !==
grid.getTileCount(true)) {
ctx.solver.add(ctx.ctx.Bool.val(false));
return;
}
}
// encode for real
for (const [color, count] of colorMap.entries()) {
const sumTerms = [];
grid.forEach((tile, x, y) => {
if (tile.exists) {
sumTerms.push(ctx.ctx.If(ctx.grid.cellAt(new Point(y, x)).eq(ctx.symbolSet.indices[color]), 1, 0));
}
});
ctx.solver.add(ctx.ctx.Sum(sumTerms[0], ...sumTerms.slice(1)).eq(count));
}
}
}
export const instance = new CellCountModule();