@logic-pad/core 0.4.6 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/assets/logic-core.global.d.ts +134 -25
  2. package/dist/data/grid.d.ts +44 -14
  3. package/dist/data/grid.js +43 -36
  4. package/dist/data/primitives.d.ts +19 -1
  5. package/dist/data/primitives.js +20 -0
  6. package/dist/data/rules/banPatternRule.js +1 -1
  7. package/dist/data/rules/customRule.js +1 -1
  8. package/dist/data/rules/lyingSymbolRule.d.ts +30 -0
  9. package/dist/data/rules/lyingSymbolRule.js +239 -0
  10. package/dist/data/rules/musicGridRule.js +1 -1
  11. package/dist/data/rules/mysteryRule.js +2 -2
  12. package/dist/data/rules/offByXRule.d.ts +1 -1
  13. package/dist/data/rules/offByXRule.js +7 -3
  14. package/dist/data/rules/regionAreaRule.js +3 -3
  15. package/dist/data/rules/rules.gen.d.ts +1 -0
  16. package/dist/data/rules/rules.gen.js +1 -0
  17. package/dist/data/serializer/serializer_v0.js +1 -1
  18. package/dist/data/solver/allSolvers.js +2 -2
  19. package/dist/data/solver/backtrack/backtrackSolver.d.ts +3 -4
  20. package/dist/data/solver/backtrack/backtrackSolver.js +4 -30
  21. package/dist/data/solver/backtrack/backtrackWorker.d.ts +1 -2
  22. package/dist/data/solver/backtrack/backtrackWorker.js +12 -8
  23. package/dist/data/solver/eventIteratingSolver.d.ts +6 -0
  24. package/dist/data/solver/eventIteratingSolver.js +33 -0
  25. package/dist/data/solver/solver.d.ts +6 -1
  26. package/dist/data/solver/solver.js +2 -1
  27. package/dist/data/solver/universal/universalSolver.d.ts +7 -0
  28. package/dist/data/solver/universal/universalSolver.js +30 -0
  29. package/dist/data/solver/universal/universalWorker.d.ts +1 -0
  30. package/dist/data/solver/universal/universalWorker.js +119 -0
  31. package/dist/data/symbols/customIconSymbol.js +2 -2
  32. package/dist/data/symbols/customTextSymbol.js +2 -2
  33. package/dist/data/validate.d.ts +1 -1
  34. package/dist/data/validate.js +3 -3
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.js +4 -2
  37. package/package.json +1 -1
  38. package/dist/data/solver/underclued/undercluedSolver.d.ts +0 -8
  39. package/dist/data/solver/underclued/undercluedSolver.js +0 -55
  40. package/dist/data/solver/underclued/undercluedWorker.d.ts +0 -2
  41. package/dist/data/solver/underclued/undercluedWorker.js +0 -135
