@logic-pad/core 0.1.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 (211) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +19 -0
  3. package/assets/logic-core.global.d.ts +5865 -0
  4. package/assets/z3-built.js +14723 -0
  5. package/assets/z3-built.wasm +0 -0
  6. package/assets/z3-built.worker.js +206 -0
  7. package/dist/data/config.d.ts +101 -0
  8. package/dist/data/config.js +55 -0
  9. package/dist/data/configurable.d.ts +12 -0
  10. package/dist/data/configurable.js +26 -0
  11. package/dist/data/dataHelper.d.ts +77 -0
  12. package/dist/data/dataHelper.js +190 -0
  13. package/dist/data/events/eventHelper.d.ts +1 -0
  14. package/dist/data/events/eventHelper.js +6 -0
  15. package/dist/data/events/onFinalValidation.d.ts +14 -0
  16. package/dist/data/events/onFinalValidation.js +4 -0
  17. package/dist/data/events/onGridChange.d.ts +6 -0
  18. package/dist/data/events/onGridChange.js +4 -0
  19. package/dist/data/events/onGridResize.d.ts +9 -0
  20. package/dist/data/events/onGridResize.js +4 -0
  21. package/dist/data/events/onSetGrid.d.ts +6 -0
  22. package/dist/data/events/onSetGrid.js +4 -0
  23. package/dist/data/events/onSymbolValidation.d.ts +18 -0
  24. package/dist/data/events/onSymbolValidation.js +4 -0
  25. package/dist/data/grid.d.ts +362 -0
  26. package/dist/data/grid.js +886 -0
  27. package/dist/data/gridConnections.d.ts +38 -0
  28. package/dist/data/gridConnections.js +328 -0
  29. package/dist/data/instruction.d.ts +19 -0
  30. package/dist/data/instruction.js +23 -0
  31. package/dist/data/primitives.d.ts +85 -0
  32. package/dist/data/primitives.js +90 -0
  33. package/dist/data/puzzle.d.ts +86 -0
  34. package/dist/data/puzzle.js +22 -0
  35. package/dist/data/rules/banPatternRule.d.ts +29 -0
  36. package/dist/data/rules/banPatternRule.js +133 -0
  37. package/dist/data/rules/cellCountRule.d.ts +32 -0
  38. package/dist/data/rules/cellCountRule.js +166 -0
  39. package/dist/data/rules/completePatternRule.d.ts +22 -0
  40. package/dist/data/rules/completePatternRule.js +53 -0
  41. package/dist/data/rules/connectAllRule.d.ts +28 -0
  42. package/dist/data/rules/connectAllRule.js +113 -0
  43. package/dist/data/rules/customRule.d.ts +32 -0
  44. package/dist/data/rules/customRule.js +92 -0
  45. package/dist/data/rules/foresightRule.d.ts +30 -0
  46. package/dist/data/rules/foresightRule.js +107 -0
  47. package/dist/data/rules/index.d.ts +3 -0
  48. package/dist/data/rules/index.js +10 -0
  49. package/dist/data/rules/musicControlLine.d.ts +64 -0
  50. package/dist/data/rules/musicControlLine.js +178 -0
  51. package/dist/data/rules/musicGridRule.d.ts +46 -0
  52. package/dist/data/rules/musicGridRule.js +211 -0
  53. package/dist/data/rules/mysteryRule.d.ts +37 -0
  54. package/dist/data/rules/mysteryRule.js +164 -0
  55. package/dist/data/rules/offByXRule.d.ts +30 -0
  56. package/dist/data/rules/offByXRule.js +134 -0
  57. package/dist/data/rules/regionAreaRule.d.ts +33 -0
  58. package/dist/data/rules/regionAreaRule.js +182 -0
  59. package/dist/data/rules/regionShapeRule.d.ts +22 -0
  60. package/dist/data/rules/regionShapeRule.js +58 -0
  61. package/dist/data/rules/rule.d.ts +18 -0
  62. package/dist/data/rules/rule.js +19 -0
  63. package/dist/data/rules/rules.gen.d.ts +14 -0
  64. package/dist/data/rules/rules.gen.js +18 -0
  65. package/dist/data/rules/sameShapeRule.d.ts +27 -0
  66. package/dist/data/rules/sameShapeRule.js +88 -0
  67. package/dist/data/rules/symbolsPerRegionRule.d.ts +37 -0
  68. package/dist/data/rules/symbolsPerRegionRule.js +211 -0
  69. package/dist/data/rules/undercluedRule.d.ts +22 -0
  70. package/dist/data/rules/undercluedRule.js +60 -0
  71. package/dist/data/rules/uniqueShapeRule.d.ts +27 -0
  72. package/dist/data/rules/uniqueShapeRule.js +85 -0
  73. package/dist/data/serializer/allSerializers.d.ts +30 -0
  74. package/dist/data/serializer/allSerializers.js +64 -0
  75. package/dist/data/serializer/compressor/allCompressors.d.ts +14 -0
  76. package/dist/data/serializer/compressor/allCompressors.js +43 -0
  77. package/dist/data/serializer/compressor/compressorBase.d.ts +16 -0
  78. package/dist/data/serializer/compressor/compressorBase.js +2 -0
  79. package/dist/data/serializer/compressor/deflateCompressor.d.ts +7 -0
  80. package/dist/data/serializer/compressor/deflateCompressor.js +17 -0
  81. package/dist/data/serializer/compressor/gzipCompressor.d.ts +5 -0
  82. package/dist/data/serializer/compressor/gzipCompressor.js +9 -0
  83. package/dist/data/serializer/compressor/streamCompressor.d.ts +6 -0
  84. package/dist/data/serializer/compressor/streamCompressor.js +36 -0
  85. package/dist/data/serializer/serializerBase.d.ts +27 -0
  86. package/dist/data/serializer/serializerBase.js +2 -0
  87. package/dist/data/serializer/serializer_v0.d.ts +36 -0
  88. package/dist/data/serializer/serializer_v0.js +426 -0
  89. package/dist/data/shapes.d.ts +17 -0
  90. package/dist/data/shapes.js +117 -0
  91. package/dist/data/solver/allSolvers.d.ts +3 -0
  92. package/dist/data/solver/allSolvers.js +11 -0
  93. package/dist/data/solver/backtrack/backtrackSolver.d.ts +9 -0
  94. package/dist/data/solver/backtrack/backtrackSolver.js +92 -0
  95. package/dist/data/solver/backtrack/backtrackWorker.d.ts +2 -0
  96. package/dist/data/solver/backtrack/backtrackWorker.js +295 -0
  97. package/dist/data/solver/backtrack/data.d.ts +46 -0
  98. package/dist/data/solver/backtrack/data.js +140 -0
  99. package/dist/data/solver/backtrack/rules/banPattern.d.ts +9 -0
  100. package/dist/data/solver/backtrack/rules/banPattern.js +66 -0
  101. package/dist/data/solver/backtrack/rules/cellCount.d.ts +7 -0
  102. package/dist/data/solver/backtrack/rules/cellCount.js +30 -0
  103. package/dist/data/solver/backtrack/rules/connectAll.d.ts +7 -0
  104. package/dist/data/solver/backtrack/rules/connectAll.js +49 -0
  105. package/dist/data/solver/backtrack/rules/regionArea.d.ts +8 -0
  106. package/dist/data/solver/backtrack/rules/regionArea.js +76 -0
  107. package/dist/data/solver/backtrack/rules/regionShape.d.ts +8 -0
  108. package/dist/data/solver/backtrack/rules/regionShape.js +62 -0
  109. package/dist/data/solver/backtrack/rules/sameShape.d.ts +8 -0
  110. package/dist/data/solver/backtrack/rules/sameShape.js +19 -0
  111. package/dist/data/solver/backtrack/rules/symbolsPerRegion.d.ts +10 -0
  112. package/dist/data/solver/backtrack/rules/symbolsPerRegion.js +92 -0
  113. package/dist/data/solver/backtrack/rules/uniqueShape.d.ts +8 -0
  114. package/dist/data/solver/backtrack/rules/uniqueShape.js +19 -0
  115. package/dist/data/solver/backtrack/symbols/areaNumber.d.ts +9 -0
  116. package/dist/data/solver/backtrack/symbols/areaNumber.js +77 -0
  117. package/dist/data/solver/backtrack/symbols/dart.d.ts +9 -0
  118. package/dist/data/solver/backtrack/symbols/dart.js +58 -0
  119. package/dist/data/solver/backtrack/symbols/directionLinker.d.ts +9 -0
  120. package/dist/data/solver/backtrack/symbols/directionLinker.js +50 -0
  121. package/dist/data/solver/backtrack/symbols/galaxy.d.ts +9 -0
  122. package/dist/data/solver/backtrack/symbols/galaxy.js +19 -0
  123. package/dist/data/solver/backtrack/symbols/letter.d.ts +9 -0
  124. package/dist/data/solver/backtrack/symbols/letter.js +100 -0
  125. package/dist/data/solver/backtrack/symbols/lotus.d.ts +9 -0
  126. package/dist/data/solver/backtrack/symbols/lotus.js +36 -0
  127. package/dist/data/solver/backtrack/symbols/minesweeper.d.ts +9 -0
  128. package/dist/data/solver/backtrack/symbols/minesweeper.js +55 -0
  129. package/dist/data/solver/backtrack/symbols/myopia.d.ts +7 -0
  130. package/dist/data/solver/backtrack/symbols/myopia.js +79 -0
  131. package/dist/data/solver/backtrack/symbols/viewpoint.d.ts +7 -0
  132. package/dist/data/solver/backtrack/symbols/viewpoint.js +56 -0
  133. package/dist/data/solver/solver.d.ts +61 -0
  134. package/dist/data/solver/solver.js +55 -0
  135. package/dist/data/solver/underclued/undercluedSolver.d.ts +8 -0
  136. package/dist/data/solver/underclued/undercluedSolver.js +55 -0
  137. package/dist/data/solver/underclued/undercluedWorker.d.ts +2 -0
  138. package/dist/data/solver/underclued/undercluedWorker.js +131 -0
  139. package/dist/data/solver/z3/modules/areaNumberModule.d.ts +9 -0
  140. package/dist/data/solver/z3/modules/areaNumberModule.js +35 -0
  141. package/dist/data/solver/z3/modules/cellCountModule.d.ts +9 -0
  142. package/dist/data/solver/z3/modules/cellCountModule.js +59 -0
  143. package/dist/data/solver/z3/modules/connectAllModule.d.ts +9 -0
  144. package/dist/data/solver/z3/modules/connectAllModule.js +32 -0
  145. package/dist/data/solver/z3/modules/dartModule.d.ts +9 -0
  146. package/dist/data/solver/z3/modules/dartModule.js +69 -0
  147. package/dist/data/solver/z3/modules/index.d.ts +3 -0
  148. package/dist/data/solver/z3/modules/index.js +10 -0
  149. package/dist/data/solver/z3/modules/letterModule.d.ts +9 -0
  150. package/dist/data/solver/z3/modules/letterModule.js +41 -0
  151. package/dist/data/solver/z3/modules/modules.gen.d.ts +8 -0
  152. package/dist/data/solver/z3/modules/modules.gen.js +12 -0
  153. package/dist/data/solver/z3/modules/myopiaModule.d.ts +9 -0
  154. package/dist/data/solver/z3/modules/myopiaModule.js +64 -0
  155. package/dist/data/solver/z3/modules/regionAreaModule.d.ts +9 -0
  156. package/dist/data/solver/z3/modules/regionAreaModule.js +48 -0
  157. package/dist/data/solver/z3/modules/viewpointModule.d.ts +9 -0
  158. package/dist/data/solver/z3/modules/viewpointModule.js +37 -0
  159. package/dist/data/solver/z3/modules/z3Module.d.ts +7 -0
  160. package/dist/data/solver/z3/modules/z3Module.js +3 -0
  161. package/dist/data/solver/z3/utils.d.ts +2 -0
  162. package/dist/data/solver/z3/utils.js +26 -0
  163. package/dist/data/solver/z3/z3Solver.d.ts +10 -0
  164. package/dist/data/solver/z3/z3Solver.js +134 -0
  165. package/dist/data/solver/z3/z3SolverContext.d.ts +808 -0
  166. package/dist/data/solver/z3/z3SolverContext.js +49 -0
  167. package/dist/data/symbols/areaNumberSymbol.d.ts +30 -0
  168. package/dist/data/symbols/areaNumberSymbol.js +88 -0
  169. package/dist/data/symbols/customIconSymbol.d.ts +35 -0
  170. package/dist/data/symbols/customIconSymbol.js +105 -0
  171. package/dist/data/symbols/customSymbol.d.ts +23 -0
  172. package/dist/data/symbols/customSymbol.js +48 -0
  173. package/dist/data/symbols/customTextSymbol.d.ts +33 -0
  174. package/dist/data/symbols/customTextSymbol.js +106 -0
  175. package/dist/data/symbols/dartSymbol.d.ts +35 -0
  176. package/dist/data/symbols/dartSymbol.js +110 -0
  177. package/dist/data/symbols/directionLinkerSymbol.d.ts +36 -0
  178. package/dist/data/symbols/directionLinkerSymbol.js +259 -0
  179. package/dist/data/symbols/galaxySymbol.d.ts +26 -0
  180. package/dist/data/symbols/galaxySymbol.js +74 -0
  181. package/dist/data/symbols/index.d.ts +3 -0
  182. package/dist/data/symbols/index.js +10 -0
  183. package/dist/data/symbols/letterSymbol.d.ts +31 -0
  184. package/dist/data/symbols/letterSymbol.js +137 -0
  185. package/dist/data/symbols/lotusSymbol.d.ts +29 -0
  186. package/dist/data/symbols/lotusSymbol.js +132 -0
  187. package/dist/data/symbols/minesweeperSymbol.d.ts +31 -0
  188. package/dist/data/symbols/minesweeperSymbol.js +100 -0
  189. package/dist/data/symbols/multiEntrySymbol.d.ts +11 -0
  190. package/dist/data/symbols/multiEntrySymbol.js +14 -0
  191. package/dist/data/symbols/myopiaSymbol.d.ts +34 -0
  192. package/dist/data/symbols/myopiaSymbol.js +187 -0
  193. package/dist/data/symbols/numberSymbol.d.ts +19 -0
  194. package/dist/data/symbols/numberSymbol.js +41 -0
  195. package/dist/data/symbols/symbol.d.ts +16 -0
  196. package/dist/data/symbols/symbol.js +51 -0
  197. package/dist/data/symbols/symbols.gen.d.ts +10 -0
  198. package/dist/data/symbols/symbols.gen.js +14 -0
  199. package/dist/data/symbols/viewpointSymbol.d.ts +31 -0
  200. package/dist/data/symbols/viewpointSymbol.js +106 -0
  201. package/dist/data/tile.d.ts +26 -0
  202. package/dist/data/tile.js +68 -0
  203. package/dist/data/tileConnections.d.ts +25 -0
  204. package/dist/data/tileConnections.js +74 -0
  205. package/dist/data/validate.d.ts +5 -0
  206. package/dist/data/validate.js +131 -0
  207. package/dist/index.d.ts +96 -0
  208. package/dist/index.js +100 -0
  209. package/dist/polyfill/streamPolyfill.d.ts +2 -0
  210. package/dist/polyfill/streamPolyfill.js +1 -0
  211. package/package.json +75 -0