@@ -0,0 +1,119 @@
1
+ import { Color, State } from '../../primitives.js';
2
+ import { Serializer } from '../../serializer/allSerializers.js';
3
+ import { instance as undercluedInstance } from '../../rules/undercluedRule.js';
4
+ import { array } from '../../dataHelper.js';
5
+ import validateGrid from '../../validate.js';
6
+ function gridToRawTiles(grid) {
7
+ return array(grid.width, grid.height, (x, y) => grid.getTile(x, y).color);
8
+ }
9
+ function rawTilesToGrid(rawTiles, grid) {
10
+ return grid.fastCopyWith({
11
+ tiles: array(grid.width, grid.height, (x, y) => grid.getTile(x, y).withColor(rawTiles[y][x])),
12
+ });
13
+ }
14
+ function getNextTile(grid, rawTiles) {
15
+ for (let y = 0; y < grid.height; y++) {
16
+ for (let x = 0; x < grid.width; x++) {
17
+ const tile = grid.getTile(x, y);
18
+ if (!tile.exists || tile.fixed)
19
+ continue;
20
+ if (rawTiles[y][x] === Color.Gray)
21
+ return [{ x, y }, Color.Dark];
22
+ }
23
+ }
24
+ return undefined;
25
+ }
26
+ function backtrack(grid, rawTiles, submitSolution) {
27
+ // Find the best empty cell to guess
28
+ const target = getNextTile(grid, rawTiles);
29
+ // Found a solution
30
+ if (!target)
31
+ return !submitSolution(rawTiles);
32
+ const [pos, color] = target;
33
+ const positions = grid.connections.getConnectedTiles(pos);
34
+ for (let i = 0; i <= 1; i++) {
35
+ const tile = i === 0 ? color : color === Color.Dark ? Color.Light : Color.Dark;
36
+ positions.forEach(({ x, y }) => (rawTiles[y][x] = tile));
37
+ const newGrid = rawTilesToGrid(rawTiles, grid);
38
+ const isValid = validateGrid(newGrid, null);
39
+ if (isValid.final !== State.Error &&
40
+ backtrack(newGrid, rawTiles, submitSolution))
41
+ return true;
42
+ }
43
+ positions.forEach(({ x, y }) => (rawTiles[y][x] = Color.Gray));
44
+ return false;
45
+ }
46
+ function solveNormal(input, submitSolution) {
47
+ // Call backtrack
48
+ backtrack(input, gridToRawTiles(input), rawTiles => submitSolution(rawTiles ? rawTilesToGrid(rawTiles, input) : null));
49
+ }
50
+ function solveUnderclued(input) {
51
+ let grid = input;
52
+ const possibles = array(grid.width, grid.height, () => ({
53
+ dark: false,
54
+ light: false,
55
+ }));
56
+ function search(x, y, tile, color) {
57
+ const newGrid = grid.fastCopyWith({
58
+ tiles: grid.setTile(x, y, tile.withColor(color)),
59
+ });
60
+ // Solve
61
+ let solution;
62
+ solveNormal(newGrid, sol => {
63
+ solution = sol;
64
+ return false;
65
+ });
66
+ if (!solution)
67
+ return false;
68
+ // Update the new possible states
69
+ solution.forEach((solTile, solX, solY) => {
70
+ if (solTile.color === Color.Dark) {
71
+ possibles[solY][solX].dark = true;
72
+ }
73
+ else {
74
+ possibles[solY][solX].light = true;
75
+ }
76
+ });
77
+ return true;
78
+ }
79
+ for (let y = 0; y < grid.height; y++) {
80
+ for (let x = 0; x < grid.width; x++) {
81
+ const tile = grid.getTile(x, y);
82
+ if (!tile.exists || tile.color !== Color.Gray)
83
+ continue;
84
+ // We can skip this solve if it is proved to be solvable
85
+ const darkPossible = possibles[y][x].dark || search(x, y, tile, Color.Dark);
86
+ const lightPossible = possibles[y][x].light || search(x, y, tile, Color.Light);
87
+ // No solution
88
+ if (!darkPossible && !lightPossible)
89
+ return null;
90
+ if (darkPossible && !lightPossible)
91
+ grid = grid.fastCopyWith({
92
+ tiles: grid.setTile(x, y, tile.withColor(Color.Dark)),
93
+ });
94
+ if (!darkPossible && lightPossible)
95
+ grid = grid.fastCopyWith({
96
+ tiles: grid.setTile(x, y, tile.withColor(Color.Light)),
97
+ });
98
+ }
99
+ }
100
+ return grid;
101
+ }
102
+ function solve(grid, submitSolution) {
103
+ if (grid.findRule(rule => rule.id === undercluedInstance.id)) {
104
+ submitSolution(solveUnderclued(grid));
105
+ }
106
+ else {
107
+ solveNormal(grid, submitSolution);
108
+ }
109
+ }
110
+ onmessage = e => {
111
+ const grid = Serializer.parseGrid(e.data);
112
+ let count = 0;
113
+ solve(grid, solution => {
114
+ postMessage(solution ? Serializer.stringifyGrid(solution) : null);
115
+ count += 1;
116
+ return count < 2;
117
+ });
118
+ postMessage(null);
119
+ };
@@ -49,7 +49,7 @@ Object.defineProperty(CustomIconSymbol, "EXAMPLE_GRID", {
49
49
  enumerable: true,
50
50
  configurable: true,
51
51
  writable: true,
52
- value: Object.freeze(new GridData(5, 4))
52
+ value: Object.freeze(GridData.create(5, 4))
53
53
  });
54
54
  Object.defineProperty(CustomIconSymbol, "CONFIGS", {
55
55
  enumerable: true,
@@ -102,4 +102,4 @@ Object.defineProperty(CustomIconSymbol, "CONFIGS", {
102
102
  ])
103
103
  });
104
104
  export default CustomIconSymbol;
105
- export const instance = new CustomIconSymbol('A *custom* icon symbol', new GridData(5, 4), 0, 0, 'MdQuestionMark');
105
+ export const instance = new CustomIconSymbol('A *custom* icon symbol', GridData.create(5, 4), 0, 0, 'MdQuestionMark');
@@ -49,7 +49,7 @@ Object.defineProperty(CustomTextSymbol, "EXAMPLE_GRID", {
49
49
  enumerable: true,
50
50
  configurable: true,
51
51
  writable: true,
52
- value: Object.freeze(new GridData(5, 4))
52
+ value: Object.freeze(GridData.create(5, 4))
53
53
  });
54
54
  Object.defineProperty(CustomTextSymbol, "CONFIGS", {
55
55
  enumerable: true,
@@ -103,4 +103,4 @@ Object.defineProperty(CustomTextSymbol, "CONFIGS", {
103
103
  ])
104
104
  });
105
105
  export default CustomTextSymbol;
106
- export const instance = new CustomTextSymbol('A *custom* text symbol', new GridData(5, 4), 0, 0, 'X');
106
+ export const instance = new CustomTextSymbol('A *custom* text symbol', GridData.create(5, 4), 0, 0, 'X');
@@ -1,5 +1,5 @@
1
1
  import GridData from './grid.js';
2
2
  import { GridState, RuleState, State } from './primitives.js';
3
- export declare function aggregateState(rules: RuleState[], grid: GridData, symbols: Map<string, State[]>): State;
3
+ export declare function aggregateState(rules: readonly RuleState[], grid: GridData, symbols: ReadonlyMap<string, State[]>): State.Error | State.Satisfied | State.Incomplete;
4
4
  export declare function applyFinalOverrides(grid: GridData, solution: GridData | null, state: GridState): GridState;
5
5
  export default function validateGrid(grid: GridData, solution: GridData | null): GridState;
@@ -72,18 +72,18 @@ export default function validateGrid(grid, solution) {
72
72
  return;
73
73
  if (states.some(s => s === State.Error))
74
74
  ruleStates[i] = { state: State.Error, positions: [] };
75
- else if (states.length > 0 && states.every(s => s === State.Satisfied))
75
+ else if (states.length > 0 && states.every(s => State.isSatisfied(s)))
76
76
  ruleStates[i] = { state: State.Satisfied };
77
77
  });
78
78
  let final = aggregateState(ruleStates, grid, symbolStates);
79
79
  // in addition to satisfying all rules and symbols, a solution must also fill the grid completely