@@ -0,0 +1,131 @@
1
+ import { Color, State } from '../../primitives';
2
+ import { Serializer } from '../../serializer/allSerializers';
3
+ import validateGrid from '../../validate';
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(currentGrid.tiles
74
+ .map(row => row
75
+ .map(t => {
76
+ const color = t.color === Color.Light ? 'w' : 'b';
77
+ if (t.color === Color.Gray)
78
+ return 'n';
79
+ if (!t.exists)
80
+ return '.';
81
+ return t.fixed ? color.toUpperCase() : color;
82
+ })
83
+ .join(''))
84
+ .join('\n'));
85
+ if (!anyNewGrid) {
86
+ break;
87
+ }
88
+ const newLastValidGrid = currentGrid.tiles
89
+ .map(row => row.map(t => t.color))
90
+ .flat();
91
+ if (lastValidGrid.length !== 0) {
92
+ const diff = newLastValidGrid.map((color, i) => color === lastValidGrid[i]);
93
+ diff.forEach((same, i) => {
94
+ if (!same) {
95
+ newLastValidGrid[i] = Color.Gray;
96
+ }
97
+ });
98
+ }
99
+ [currentGrid, assumptions] = tryToBacktrack(currentGrid, assumptions);
100
+ lastValidGrid = newLastValidGrid;
101
+ }
102
+ // Create a new grid with lastValidGrid
103
+ let solutionGrid = initialGrid.copyWith({});
104
+ lastValidGrid.forEach((color, i) => {
105
+ const coords = posToCoords(i, solutionGrid.width);
106
+ solutionGrid = solutionGrid.setTile(coords[0], coords[1], tile => tile.withColor(color));
107
+ });
108
+ console.log(solutionGrid.tiles
109
+ .map(row => row
110
+ .map(t => {
111
+ const color = t.color === Color.Light ? 'w' : 'b';
112
+ if (t.color === Color.Gray)
113
+ return 'n';
114
+ if (!t.exists)
115
+ return '.';
116
+ return t.fixed ? color.toUpperCase() : color;
117
+ })
118
+ .join(''))
119
+ .join('\n'));
120
+ return solutionGrid;
121
+ }
122
+ onmessage = e => {
123
+ if (!e.data || typeof e.data !== 'string')
124
+ return;
125
+ const grid = Serializer.parseGrid(e.data);
126
+ const solved = computeSolution(grid);
127
+ postMessage(Serializer.stringifyGrid(solved));
128
+ };
129
+ // make typescript happy
130
+ // eslint-disable-next-line import/no-anonymous-default-export
131
+ export default null;
@@ -0,0 +1,9 @@
1
+ import { Solver, Optimize } from 'z3-solver';
2
+ import GridData from '../../../grid';
3
+ import Z3SolverContext from '../z3SolverContext';
4
+ import Z3Module from './z3Module';
5
+ export default class AreaNumberModule extends Z3Module {
6
+ readonly id: string;
7
+ encode<Name extends string>(grid: GridData, ctx: Z3SolverContext<Name, Solver<Name> | Optimize<Name>>): void;
8
+ }
9
+ export declare const instance: AreaNumberModule;
@@ -0,0 +1,35 @@
1
+ import Z3Module from './z3Module';
2
+ import { instance as areaNumberInstance, } from '../../../symbols/areaNumberSymbol';
3
+ import { Point } from 'grilops';
4
+ export default class AreaNumberModule extends Z3Module {
5
+ constructor() {
6
+ super(...arguments);
7
+ Object.defineProperty(this, "id", {
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true,
11
+ value: areaNumberInstance.id
12
+ });
13
+ }
14
+ encode(grid, ctx) {
15
+ const symbols = grid.symbols.get(this.id);
16
+ // optimizations
17
+ if (!symbols || symbols.length === 0) {
18
+ return;
19
+ }
20
+ for (const symbol of symbols) {
21
+ if (symbol.number < 1) {
22
+ ctx.solver.add(ctx.ctx.Bool.val(false));
23
+ return;
24
+ }
25
+ }
26
+ // encode for real
27
+ const rc = ctx.regionConstrainer;
28
+ for (const symbol of symbols) {
29
+ const x = Math.floor(symbol.x);
30
+ const y = Math.floor(symbol.y);
31
+ ctx.solver.add(rc.regionSizeGrid.get(new Point(y, x)).eq(Math.round(symbol.number)));
32
+ }
33
+ }
34
+ }
35
+ export const instance = new AreaNumberModule();
@@ -0,0 +1,9 @@
1
+ import { Solver, Optimize } from 'z3-solver';
2
+ import GridData from '../../../grid';
3
+ import Z3SolverContext from '../z3SolverContext';
4
+ import Z3Module from './z3Module';
5
+ export default class CellCountModule extends Z3Module {
6
+ readonly id: string;
7
+ encode<Name extends string>(grid: GridData, ctx: Z3SolverContext<Name, Solver<Name> | Optimize<Name>>): void;
8
+ }
9
+ export declare const instance: CellCountModule;
@@ -0,0 +1,59 @@
1
+ import Z3Module from './z3Module';
2
+ import { Point } from 'grilops';
3
+ import { instance as cellCountInstance, } from '../../../rules/cellCountRule';
4
+ import { Color } from '../../../primitives';
5
+ export default class CellCountModule extends Z3Module {
6
+ constructor() {
7
+ super(...arguments);
8
+ Object.defineProperty(this, "id", {
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true,
12
+ value: cellCountInstance.id
13
+ });
14
+ }
15
+ encode(grid, ctx) {
16
+ const rules = grid.rules.filter(rule => rule.id === this.id);
17
+ // optimizations
18
+ if (rules.length === 0) {
19
+ return;
20
+ }
21
+ const colorMap = new Map();
22
+ for (const rule of rules) {
23
+ if (colorMap.has(rule.color)) {
24
+ if (colorMap.get(rule.color) !== rule.count) {
25
+ ctx.solver.add(ctx.ctx.Bool.val(false));
26
+ return;
27
+ }
28
+ }
29
+ else {
30
+ colorMap.set(rule.color, rule.count);
31
+ }
32
+ }
33
+ for (const [color, count] of colorMap.entries()) {
34
+ const { min, max } = grid.getColorCount(color);
35
+ if (min > count || max < count) {
36
+ ctx.solver.add(ctx.ctx.Bool.val(false));
37
+ return;
38
+ }
39
+ }
40
+ if (colorMap.has(Color.Light) && colorMap.has(Color.Dark)) {
41
+ if (colorMap.get(Color.Light) + colorMap.get(Color.Dark) !==
42
+ grid.getTileCount(true)) {
43
+ ctx.solver.add(ctx.ctx.Bool.val(false));
44
+ return;
45
+ }
46
+ }
47
+ // encode for real
48
+ for (const [color, count] of colorMap.entries()) {
49
+ const sumTerms = [];
50
+ grid.forEach((tile, x, y) => {
51
+ if (tile.exists) {
52
+ sumTerms.push(ctx.ctx.If(ctx.grid.cellAt(new Point(y, x)).eq(ctx.symbolSet.indices[color]), 1, 0));
53
+ }
54
+ });
55
+ ctx.solver.add(ctx.ctx.Sum(sumTerms[0], ...sumTerms.slice(1)).eq(count));
56
+ }
57
+ }
58
+ }
59
+ export const instance = new CellCountModule();
@@ -0,0 +1,9 @@
1
+ import { Solver, Optimize } from 'z3-solver';
2
+ import GridData from '../../../grid';
3
+ import Z3SolverContext from '../z3SolverContext';
4
+ import Z3Module from './z3Module';
5
+ export default class ConnectAllModule extends Z3Module {
6
+ readonly id: string;
7
+ encode<Name extends string>(grid: GridData, ctx: Z3SolverContext<Name, Solver<Name> | Optimize<Name>>): void;
8
+ }
9
+ export declare const instance: ConnectAllModule;
@@ -0,0 +1,32 @@
1
+ import Z3Module from './z3Module';
2
+ import { instance as connectAllInstance, } from '../../../rules/connectAllRule';
3
+ export default class ConnectAllModule extends Z3Module {
4
+ constructor() {
5
+ super(...arguments);
6
+ Object.defineProperty(this, "id", {
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true,
10
+ value: connectAllInstance.id
11
+ });
12
+ }
13
+ encode(grid, ctx) {
14
+ const rules = grid.rules.filter(rule => rule.id === this.id);
15
+ // optimizations to try to simplify the encoding
16
+ if (rules.length === 0) {
17
+ return;
18
+ }
19
+ // encode for real
20
+ const rc = ctx.regionConstrainer;
21
+ for (const color of new Set(rules.map(rule => rule.color))) {
22
+ const sumTerms = [];
23
+ for (const [p, cell] of ctx.grid.grid.entries()) {
24
+ sumTerms.push(ctx.ctx.If(cell
25
+ .eq(ctx.symbolSet.indices[color])
26
+ .and(rc.parentGrid.get(p).eq(1)), 1, 0));
27
+ }
28
+ ctx.solver.add(ctx.ctx.Sum(sumTerms[0], ...sumTerms.slice(1)).eq(1));
29
+ }
30
+ }
31
+ }
32
+ export const instance = new ConnectAllModule();
@@ -0,0 +1,9 @@
1
+ import { Solver, Optimize } from 'z3-solver';
2
+ import GridData from '../../../grid';
3
+ import Z3SolverContext from '../z3SolverContext';
4
+ import Z3Module from './z3Module';
5
+ export default class DartModule extends Z3Module {
6
+ readonly id: string;
7
+ encode<Name extends string>(grid: GridData, ctx: Z3SolverContext<Name, Solver<Name> | Optimize<Name>>): void;
8
+ }
9
+ export declare const instance: DartModule;
@@ -0,0 +1,69 @@
1
+ import Z3Module from './z3Module';
2
+ import { instance as dartInstance, } from '../../../symbols/dartSymbol';
3
+ import { Point, reduceCells } from 'grilops';
4
+ import { Color } from '../../../primitives';
5
+ import { move } from '../../../dataHelper';
6
+ import { convertDirection } from '../utils';
7
+ export default class DartModule extends Z3Module {
8
+ constructor() {
9
+ super(...arguments);
10
+ Object.defineProperty(this, "id", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: dartInstance.id
15
+ });
16
+ }
17
+ encode(grid, ctx) {
18
+ const symbols = grid.symbols.get(this.id);
19
+ // optimizations
20
+ if (!symbols || symbols.length === 0) {
21
+ return;
22
+ }
23
+ for (const symbol of symbols) {
24
+ const x = Math.floor(symbol.x);
25
+ const y = Math.floor(symbol.y);
26
+ const startPos = move({ x, y }, symbol.orientation);
27
+ const tile = grid.getTile(x, y);
28
+ if (tile.fixed) {
29
+ let min = 0;
30
+ let unknown = 0;
31
+ grid.iterateDirectionAll(startPos, symbol.orientation, () => true, cell => {
32
+ if (!cell.exists)
33
+ return;
34
+ if (cell.fixed &&
35
+ cell.color !== tile.color &&
36
+ cell.color !== Color.Gray)
37
+ min++;
38
+ if (!cell.fixed)
39
+ unknown++;
40
+ });
41
+ if (min > symbol.number || min + unknown < symbol.number) {
42
+ ctx.solver.add(ctx.ctx.Bool.val(false));
43
+ return;
44
+ }
45
+ }
46
+ else {
47
+ let count = 0;
48
+ grid.iterateDirectionAll(startPos, symbol.orientation, () => true, cell => {
49
+ if (!cell.exists)
50
+ return;
51
+ count++;
52
+ });
53
+ if (count < symbol.number) {
54
+ ctx.solver.add(ctx.ctx.Bool.val(false));
55
+ return;
56
+ }
57
+ }
58
+ }
59
+ // encode for real
60
+ for (const symbol of symbols) {
61
+ const x = Math.floor(symbol.x);
62
+ const y = Math.floor(symbol.y);
63
+ const startPos = move({ x, y }, symbol.orientation);
64
+ const origin = ctx.grid.cellAt(new Point(y, x));
65
+ ctx.solver.add(reduceCells(ctx.grid.ctx, ctx.grid, new Point(startPos.y, startPos.x), convertDirection(symbol.orientation), ctx.ctx.Int.val(0), (acc, cell) => ctx.ctx.If(ctx.ctx.Or(cell.eq(origin), cell.eq(ctx.symbolSet.indices.empty)), acc, acc.add(1))).eq(symbol.number));
66
+ }
67
+ }
68
+ }
69
+ export const instance = new DartModule();
@@ -0,0 +1,3 @@
1
+ import Z3Module from './z3Module';
2
+ declare const allZ3Modules: Map<string, Z3Module>;
3
+ export { allZ3Modules };
@@ -0,0 +1,10 @@
1
+ import * as modules from './modules.gen';
2
+ const allZ3Modules = new Map();
3
+ function register(prototype) {
4
+ allZ3Modules.set(prototype.id, prototype);
5
+ }
6
+ Object.values(modules).forEach(module => {
7
+ if (module)
8
+ register(module);
9
+ });
10
+ export { allZ3Modules };
@@ -0,0 +1,9 @@
1
+ import { Solver, Optimize } from 'z3-solver';
2
+ import GridData from '../../../grid';
3
+ import Z3SolverContext from '../z3SolverContext';
4
+ import Z3Module from './z3Module';
5
+ export default class LetterModule extends Z3Module {
6
+ readonly id: string;
7
+ encode<Name extends string>(grid: GridData, ctx: Z3SolverContext<Name, Solver<Name> | Optimize<Name>>): void;
8
+ }
9
+ export declare const instance: LetterModule;
@@ -0,0 +1,41 @@
1
+ import Z3Module from './z3Module';
2
+ import { instance as letterInstance, } from '../../../symbols/letterSymbol';
3
+ import { Point } from 'grilops';
4
+ export default class LetterModule extends Z3Module {
5
+ constructor() {
6
+ super(...arguments);
7
+ Object.defineProperty(this, "id", {
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true,
11
+ value: letterInstance.id
12
+ });
13
+ }
14
+ encode(grid, ctx) {
15
+ const symbols = grid.symbols.get(this.id);
16
+ if (!symbols || symbols.length === 0) {
17
+ return;
18
+ }
19
+ const rc = ctx.regionConstrainer;
20
+ const letterMap = new Map();
21
+ for (const symbol of symbols) {
22
+ const x = Math.floor(symbol.x);
23
+ const y = Math.floor(symbol.y);
24
+ if (letterMap.has(symbol.letter)) {
25
+ ctx.solver.add(letterMap
26
+ .get(symbol.letter)
27
+ .eq(rc.regionIdGrid.get(new Point(y, x))));
28
+ }
29
+ else {
30
+ letterMap.set(symbol.letter, rc.regionIdGrid.get(new Point(y, x)));
31
+ }
32
+ }
33
+ const letters = Array.from(letterMap.values());
34
+ for (let i = 0; i < letters.length - 1; i++) {
35
+ for (let j = i + 1; j < letters.length; j++) {
36
+ ctx.solver.add(letters[i].neq(letters[j]));
37
+ }
38
+ }
39
+ }
40
+ }
41
+ export const instance = new LetterModule();
@@ -0,0 +1,8 @@
1
+ export { instance as AreaNumberModule } from './areaNumberModule';
2
+ export { instance as CellCountModule } from './cellCountModule';
3
+ export { instance as ConnectAllModule } from './connectAllModule';
4
+ export { instance as DartModule } from './dartModule';
5
+ export { instance as LetterModule } from './letterModule';
6
+ export { instance as MyopiaModule } from './myopiaModule';
7
+ export { instance as RegionAreaModule } from './regionAreaModule';
8
+ export { instance as ViewpointModule } from './viewpointModule';
@@ -0,0 +1,12 @@
1
+ /* prettier-ignore-start */
2
+ /* eslint-disable */
3
+ // @ts-nocheck
4
+ // noinspection JSUnusedGlobalSymbols
5
+ export { instance as AreaNumberModule } from './areaNumberModule';
6
+ export { instance as CellCountModule } from './cellCountModule';
7
+ export { instance as ConnectAllModule } from './connectAllModule';
8
+ export { instance as DartModule } from './dartModule';
9
+ export { instance as LetterModule } from './letterModule';
10
+ export { instance as MyopiaModule } from './myopiaModule';
11
+ export { instance as RegionAreaModule } from './regionAreaModule';
12
+ export { instance as ViewpointModule } from './viewpointModule';
@@ -0,0 +1,9 @@
1
+ import { Solver, Optimize } from 'z3-solver';
2
+ import GridData from '../../../grid';
3
+ import Z3SolverContext from '../z3SolverContext';
4
+ import Z3Module from './z3Module';
5
+ export default class MyopiaModule extends Z3Module {
6
+ readonly id: string;
7
+ encode<Name extends string>(grid: GridData, ctx: Z3SolverContext<Name, Solver<Name> | Optimize<Name>>): void;
8
+ }
9
+ export declare const instance: MyopiaModule;
@@ -0,0 +1,64 @@
1
+ import Z3Module from './z3Module';
2
+ import { instance as myopiaInstance, } from '../../../symbols/myopiaSymbol';
3
+ import { Point, reduceCells } from 'grilops';
4
+ import { DIRECTIONS, ORIENTATIONS } from '../../../primitives';
5
+ import { convertDirection } from '../utils';
6
+ import { move } from '../../../dataHelper';
7
+ export default class MyopiaModule extends Z3Module {
8
+ constructor() {
9
+ super(...arguments);
10
+ Object.defineProperty(this, "id", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: myopiaInstance.id
15
+ });
16
+ }
17
+ encode(grid, ctx) {
18
+ const symbols = grid.symbols.get(this.id);
19
+ // optimizations
20
+ if (!symbols || symbols.length === 0) {
21
+ return;
22
+ }
23
+ // encode for real
24
+ for (const symbol of symbols) {
25
+ const x = Math.floor(symbol.x);
26
+ const y = Math.floor(symbol.y);
27
+ const startPos = new Point(y, x);
28
+ const origin = ctx.grid.cellAt(new Point(y, x));
29
+ const pointedTerms = [];
30
+ const otherTerms = [];
31
+ ORIENTATIONS.filter(d => symbol.directions[d]).forEach(direction => {
32
+ pointedTerms.push(reduceCells(ctx.grid.ctx, ctx.grid, startPos, convertDirection(direction), ctx.ctx.Int.val(0), (acc, cell, p) => {
33
+ const nextPos = move({ x: p.x, y: p.y }, direction);
34
+ if (grid.isPositionValid(nextPos.x, nextPos.y)) {
35
+ return ctx.ctx.If(cell.eq(origin), acc.add(1), acc);
36
+ }
37
+ else {
38
+ return ctx.ctx.If(cell.eq(origin), acc.add(Number.MAX_SAFE_INTEGER), acc);
39
+ }
40
+ }, (_, cell) => cell.neq(origin)));
41
+ });
42
+ (symbol.diagonals ? ORIENTATIONS : DIRECTIONS)
43
+ .filter(d => !symbol.directions[d])
44
+ .forEach(direction => {
45
+ otherTerms.push(reduceCells(ctx.grid.ctx, ctx.grid, startPos, convertDirection(direction), ctx.ctx.Int.val(0), (acc, cell, p) => {
46
+ const nextPos = move({ x: p.x, y: p.y }, direction);
47
+ if (grid.isPositionValid(nextPos.x, nextPos.y)) {
48
+ return ctx.ctx.If(cell.eq(origin), acc.add(1), acc);
49
+ }
50
+ else {
51
+ return ctx.ctx.If(cell.eq(origin), acc.add(Number.MAX_SAFE_INTEGER), acc);
52
+ }
53
+ }, (_, cell) => cell.neq(origin)));
54
+ });
55
+ for (let i = 1; i < pointedTerms.length; i++) {
56
+ ctx.solver.add(pointedTerms[i].eq(pointedTerms[0]));
57
+ }
58
+ for (const otherTerm of otherTerms) {
59
+ ctx.solver.add(otherTerm.gt(pointedTerms[0]));
60
+ }
61
+ }
62
+ }
63
+ }
64
+ export const instance = new MyopiaModule();
@@ -0,0 +1,9 @@
1
+ import { Solver, Optimize } from 'z3-solver';
2
+ import GridData from '../../../grid';
3
+ import Z3SolverContext from '../z3SolverContext';
4
+ import Z3Module from './z3Module';
5
+ export default class RegionAreaModule extends Z3Module {
6
+ readonly id: string;
7
+ encode<Name extends string>(grid: GridData, ctx: Z3SolverContext<Name, Solver<Name> | Optimize<Name>>): void;
8
+ }
9
+ export declare const instance: RegionAreaModule;
@@ -0,0 +1,48 @@
1
+ import Z3Module from './z3Module';
2
+ import { instance as regionAreaInstance, } from '../../../rules/regionAreaRule';
3
+ export default class RegionAreaModule extends Z3Module {
4
+ constructor() {
5
+ super(...arguments);
6
+ Object.defineProperty(this, "id", {
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true,
10
+ value: regionAreaInstance.id
11
+ });
12
+ }
13
+ encode(grid, ctx) {
14
+ const rules = grid.rules.filter(rule => rule.id === this.id);
15
+ // optimizations
16
+ if (rules.length === 0) {
17
+ return;
18
+ }
19
+ const colorMap = new Map();
20
+ for (const rule of rules) {
21
+ if (colorMap.has(rule.color)) {
22
+ if (colorMap.get(rule.color) !== rule.size) {
23
+ ctx.solver.add(ctx.ctx.Bool.val(false));
24
+ return;
25
+ }
26
+ }
27
+ else {
28
+ colorMap.set(rule.color, rule.size);
29
+ }
30
+ }
31
+ for (const [color, count] of colorMap.entries()) {
32
+ if (count < 0 || count > grid.getColorCount(color).max) {
33
+ ctx.solver.add(ctx.ctx.Bool.val(false));
34
+ return;
35
+ }
36
+ }
37
+ // encode for real
38
+ const rc = ctx.regionConstrainer;
39
+ for (const [color, count] of colorMap.entries()) {
40
+ for (const [p, cell] of ctx.grid.grid.entries()) {
41
+ ctx.solver.add(cell
42
+ .eq(ctx.symbolSet.indices[color])
43
+ .implies(rc.regionSizeGrid.get(p).eq(count)));
44
+ }
45
+ }
46
+ }
47
+ }
48
+ export const instance = new RegionAreaModule();
@@ -0,0 +1,9 @@
1
+ import { Solver, Optimize } from 'z3-solver';
2
+ import GridData from '../../../grid';
3
+ import Z3SolverContext from '../z3SolverContext';
4
+ import Z3Module from './z3Module';
5
+ export default class ViewpointModule extends Z3Module {
6
+ readonly id: string;
7
+ encode<Name extends string>(grid: GridData, ctx: Z3SolverContext<Name, Solver<Name> | Optimize<Name>>): void;
8
+ }
9
+ export declare const instance: ViewpointModule;
@@ -0,0 +1,37 @@
1
+ import Z3Module from './z3Module';
2
+ import { instance as viewpointInstance, } from '../../../symbols/viewpointSymbol';
3
+ import { Point, reduceCells } from 'grilops';
4
+ import { DIRECTIONS } from '../../../primitives';
5
+ import { move } from '../../../dataHelper';
6
+ import { convertDirection } from '../utils';
7
+ export default class ViewpointModule extends Z3Module {
8
+ constructor() {
9
+ super(...arguments);
10
+ Object.defineProperty(this, "id", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: viewpointInstance.id
15
+ });
16
+ }
17
+ encode(grid, ctx) {
18
+ const symbols = grid.symbols.get(this.id);
19
+ // optimizations
20
+ if (!symbols || symbols.length === 0) {
21
+ return;
22
+ }
23
+ // encode for real
24
+ for (const symbol of symbols) {
25
+ const x = Math.floor(symbol.x);
26
+ const y = Math.floor(symbol.y);
27
+ const origin = ctx.grid.cellAt(new Point(y, x));
28
+ const sumTerms = [];
29
+ DIRECTIONS.forEach(direction => {
30
+ const startPos = move({ x, y }, direction);
31
+ sumTerms.push(reduceCells(ctx.grid.ctx, ctx.grid, new Point(startPos.y, startPos.x), convertDirection(direction), ctx.ctx.Int.val(0), (acc, cell) => ctx.ctx.If(cell.eq(origin), acc.add(1), acc), (_, cell) => cell.neq(origin)));
32
+ });
33
+ ctx.solver.add(ctx.ctx.Sum(ctx.ctx.Int.val(1), ...sumTerms).eq(symbol.number));
34
+ }
35
+ }
36
+ }
37
+ export const instance = new ViewpointModule();
@@ -0,0 +1,7 @@
1
+ import GridData from '../../../grid';
2
+ import Z3SolverContext from '../z3SolverContext';
3
+ export default abstract class Z3Module {
4
+ abstract get id(): string;
5
+ abstract encode<Name extends string>(grid: GridData, ctx: Z3SolverContext<Name>): void;
6
+ }
7
+ export declare const instance: undefined;
@@ -0,0 +1,3 @@
1
+ export default class Z3Module {
2
+ }
3
+ export const instance = undefined;
@@ -0,0 +1,2 @@
1
+ import { Direction, Orientation } from '../../primitives';
2
+ export declare function convertDirection(direction: Orientation | Direction): import("grilops").Direction;