80
- if (!requireSolution && final === State.Satisfied) {
80
+ if (!requireSolution && State.isSatisfied(final)) {
81
81
  final = grid.forEach(tile => tile.exists && tile.color === Color.Gray ? true : undefined)
82
82
  ? State.Incomplete
83
83
  : State.Satisfied;
84
84
  }
85
85
  // return early if there is no need to validate against a solution
86
- if (final === State.Satisfied ||
86
+ if (State.isSatisfied(final) ||
87
87
  !requireSolution ||
88
88
  !solution ||
89
89
  solution.width !== grid.width ||
package/dist/index.d.ts CHANGED
@@ -22,6 +22,7 @@ import ConnectAllRule from './data/rules/connectAllRule.js';
22
22
  import CustomRule from './data/rules/customRule.js';
23
23
  import ForesightRule from './data/rules/foresightRule.js';
24
24
  import { allRules } from './data/rules/index.js';
25
+ import LyingSymbolRule from './data/rules/lyingSymbolRule.js';
25
26
  import { ControlLine, Row } from './data/rules/musicControlLine.js';
26
27
  import MusicGridRule from './data/rules/musicGridRule.js';
27
28
  import MysteryRule from './data/rules/mysteryRule.js';
@@ -63,8 +64,9 @@ import LotusBTModule from './data/solver/backtrack/symbols/lotus.js';
63
64
  import MinesweeperBTModule from './data/solver/backtrack/symbols/minesweeper.js';
64
65
  import MyopiaBTModule from './data/solver/backtrack/symbols/myopia.js';
65
66
  import ViewpointBTModule from './data/solver/backtrack/symbols/viewpoint.js';
67
+ import EventIteratingSolver from './data/solver/eventIteratingSolver.js';
66
68
  import Solver from './data/solver/solver.js';
67
- import UndercluedSolver from './data/solver/underclued/undercluedSolver.js';
69
+ import UniversalSolver from './data/solver/universal/universalSolver.js';
68
70
  import AreaNumberModule from './data/solver/z3/modules/areaNumberModule.js';
69
71
  import CellCountModule from './data/solver/z3/modules/cellCountModule.js';
70
72
  import ConnectAllModule from './data/solver/z3/modules/connectAllModule.js';
@@ -98,4 +100,4 @@ import ViewpointSymbol from './data/symbols/viewpointSymbol.js';
98
100
  import TileData from './data/tile.js';
99
101
  import TileConnections from './data/tileConnections.js';
100
102
  import validateGrid, { aggregateState, applyFinalOverrides } from './data/validate.js';
101
- export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGridChange, handlesGridResize, handlesSetGrid, invokeSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, GridZones, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, Serializer, Compressor, CompressorBase, DeflateCompressor, GzipCompressor, StreamCompressor, SerializerBase, SerializerV0, getShapeVariants, normalizeShape, positionsToShape, shapeEquals, tilesToShape, allSolvers, BacktrackSolver, BTModule, BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor, BanPatternBTModule, CellCountBTModule, ConnectAllBTModule, RegionAreaBTModule, RegionShapeBTModule, SameShapeBTModule, SymbolsPerRegionBTModule, UniqueShapeBTModule, AreaNumberBTModule, DartBTModule, DirectionLinkerBTModule, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, Solver, UndercluedSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
103
+ export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGridChange, handlesGridResize, handlesSetGrid, invokeSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, GridZones, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, LyingSymbolRule, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, Serializer, Compressor, CompressorBase, DeflateCompressor, GzipCompressor, StreamCompressor, SerializerBase, SerializerV0, getShapeVariants, normalizeShape, positionsToShape, shapeEquals, tilesToShape, allSolvers, BacktrackSolver, BTModule, BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor, BanPatternBTModule, CellCountBTModule, ConnectAllBTModule, RegionAreaBTModule, RegionShapeBTModule, SameShapeBTModule, SymbolsPerRegionBTModule, UniqueShapeBTModule, AreaNumberBTModule, DartBTModule, DirectionLinkerBTModule, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, EventIteratingSolver, Solver, UniversalSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ import ConnectAllRule from './data/rules/connectAllRule.js';
25
25
  import CustomRule from './data/rules/customRule.js';
26
26
  import ForesightRule from './data/rules/foresightRule.js';
27
27
  import { allRules } from './data/rules/index.js';
28
+ import LyingSymbolRule from './data/rules/lyingSymbolRule.js';
28
29
  import { ControlLine, Row } from './data/rules/musicControlLine.js';
29
30
  import MusicGridRule from './data/rules/musicGridRule.js';
30
31
  import MysteryRule from './data/rules/mysteryRule.js';
@@ -66,8 +67,9 @@ import LotusBTModule from './data/solver/backtrack/symbols/lotus.js';
66
67
  import MinesweeperBTModule from './data/solver/backtrack/symbols/minesweeper.js';
67
68
  import MyopiaBTModule from './data/solver/backtrack/symbols/myopia.js';
68
69
  import ViewpointBTModule from './data/solver/backtrack/symbols/viewpoint.js';
70
+ import EventIteratingSolver from './data/solver/eventIteratingSolver.js';
69
71
  import Solver from './data/solver/solver.js';
70
- import UndercluedSolver from './data/solver/underclued/undercluedSolver.js';
72
+ import UniversalSolver from './data/solver/universal/universalSolver.js';
71
73
  import AreaNumberModule from './data/solver/z3/modules/areaNumberModule.js';
72
74
  import CellCountModule from './data/solver/z3/modules/cellCountModule.js';
73
75
  import ConnectAllModule from './data/solver/z3/modules/connectAllModule.js';
@@ -101,4 +103,4 @@ import ViewpointSymbol from './data/symbols/viewpointSymbol.js';
101
103
  import TileData from './data/tile.js';
102
104
  import TileConnections from './data/tileConnections.js';
103
105
  import validateGrid, { aggregateState, applyFinalOverrides } from './data/validate.js';
104
- export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGridChange, handlesGridResize, handlesSetGrid, invokeSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, GridZones, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, Serializer, Compressor, CompressorBase, DeflateCompressor, GzipCompressor, StreamCompressor, SerializerBase, SerializerV0, getShapeVariants, normalizeShape, positionsToShape, shapeEquals, tilesToShape, allSolvers, BacktrackSolver, BTModule, BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor, BanPatternBTModule, CellCountBTModule, ConnectAllBTModule, RegionAreaBTModule, RegionShapeBTModule, SameShapeBTModule, SymbolsPerRegionBTModule, UniqueShapeBTModule, AreaNumberBTModule, DartBTModule, DirectionLinkerBTModule, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, Solver, UndercluedSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
106
+ export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGridChange, handlesGridResize, handlesSetGrid, invokeSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, GridZones, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, LyingSymbolRule, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, Serializer, Compressor, CompressorBase, DeflateCompressor, GzipCompressor, StreamCompressor, SerializerBase, SerializerV0, getShapeVariants, normalizeShape, positionsToShape, shapeEquals, tilesToShape, allSolvers, BacktrackSolver, BTModule, BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor, BanPatternBTModule, CellCountBTModule, ConnectAllBTModule, RegionAreaBTModule, RegionShapeBTModule, SameShapeBTModule, SymbolsPerRegionBTModule, UniqueShapeBTModule, AreaNumberBTModule, DartBTModule, DirectionLinkerBTModule, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, EventIteratingSolver, Solver, UniversalSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logic-pad/core",
3
- "version": "0.4.6",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -1,8 +0,0 @@
1
- import GridData from '../../grid.js';
2
- import Solver from '../solver.js';
3
- export default class UndercluedSolver extends Solver {
4
- readonly id = "underclued";
5
- readonly description = "Solves every puzzle as if it were underclued. Supports all rules and symbols and is decently fast for small puzzles. Very slow for large puzzles.";
6
- solve(grid: GridData): AsyncGenerator<GridData | null>;
7
- isInstructionSupported(instructionId: string): boolean;
8
- }
@@ -1,55 +0,0 @@
1
- import { Color } from '../../primitives.js';
2
- import { instance as undercluedInstance } from '../../rules/undercluedRule.js';
3
- import { Serializer } from '../../serializer/allSerializers.js';
4
- import Solver from '../solver.js';
5
- export default class UndercluedSolver extends Solver {
6
- constructor() {
7
- super(...arguments);
8
- Object.defineProperty(this, "id", {
9
- enumerable: true,
10
- configurable: true,
11
- writable: true,
12
- value: 'underclued'
13
- });
14
- Object.defineProperty(this, "description", {
15
- enumerable: true,
16
- configurable: true,
17
- writable: true,
18
- value: 'Solves every puzzle as if it were underclued. Supports all rules and symbols and is decently fast for small puzzles. Very slow for large puzzles.'
19
- });
20
- }
21
- async *solve(grid) {
22
- const worker = new Worker(new URL('./undercluedWorker.js', import.meta.url), {
23
- type: 'module',
24
- });
25
- try {
26
- const solved = await new Promise(resolve => {
27
- worker.addEventListener('message', e => {
28
- const solution = Serializer.parseGrid(e.data);
29
- // console.timeEnd('Solve time');
30
- if (solution.resetTiles().equals(solution))
31
- resolve(null);
32
- else
33
- resolve(solution);
34
- });
35
- worker.postMessage(Serializer.stringifyGrid(grid));
36
- // console.time('Solve time');
37
- });
38
- yield solved;
39
- if (solved) {
40
- if (solved.getTileCount(true, undefined, Color.Gray) === 0) {
41
- yield null; // the grid is completely filled, which means the solution is unique
42
- }
43
- }
44
- }
45
- finally {
46
- worker.terminate();
47
- }
48
- }
49
- isInstructionSupported(instructionId) {
50
- if (super.isInstructionSupported(instructionId)) {
51
- return true;
52
- }
53
- return instructionId === undercluedInstance.id;
54
- }
55
- }
@@ -1,2 +0,0 @@
1
- declare const _default: null;
2
- export default _default;
@@ -1,135 +0,0 @@
1
- import { Color, State } from '../../primitives.js';
2
- import { Serializer } from '../../serializer/allSerializers.js';
3
- import validateGrid from '../../validate.js';
4
- function posToCoords(pos, width) {
5
- if (pos === undefined) {
6
- throw new Error('pos is undefined');
7
- }
8
- return [pos % width, Math.floor(pos / width)];
9
- }
10
- function coordsToPos(a, width) {
11
- return a[0] + a[1] * width;
12
- }
13
- function getValidGrid(grid, assumptions, canAssump) {
14
- while (true) {
15
- // Get assumption
16
- const newAssump = canAssump.findIndex((a, i) => a && !assumptions.includes(i));
17
- if (newAssump === -1) {
18
- return [grid, assumptions, true];
19
- }
20
- // Set assumption's color to dark
21
- const coords = posToCoords(newAssump, grid.width);
22
- grid = grid.setTile(coords[0], coords[1], tile => tile.withColor(Color.Dark));
23
- assumptions.push(newAssump);
24
- for (const a of grid.connections.getConnectedTiles({
25
- x: coords[0],
26
- y: coords[1],
27
- })) {
28
- canAssump[coordsToPos([a.x, a.y], grid.width)] =
29
- a.x === coords[0] && a.y === coords[1];
30
- }
31
- const state = validateGrid(grid, null);
32
- // If the grid is invalid, try to backtrack to a right assumption
33
- if (state.final === State.Error) {
34
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
35
- [grid, assumptions] = tryToBacktrack(grid, assumptions);
36
- if (assumptions.length === 0) {
37
- return [grid, assumptions, false];
38
- }
39
- }
40
- }
41
- }
42
- function tryToBacktrack(grid, assumptions) {
43
- while (assumptions.length > 0) {
44
- const coords = posToCoords(assumptions[assumptions.length - 1], grid.width);
45
- if (grid.getTile(coords[0], coords[1]).color === Color.Light) {
46
- grid = grid.setTile(coords[0], coords[1], tile => tile.withColor(Color.Gray));
47
- assumptions.pop();
48
- }
49
- else {
50
- grid = grid.setTile(coords[0], coords[1], tile => tile.withColor(Color.Light));
51
- const state = validateGrid(grid, null);
52
- if (state.final === State.Error) {
53
- grid = grid.setTile(coords[0], coords[1], tile => tile.withColor(Color.Gray));
54
- assumptions.pop();
55
- }
56
- else {
57
- return [grid, assumptions];
58
- }
59
- }
60
- }
61
- return [grid, assumptions];
62
- }
63
- function computeSolution(initialGrid) {
64
- const canAssump = initialGrid.tiles
65
- .map(row => row.map(t => t.exists && !t.fixed))
66
- .flat();
67
- let lastValidGrid = [];
68
- let assumptions = [];
69
- let currentGrid = initialGrid.copyWith({});
70
- let anyNewGrid;
71
- while (assumptions.length > 0 || lastValidGrid.length === 0) {
72
- [currentGrid, assumptions, anyNewGrid] = getValidGrid(currentGrid, assumptions, canAssump);
73
- // console.log(
74
- // currentGrid.tiles
75
- // .map(row =>
76
- // row
77
- // .map(t => {
78
- // const color = t.color === Color.Light ? 'w' : 'b';
79
- // if (t.color === Color.Gray) return 'n';
80
- // if (!t.exists) return '.';
81
- // return t.fixed ? color.toUpperCase() : color;
82
- // })
83
- // .join('')
84
- // )
85
- // .join('\n')
86
- // );
87
- if (!anyNewGrid) {
88
- break;
89
- }
90
- const newLastValidGrid = currentGrid.tiles
91
- .map(row => row.map(t => t.color))
92
- .flat();
93
- if (lastValidGrid.length !== 0) {
94
- const diff = newLastValidGrid.map((color, i) => color === lastValidGrid[i]);
95
- diff.forEach((same, i) => {
96
- if (!same) {
97
- newLastValidGrid[i] = Color.Gray;
98
- }
99
- });
100
- }
101
- [currentGrid, assumptions] = tryToBacktrack(currentGrid, assumptions);
102
- lastValidGrid = newLastValidGrid;
103
- }
104
- // Create a new grid with lastValidGrid
105
- let solutionGrid = initialGrid.copyWith({});
106
- lastValidGrid.forEach((color, i) => {
107
- const coords = posToCoords(i, solutionGrid.width);
108
- solutionGrid = solutionGrid.setTile(coords[0], coords[1], tile => tile.withColor(color));
109
- });
110
- // console.log(
111
- // solutionGrid.tiles
112
- // .map(row =>
113
- // row
114
- // .map(t => {
115
- // const color = t.color === Color.Light ? 'w' : 'b';
116
- // if (t.color === Color.Gray) return 'n';
117
- // if (!t.exists) return '.';
118
- // return t.fixed ? color.toUpperCase() : color;
119
- // })
120
- // .join('')
121
- // )
122
- // .join('\n')
123
- // );
124
- return solutionGrid;
125
- }
126
- onmessage = e => {
127
- if (!e.data || typeof e.data !== 'string')
128
- return;
129
- const grid = Serializer.parseGrid(e.data);
130
- const solved = computeSolution(grid);
131
- postMessage(Serializer.stringifyGrid(solved));
132
- };
133
- // make typescript happy
134
- // eslint-disable-next-line import/no-anonymous-default-export
135
- export default null;