@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.
- package/LICENSE +661 -0
- package/README.md +19 -0
- package/assets/logic-core.global.d.ts +5865 -0
- package/assets/z3-built.js +14723 -0
- package/assets/z3-built.wasm +0 -0
- package/assets/z3-built.worker.js +206 -0
- package/dist/data/config.d.ts +101 -0
- package/dist/data/config.js +55 -0
- package/dist/data/configurable.d.ts +12 -0
- package/dist/data/configurable.js +26 -0
- package/dist/data/dataHelper.d.ts +77 -0
- package/dist/data/dataHelper.js +190 -0
- package/dist/data/events/eventHelper.d.ts +1 -0
- package/dist/data/events/eventHelper.js +6 -0
- package/dist/data/events/onFinalValidation.d.ts +14 -0
- package/dist/data/events/onFinalValidation.js +4 -0
- package/dist/data/events/onGridChange.d.ts +6 -0
- package/dist/data/events/onGridChange.js +4 -0
- package/dist/data/events/onGridResize.d.ts +9 -0
- package/dist/data/events/onGridResize.js +4 -0
- package/dist/data/events/onSetGrid.d.ts +6 -0
- package/dist/data/events/onSetGrid.js +4 -0
- package/dist/data/events/onSymbolValidation.d.ts +18 -0
- package/dist/data/events/onSymbolValidation.js +4 -0
- package/dist/data/grid.d.ts +362 -0
- package/dist/data/grid.js +886 -0
- package/dist/data/gridConnections.d.ts +38 -0
- package/dist/data/gridConnections.js +328 -0
- package/dist/data/instruction.d.ts +19 -0
- package/dist/data/instruction.js +23 -0
- package/dist/data/primitives.d.ts +85 -0
- package/dist/data/primitives.js +90 -0
- package/dist/data/puzzle.d.ts +86 -0
- package/dist/data/puzzle.js +22 -0
- package/dist/data/rules/banPatternRule.d.ts +29 -0
- package/dist/data/rules/banPatternRule.js +133 -0
- package/dist/data/rules/cellCountRule.d.ts +32 -0
- package/dist/data/rules/cellCountRule.js +166 -0
- package/dist/data/rules/completePatternRule.d.ts +22 -0
- package/dist/data/rules/completePatternRule.js +53 -0
- package/dist/data/rules/connectAllRule.d.ts +28 -0
- package/dist/data/rules/connectAllRule.js +113 -0
- package/dist/data/rules/customRule.d.ts +32 -0
- package/dist/data/rules/customRule.js +92 -0
- package/dist/data/rules/foresightRule.d.ts +30 -0
- package/dist/data/rules/foresightRule.js +107 -0
- package/dist/data/rules/index.d.ts +3 -0
- package/dist/data/rules/index.js +10 -0
- package/dist/data/rules/musicControlLine.d.ts +64 -0
- package/dist/data/rules/musicControlLine.js +178 -0
- package/dist/data/rules/musicGridRule.d.ts +46 -0
- package/dist/data/rules/musicGridRule.js +211 -0
- package/dist/data/rules/mysteryRule.d.ts +37 -0
- package/dist/data/rules/mysteryRule.js +164 -0
- package/dist/data/rules/offByXRule.d.ts +30 -0
- package/dist/data/rules/offByXRule.js +134 -0
- package/dist/data/rules/regionAreaRule.d.ts +33 -0
- package/dist/data/rules/regionAreaRule.js +182 -0
- package/dist/data/rules/regionShapeRule.d.ts +22 -0
- package/dist/data/rules/regionShapeRule.js +58 -0
- package/dist/data/rules/rule.d.ts +18 -0
- package/dist/data/rules/rule.js +19 -0
- package/dist/data/rules/rules.gen.d.ts +14 -0
- package/dist/data/rules/rules.gen.js +18 -0
- package/dist/data/rules/sameShapeRule.d.ts +27 -0
- package/dist/data/rules/sameShapeRule.js +88 -0
- package/dist/data/rules/symbolsPerRegionRule.d.ts +37 -0
- package/dist/data/rules/symbolsPerRegionRule.js +211 -0
- package/dist/data/rules/undercluedRule.d.ts +22 -0
- package/dist/data/rules/undercluedRule.js +60 -0
- package/dist/data/rules/uniqueShapeRule.d.ts +27 -0
- package/dist/data/rules/uniqueShapeRule.js +85 -0
- package/dist/data/serializer/allSerializers.d.ts +30 -0
- package/dist/data/serializer/allSerializers.js +64 -0
- package/dist/data/serializer/compressor/allCompressors.d.ts +14 -0
- package/dist/data/serializer/compressor/allCompressors.js +43 -0
- package/dist/data/serializer/compressor/compressorBase.d.ts +16 -0
- package/dist/data/serializer/compressor/compressorBase.js +2 -0
- package/dist/data/serializer/compressor/deflateCompressor.d.ts +7 -0
- package/dist/data/serializer/compressor/deflateCompressor.js +17 -0
- package/dist/data/serializer/compressor/gzipCompressor.d.ts +5 -0
- package/dist/data/serializer/compressor/gzipCompressor.js +9 -0
- package/dist/data/serializer/compressor/streamCompressor.d.ts +6 -0
- package/dist/data/serializer/compressor/streamCompressor.js +36 -0
- package/dist/data/serializer/serializerBase.d.ts +27 -0
- package/dist/data/serializer/serializerBase.js +2 -0
- package/dist/data/serializer/serializer_v0.d.ts +36 -0
- package/dist/data/serializer/serializer_v0.js +426 -0
- package/dist/data/shapes.d.ts +17 -0
- package/dist/data/shapes.js +117 -0
- package/dist/data/solver/allSolvers.d.ts +3 -0
- package/dist/data/solver/allSolvers.js +11 -0
- package/dist/data/solver/backtrack/backtrackSolver.d.ts +9 -0
- package/dist/data/solver/backtrack/backtrackSolver.js +92 -0
- package/dist/data/solver/backtrack/backtrackWorker.d.ts +2 -0
- package/dist/data/solver/backtrack/backtrackWorker.js +295 -0
- package/dist/data/solver/backtrack/data.d.ts +46 -0
- package/dist/data/solver/backtrack/data.js +140 -0
- package/dist/data/solver/backtrack/rules/banPattern.d.ts +9 -0
- package/dist/data/solver/backtrack/rules/banPattern.js +66 -0
- package/dist/data/solver/backtrack/rules/cellCount.d.ts +7 -0
- package/dist/data/solver/backtrack/rules/cellCount.js +30 -0
- package/dist/data/solver/backtrack/rules/connectAll.d.ts +7 -0
- package/dist/data/solver/backtrack/rules/connectAll.js +49 -0
- package/dist/data/solver/backtrack/rules/regionArea.d.ts +8 -0
- package/dist/data/solver/backtrack/rules/regionArea.js +76 -0
- package/dist/data/solver/backtrack/rules/regionShape.d.ts +8 -0
- package/dist/data/solver/backtrack/rules/regionShape.js +62 -0
- package/dist/data/solver/backtrack/rules/sameShape.d.ts +8 -0
- package/dist/data/solver/backtrack/rules/sameShape.js +19 -0
- package/dist/data/solver/backtrack/rules/symbolsPerRegion.d.ts +10 -0
- package/dist/data/solver/backtrack/rules/symbolsPerRegion.js +92 -0
- package/dist/data/solver/backtrack/rules/uniqueShape.d.ts +8 -0
- package/dist/data/solver/backtrack/rules/uniqueShape.js +19 -0
- package/dist/data/solver/backtrack/symbols/areaNumber.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/areaNumber.js +77 -0
- package/dist/data/solver/backtrack/symbols/dart.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/dart.js +58 -0
- package/dist/data/solver/backtrack/symbols/directionLinker.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/directionLinker.js +50 -0
- package/dist/data/solver/backtrack/symbols/galaxy.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/galaxy.js +19 -0
- package/dist/data/solver/backtrack/symbols/letter.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/letter.js +100 -0
- package/dist/data/solver/backtrack/symbols/lotus.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/lotus.js +36 -0
- package/dist/data/solver/backtrack/symbols/minesweeper.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/minesweeper.js +55 -0
- package/dist/data/solver/backtrack/symbols/myopia.d.ts +7 -0
- package/dist/data/solver/backtrack/symbols/myopia.js +79 -0
- package/dist/data/solver/backtrack/symbols/viewpoint.d.ts +7 -0
- package/dist/data/solver/backtrack/symbols/viewpoint.js +56 -0
- package/dist/data/solver/solver.d.ts +61 -0
- package/dist/data/solver/solver.js +55 -0
- package/dist/data/solver/underclued/undercluedSolver.d.ts +8 -0
- package/dist/data/solver/underclued/undercluedSolver.js +55 -0
- package/dist/data/solver/underclued/undercluedWorker.d.ts +2 -0
- package/dist/data/solver/underclued/undercluedWorker.js +131 -0
- package/dist/data/solver/z3/modules/areaNumberModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/areaNumberModule.js +35 -0
- package/dist/data/solver/z3/modules/cellCountModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/cellCountModule.js +59 -0
- package/dist/data/solver/z3/modules/connectAllModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/connectAllModule.js +32 -0
- package/dist/data/solver/z3/modules/dartModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/dartModule.js +69 -0
- package/dist/data/solver/z3/modules/index.d.ts +3 -0
- package/dist/data/solver/z3/modules/index.js +10 -0
- package/dist/data/solver/z3/modules/letterModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/letterModule.js +41 -0
- package/dist/data/solver/z3/modules/modules.gen.d.ts +8 -0
- package/dist/data/solver/z3/modules/modules.gen.js +12 -0
- package/dist/data/solver/z3/modules/myopiaModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/myopiaModule.js +64 -0
- package/dist/data/solver/z3/modules/regionAreaModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/regionAreaModule.js +48 -0
- package/dist/data/solver/z3/modules/viewpointModule.d.ts +9 -0
- package/dist/data/solver/z3/modules/viewpointModule.js +37 -0
- package/dist/data/solver/z3/modules/z3Module.d.ts +7 -0
- package/dist/data/solver/z3/modules/z3Module.js +3 -0
- package/dist/data/solver/z3/utils.d.ts +2 -0
- package/dist/data/solver/z3/utils.js +26 -0
- package/dist/data/solver/z3/z3Solver.d.ts +10 -0
- package/dist/data/solver/z3/z3Solver.js +134 -0
- package/dist/data/solver/z3/z3SolverContext.d.ts +808 -0
- package/dist/data/solver/z3/z3SolverContext.js +49 -0
- package/dist/data/symbols/areaNumberSymbol.d.ts +30 -0
- package/dist/data/symbols/areaNumberSymbol.js +88 -0
- package/dist/data/symbols/customIconSymbol.d.ts +35 -0
- package/dist/data/symbols/customIconSymbol.js +105 -0
- package/dist/data/symbols/customSymbol.d.ts +23 -0
- package/dist/data/symbols/customSymbol.js +48 -0
- package/dist/data/symbols/customTextSymbol.d.ts +33 -0
- package/dist/data/symbols/customTextSymbol.js +106 -0
- package/dist/data/symbols/dartSymbol.d.ts +35 -0
- package/dist/data/symbols/dartSymbol.js +110 -0
- package/dist/data/symbols/directionLinkerSymbol.d.ts +36 -0
- package/dist/data/symbols/directionLinkerSymbol.js +259 -0
- package/dist/data/symbols/galaxySymbol.d.ts +26 -0
- package/dist/data/symbols/galaxySymbol.js +74 -0
- package/dist/data/symbols/index.d.ts +3 -0
- package/dist/data/symbols/index.js +10 -0
- package/dist/data/symbols/letterSymbol.d.ts +31 -0
- package/dist/data/symbols/letterSymbol.js +137 -0
- package/dist/data/symbols/lotusSymbol.d.ts +29 -0
- package/dist/data/symbols/lotusSymbol.js +132 -0
- package/dist/data/symbols/minesweeperSymbol.d.ts +31 -0
- package/dist/data/symbols/minesweeperSymbol.js +100 -0
- package/dist/data/symbols/multiEntrySymbol.d.ts +11 -0
- package/dist/data/symbols/multiEntrySymbol.js +14 -0
- package/dist/data/symbols/myopiaSymbol.d.ts +34 -0
- package/dist/data/symbols/myopiaSymbol.js +187 -0
- package/dist/data/symbols/numberSymbol.d.ts +19 -0
- package/dist/data/symbols/numberSymbol.js +41 -0
- package/dist/data/symbols/symbol.d.ts +16 -0
- package/dist/data/symbols/symbol.js +51 -0
- package/dist/data/symbols/symbols.gen.d.ts +10 -0
- package/dist/data/symbols/symbols.gen.js +14 -0
- package/dist/data/symbols/viewpointSymbol.d.ts +31 -0
- package/dist/data/symbols/viewpointSymbol.js +106 -0
- package/dist/data/tile.d.ts +26 -0
- package/dist/data/tile.js +68 -0
- package/dist/data/tileConnections.d.ts +25 -0
- package/dist/data/tileConnections.js +74 -0
- package/dist/data/validate.d.ts +5 -0
- package/dist/data/validate.js +131 -0
- package/dist/index.d.ts +96 -0
- package/dist/index.js +100 -0
- package/dist/polyfill/streamPolyfill.d.ts +2 -0
- package/dist/polyfill/streamPolyfill.js +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import GridData from '../grid';
|
|
2
|
+
import GridConnections from '../gridConnections';
|
|
3
|
+
import Rule from '../rules/rule';
|
|
4
|
+
import TileData from '../tile';
|
|
5
|
+
import Symbol from '../symbols/symbol';
|
|
6
|
+
import { Puzzle } from '../puzzle';
|
|
7
|
+
export default abstract class SerializerBase {
|
|
8
|
+
abstract get version(): number;
|
|
9
|
+
abstract stringifyTile(tile: TileData): string;
|
|
10
|
+
abstract parseTile(str: string): TileData;
|
|
11
|
+
abstract stringifyRule(rule: Rule): string;
|
|
12
|
+
abstract stringifySymbol(symbol: Symbol): string;
|
|
13
|
+
abstract parseRule(str: string): Rule;
|
|
14
|
+
abstract parseSymbol(str: string): Symbol;
|
|
15
|
+
abstract stringifyConnections(connections: GridConnections): string;
|
|
16
|
+
abstract parseConnections(input: string): GridConnections;
|
|
17
|
+
abstract stringifyTiles(tiles: readonly (readonly TileData[])[]): string;
|
|
18
|
+
abstract parseTiles(input: string): TileData[][];
|
|
19
|
+
abstract stringifyRules(rules: readonly Rule[]): string;
|
|
20
|
+
abstract parseRules(input: string): Rule[];
|
|
21
|
+
abstract stringifySymbols(symbols: ReadonlyMap<string, readonly Symbol[]>): string;
|
|
22
|
+
abstract parseSymbols(input: string): Map<string, Symbol[]>;
|
|
23
|
+
abstract stringifyGrid(grid: GridData): string;
|
|
24
|
+
abstract parseGrid(input: string): GridData;
|
|
25
|
+
abstract stringifyPuzzle(puzzle: Puzzle): string;
|
|
26
|
+
abstract parsePuzzle(input: string): Puzzle;
|
|
27
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import GridData from '../grid';
|
|
2
|
+
import GridConnections from '../gridConnections';
|
|
3
|
+
import Rule from '../rules/rule';
|
|
4
|
+
import TileData from '../tile';
|
|
5
|
+
import Symbol from '../symbols/symbol';
|
|
6
|
+
import Instruction from '../instruction';
|
|
7
|
+
import { AnyConfig } from '../config';
|
|
8
|
+
import SerializerBase from './serializerBase';
|
|
9
|
+
import { Puzzle } from '../puzzle';
|
|
10
|
+
import { ControlLine } from '../rules/musicControlLine';
|
|
11
|
+
export default class SerializerV0 extends SerializerBase {
|
|
12
|
+
readonly version = 0;
|
|
13
|
+
stringifyTile(tile: TileData): string;
|
|
14
|
+
parseTile(str: string): TileData;
|
|
15
|
+
stringifyControlLine(line: ControlLine): string;
|
|
16
|
+
parseControlLine(str: string): ControlLine;
|
|
17
|
+
stringifyConfig(instruction: Instruction, config: AnyConfig): string;
|
|
18
|
+
parseConfig(configs: readonly AnyConfig[], entry: string): [string, unknown];
|
|
19
|
+
stringifyInstruction(instruction: Instruction): string;
|
|
20
|
+
stringifyRule(rule: Rule): string;
|
|
21
|
+
stringifySymbol(symbol: Symbol): string;
|
|
22
|
+
parseRule(str: string): Rule;
|
|
23
|
+
parseSymbol(str: string): Symbol;
|
|
24
|
+
stringifyConnections(connections: GridConnections): string;
|
|
25
|
+
parseConnections(input: string): GridConnections;
|
|
26
|
+
stringifyTiles(tiles: readonly (readonly TileData[])[]): string;
|
|
27
|
+
parseTiles(input: string): TileData[][];
|
|
28
|
+
stringifyRules(rules: readonly Rule[]): string;
|
|
29
|
+
parseRules(input: string): Rule[];
|
|
30
|
+
stringifySymbols(symbols: ReadonlyMap<string, readonly Symbol[]>): string;
|
|
31
|
+
parseSymbols(input: string): Map<string, Symbol[]>;
|
|
32
|
+
stringifyGrid(grid: GridData): string;
|
|
33
|
+
parseGrid(input: string): GridData;
|
|
34
|
+
stringifyPuzzle(puzzle: Puzzle): string;
|
|
35
|
+
parsePuzzle(input: string): Puzzle;
|
|
36
|
+
}
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import GridData from '../grid';
|
|
2
|
+
import GridConnections from '../gridConnections';
|
|
3
|
+
import TileData from '../tile';
|
|
4
|
+
import { ConfigType } from '../config';
|
|
5
|
+
import { Color, DIRECTIONS, ORIENTATIONS, Orientation, directionToggle, orientationToggle, } from '../primitives';
|
|
6
|
+
import { array, escape, unescape } from '../dataHelper';
|
|
7
|
+
import { allRules } from '../rules';
|
|
8
|
+
import { allSymbols } from '../symbols';
|
|
9
|
+
import SerializerBase from './serializerBase';
|
|
10
|
+
import { ControlLine, Row } from '../rules/musicControlLine';
|
|
11
|
+
const OFFSETS = [
|
|
12
|
+
{ x: 0, y: -1 },
|
|
13
|
+
{ x: -1, y: 0 },
|
|
14
|
+
{ x: 1, y: 0 },
|
|
15
|
+
{ x: 0, y: 1 },
|
|
16
|
+
];
|
|
17
|
+
const orientationChars = {
|
|
18
|
+
[Orientation.Up]: 'u',
|
|
19
|
+
[Orientation.UpRight]: 'x',
|
|
20
|
+
[Orientation.Right]: 'r',
|
|
21
|
+
[Orientation.DownRight]: 'z',
|
|
22
|
+
[Orientation.Down]: 'd',
|
|
23
|
+
[Orientation.DownLeft]: 'y',
|
|
24
|
+
[Orientation.Left]: 'l',
|
|
25
|
+
[Orientation.UpLeft]: 'w',
|
|
26
|
+
};
|
|
27
|
+
export default class SerializerV0 extends SerializerBase {
|
|
28
|
+
constructor() {
|
|
29
|
+
super(...arguments);
|
|
30
|
+
Object.defineProperty(this, "version", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: 0
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
stringifyTile(tile) {
|
|
38
|
+
if (!tile.exists)
|
|
39
|
+
return '.';
|
|
40
|
+
const char = tile.color === Color.Gray ? 'n' : tile.color === Color.Dark ? 'b' : 'w';
|
|
41
|
+
return tile.fixed ? char.toUpperCase() : char;
|
|
42
|
+
}
|
|
43
|
+
parseTile(str) {
|
|
44
|
+
return TileData.create(str);
|
|
45
|
+
}
|
|
46
|
+
stringifyControlLine(line) {
|
|
47
|
+
const result = [];
|
|
48
|
+
result.push(`c${line.column}`);
|
|
49
|
+
if (line.bpm !== null)
|
|
50
|
+
result.push(`b${line.bpm}`);
|
|
51
|
+
if (line.pedal !== null)
|
|
52
|
+
result.push(`p${line.pedal ? '1' : '0'}`);
|
|
53
|
+
if (line.checkpoint)
|
|
54
|
+
result.push('s');
|
|
55
|
+
result.push(`r${line.rows
|
|
56
|
+
.map(row => `v${row.velocity ?? ''}n${row.note ?? ''}`)
|
|
57
|
+
.join(',')}`);
|
|
58
|
+
return result.join('|');
|
|
59
|
+
}
|
|
60
|
+
parseControlLine(str) {
|
|
61
|
+
let column = null;
|
|
62
|
+
let bpm = null;
|
|
63
|
+
let pedal = null;
|
|
64
|
+
let checkpoint = false;
|
|
65
|
+
const rows = [];
|
|
66
|
+
const data = str.split('|');
|
|
67
|
+
for (const entry of data) {
|
|
68
|
+
const key = entry.charAt(0);
|
|
69
|
+
const value = entry.slice(1);
|
|
70
|
+
switch (key) {
|
|
71
|
+
case 'c':
|
|
72
|
+
column = value === '' ? null : Number(value);
|
|
73
|
+
break;
|
|
74
|
+
case 'b':
|
|
75
|
+
bpm = value === '' ? null : Number(value);
|
|
76
|
+
break;
|
|
77
|
+
case 'p':
|
|
78
|
+
pedal = value === '1' ? true : value === '0' ? false : null;
|
|
79
|
+
break;
|
|
80
|
+
case 's':
|
|
81
|
+
checkpoint = true;
|
|
82
|
+
break;
|
|
83
|
+
case 'r':
|
|
84
|
+
rows.push(...value.split(',').map(row => {
|
|
85
|
+
const match = row.match(/^v([\d.]*?)n(.*)$/);
|
|
86
|
+
if (!match)
|
|
87
|
+
return new Row(null, null);
|
|
88
|
+
const [, velocity, note] = match;
|
|
89
|
+
return new Row(note === '' ? null : note, velocity === '' ? null : Number(velocity));
|
|
90
|
+
}));
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return new ControlLine(column ?? 0, bpm, pedal, checkpoint, rows);
|
|
95
|
+
}
|
|
96
|
+
stringifyConfig(instruction, config) {
|
|
97
|
+
switch (config.type) {
|
|
98
|
+
case ConfigType.Boolean:
|
|
99
|
+
return (config.field +
|
|
100
|
+
'=' +
|
|
101
|
+
(instruction[config.field] ? '1' : '0'));
|
|
102
|
+
case ConfigType.Number:
|
|
103
|
+
case ConfigType.Color:
|
|
104
|
+
case ConfigType.Comparison:
|
|
105
|
+
case ConfigType.Direction:
|
|
106
|
+
case ConfigType.Orientation:
|
|
107
|
+
return (config.field +
|
|
108
|
+
'=' +
|
|
109
|
+
String(instruction[config.field]));
|
|
110
|
+
case ConfigType.NullableBoolean:
|
|
111
|
+
return (config.field +
|
|
112
|
+
'=' +
|
|
113
|
+
(instruction[config.field] === null
|
|
114
|
+
? ''
|
|
115
|
+
: instruction[config.field]
|
|
116
|
+
? '1'
|
|
117
|
+
: '0'));
|
|
118
|
+
case ConfigType.NullableNumber:
|
|
119
|
+
return (config.field +
|
|
120
|
+
'=' +
|
|
121
|
+
(instruction[config.field] === null
|
|
122
|
+
? ''
|
|
123
|
+
: String(instruction[config.field])));
|
|
124
|
+
case ConfigType.DirectionToggle:
|
|
125
|
+
return (config.field +
|
|
126
|
+
'=' +
|
|
127
|
+
DIRECTIONS.filter(dir => instruction[config.field][dir])
|
|
128
|
+
.map(x => orientationChars[x])
|
|
129
|
+
.join(''));
|
|
130
|
+
case ConfigType.OrientationToggle:
|
|
131
|
+
return (config.field +
|
|
132
|
+
'=' +
|
|
133
|
+
ORIENTATIONS.filter(dir => instruction[config.field][dir])
|
|
134
|
+
.map(x => orientationChars[x])
|
|
135
|
+
.join(''));
|
|
136
|
+
case ConfigType.String:
|
|
137
|
+
case ConfigType.Icon:
|
|
138
|
+
return (config.field +
|
|
139
|
+
'=' +
|
|
140
|
+
escape(String(instruction[config.field])));
|
|
141
|
+
case ConfigType.NullableNote:
|
|
142
|
+
return (config.field +
|
|
143
|
+
'=' +
|
|
144
|
+
escape(instruction[config.field] === null
|
|
145
|
+
? ''
|
|
146
|
+
: escape(String(instruction[config.field]))));
|
|
147
|
+
case ConfigType.Tile:
|
|
148
|
+
case ConfigType.Grid:
|
|
149
|
+
return (config.field +
|
|
150
|
+
'=' +
|
|
151
|
+
escape(this.stringifyGrid(instruction[config.field])));
|
|
152
|
+
case ConfigType.NullableGrid:
|
|
153
|
+
return (config.field +
|
|
154
|
+
'=' +
|
|
155
|
+
escape(instruction[config.field] === null
|
|
156
|
+
? ''
|
|
157
|
+
: this.stringifyGrid(instruction[config.field])));
|
|
158
|
+
case ConfigType.ControlLines:
|
|
159
|
+
return (config.field +
|
|
160
|
+
'=' +
|
|
161
|
+
escape(instruction[config.field]
|
|
162
|
+
.map(line => this.stringifyControlLine(line))
|
|
163
|
+
.join(':')));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
parseConfig(configs, entry) {
|
|
167
|
+
const [key, value] = entry.split('=');
|
|
168
|
+
const config = configs.find(x => x.field === key);
|
|
169
|
+
if (!config)
|
|
170
|
+
throw new Error(`Unknown config: ${key}`);
|
|
171
|
+
switch (config.type) {
|
|
172
|
+
case ConfigType.Boolean:
|
|
173
|
+
return [config.field, value === '1'];
|
|
174
|
+
case ConfigType.NullableBoolean:
|
|
175
|
+
return [config.field, value === '' ? null : value === '1'];
|
|
176
|
+
case ConfigType.Number:
|
|
177
|
+
return [config.field, Number(value)];
|
|
178
|
+
case ConfigType.NullableNumber:
|
|
179
|
+
return [config.field, value === '' ? null : Number(value)];
|
|
180
|
+
case ConfigType.Color:
|
|
181
|
+
return [config.field, value];
|
|
182
|
+
case ConfigType.Comparison:
|
|
183
|
+
return [config.field, value];
|
|
184
|
+
case ConfigType.Direction:
|
|
185
|
+
return [config.field, value];
|
|
186
|
+
case ConfigType.DirectionToggle: {
|
|
187
|
+
const toggle = directionToggle();
|
|
188
|
+
for (const dir of DIRECTIONS) {
|
|
189
|
+
toggle[dir] = value.includes(orientationChars[dir]);
|
|
190
|
+
}
|
|
191
|
+
return [config.field, toggle];
|
|
192
|
+
}
|
|
193
|
+
case ConfigType.Orientation:
|
|
194
|
+
return [config.field, value];
|
|
195
|
+
case ConfigType.OrientationToggle: {
|
|
196
|
+
const toggle = orientationToggle();
|
|
197
|
+
for (const dir of ORIENTATIONS) {
|
|
198
|
+
toggle[dir] = value.includes(orientationChars[dir]);
|
|
199
|
+
}
|
|
200
|
+
return [config.field, toggle];
|
|
201
|
+
}
|
|
202
|
+
case ConfigType.String:
|
|
203
|
+
case ConfigType.Icon:
|
|
204
|
+
return [config.field, unescape(value)];
|
|
205
|
+
case ConfigType.Tile:
|
|
206
|
+
case ConfigType.Grid:
|
|
207
|
+
return [config.field, this.parseGrid(unescape(value))];
|
|
208
|
+
case ConfigType.NullableGrid:
|
|
209
|
+
return [
|
|
210
|
+
config.field,
|
|
211
|
+
value === '' ? null : this.parseGrid(unescape(value)),
|
|
212
|
+
];
|
|
213
|
+
case ConfigType.ControlLines:
|
|
214
|
+
return [
|
|
215
|
+
config.field,
|
|
216
|
+
unescape(value)
|
|
217
|
+
.split(':')
|
|
218
|
+
.map(line => this.parseControlLine(line)),
|
|
219
|
+
];
|
|
220
|
+
case ConfigType.NullableNote:
|
|
221
|
+
return [config.field, value === '' ? null : unescape(value)];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
stringifyInstruction(instruction) {
|
|
225
|
+
return `${instruction.id},${instruction.configs?.map(config => this.stringifyConfig(instruction, config)).join(',') ?? ''}`;
|
|
226
|
+
}
|
|
227
|
+
stringifyRule(rule) {
|
|
228
|
+
return this.stringifyInstruction(rule);
|
|
229
|
+
}
|
|
230
|
+
stringifySymbol(symbol) {
|
|
231
|
+
return this.stringifyInstruction(symbol);
|
|
232
|
+
}
|
|
233
|
+
parseRule(str) {
|
|
234
|
+
const [id, ...entries] = str.split(',');
|
|
235
|
+
const instruction = allRules.get(id);
|
|
236
|
+
if (!instruction)
|
|
237
|
+
throw new Error(`Unknown rule: ${id}`);
|
|
238
|
+
const configs = instruction.configs;
|
|
239
|
+
if (configs == null)
|
|
240
|
+
return instruction.copyWith({});
|
|
241
|
+
return instruction.copyWith(Object.fromEntries(entries
|
|
242
|
+
.filter(entry => entry !== '')
|
|
243
|
+
.map(entry => this.parseConfig(configs, entry))));
|
|
244
|
+
}
|
|
245
|
+
parseSymbol(str) {
|
|
246
|
+
const [id, ...entries] = str.split(',');
|
|
247
|
+
const instruction = allSymbols.get(id);
|
|
248
|
+
if (!instruction)
|
|
249
|
+
throw new Error(`Unknown symbol: ${id}`);
|
|
250
|
+
const configs = instruction.configs;
|
|
251
|
+
if (configs == null)
|
|
252
|
+
return instruction.copyWith({});
|
|
253
|
+
return instruction.copyWith(Object.fromEntries(entries.map(entry => this.parseConfig(configs, entry))));
|
|
254
|
+
}
|
|
255
|
+
stringifyConnections(connections) {
|
|
256
|
+
const maxX = connections.edges.reduce((max, edge) => Math.max(max, edge.x1, edge.x2), 0);
|
|
257
|
+
const maxY = connections.edges.reduce((max, edge) => Math.max(max, edge.y1, edge.y2), 0);
|
|
258
|
+
const result = array(maxX + 1, maxY + 1, () => '.');
|
|
259
|
+
for (let y = 0; y <= maxY; y++) {
|
|
260
|
+
for (let x = 0; x <= maxX; x++) {
|
|
261
|
+
if (result[y][x] !== '.') {
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
const tiles = connections.getConnectedTiles({ x, y });
|
|
265
|
+
if (tiles.length < 2) {
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
const existingChars = [];
|
|
269
|
+
for (const { x: tx, y: ty } of tiles) {
|
|
270
|
+
for (const { x: dx, y: dy } of OFFSETS) {
|
|
271
|
+
if (tx + dx > maxX ||
|
|
272
|
+
ty + dy > maxY ||
|
|
273
|
+
tx + dx < 0 ||
|
|
274
|
+
ty + dy < 0) {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
if (result[ty + dy][tx + dx] !== '.')
|
|
278
|
+
existingChars.push(result[ty + dy][tx + dx]);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
let char = 'A';
|
|
282
|
+
while (existingChars.includes(char)) {
|
|
283
|
+
char = String.fromCharCode(char.charCodeAt(0) + 1);
|
|
284
|
+
}
|
|
285
|
+
for (const connection of tiles) {
|
|
286
|
+
result[connection.y][connection.x] = char;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return `C${maxX + 1}:${result.map(row => row.join('')).join('')}`.replace(/\.+$/, '');
|
|
291
|
+
}
|
|
292
|
+
parseConnections(input) {
|
|
293
|
+
if (!input.startsWith('C')) {
|
|
294
|
+
throw new Error('Invalid grid connections\n' + input);
|
|
295
|
+
}
|
|
296
|
+
const [size, data] = input.slice(1).split(':');
|
|
297
|
+
const width = Number(size);
|
|
298
|
+
const tiles = array(width, Math.ceil(data.length / width), (x, y) => data[y * width + x]);
|
|
299
|
+
return GridConnections.create(tiles.map(row => row.join('')));
|
|
300
|
+
}
|
|
301
|
+
stringifyTiles(tiles) {
|
|
302
|
+
return `T${tiles[0]?.length ?? 0}:${tiles.map(row => row.map(tile => this.stringifyTile(tile)).join('')).join('')}`;
|
|
303
|
+
}
|
|
304
|
+
parseTiles(input) {
|
|
305
|
+
if (!input.startsWith('T')) {
|
|
306
|
+
throw new Error('Invalid grid data\n' + input);
|
|
307
|
+
}
|
|
308
|
+
const [size, data] = input.slice(1).split(':');
|
|
309
|
+
const width = Number(size);
|
|
310
|
+
return array(width, Math.ceil(data.length / width), (x, y) => this.parseTile(data.charAt(y * width + x)));
|
|
311
|
+
}
|
|
312
|
+
stringifyRules(rules) {
|
|
313
|
+
return `R${rules.map(rule => this.stringifyRule(rule)).join(':')}`;
|
|
314
|
+
}
|
|
315
|
+
parseRules(input) {
|
|
316
|
+
if (!input.startsWith('R')) {
|
|
317
|
+
throw new Error('Invalid rules\n' + input);
|
|
318
|
+
}
|
|
319
|
+
return input
|
|
320
|
+
.slice(1)
|
|
321
|
+
.split(':')
|
|
322
|
+
.filter(rule => rule !== '')
|
|
323
|
+
.map(rule => this.parseRule(rule));
|
|
324
|
+
}
|
|
325
|
+
stringifySymbols(symbols) {
|
|
326
|
+
return `S${Array.from(symbols.values())
|
|
327
|
+
.flat()
|
|
328
|
+
.map(symbol => this.stringifySymbol(symbol))
|
|
329
|
+
.join(':')}`;
|
|
330
|
+
}
|
|
331
|
+
parseSymbols(input) {
|
|
332
|
+
if (!input.startsWith('S')) {
|
|
333
|
+
throw new Error('Invalid symbols\n' + input);
|
|
334
|
+
}
|
|
335
|
+
const symbols = new Map();
|
|
336
|
+
input
|
|
337
|
+
.slice(1)
|
|
338
|
+
.split(':')
|
|
339
|
+
.filter(symbol => symbol !== '')
|
|
340
|
+
.forEach(symbol => {
|
|
341
|
+
const parsed = this.parseSymbol(symbol);
|
|
342
|
+
if (symbols.has(parsed.id)) {
|
|
343
|
+
symbols.set(parsed.id, [...symbols.get(parsed.id), parsed]);
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
346
|
+
symbols.set(parsed.id, [parsed]);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
return symbols;
|
|
350
|
+
}
|
|
351
|
+
stringifyGrid(grid) {
|
|
352
|
+
const data = [
|
|
353
|
+
this.stringifyTiles(grid.tiles),
|
|
354
|
+
this.stringifyConnections(grid.connections),
|
|
355
|
+
this.stringifySymbols(grid.symbols),
|
|
356
|
+
this.stringifyRules(grid.rules),
|
|
357
|
+
];
|
|
358
|
+
return `${grid.width}x${grid.height}|${data.join('|')}`;
|
|
359
|
+
}
|
|
360
|
+
parseGrid(input) {
|
|
361
|
+
const data = input.split('|');
|
|
362
|
+
let width;
|
|
363
|
+
let height;
|
|
364
|
+
let tiles;
|
|
365
|
+
let connections;
|
|
366
|
+
let symbols;
|
|
367
|
+
let rules;
|
|
368
|
+
for (const d of data) {
|
|
369
|
+
if (/^\d+x\d+$/.test(d)) {
|
|
370
|
+
[width, height] = d.split('x').map(Number);
|
|
371
|
+
}
|
|
372
|
+
else if (d.startsWith('T')) {
|
|
373
|
+
tiles = this.parseTiles(d);
|
|
374
|
+
}
|
|
375
|
+
else if (d.startsWith('C')) {
|
|
376
|
+
connections = this.parseConnections(d);
|
|
377
|
+
}
|
|
378
|
+
else if (d.startsWith('S')) {
|
|
379
|
+
symbols = this.parseSymbols(d);
|
|
380
|
+
}
|
|
381
|
+
else if (d.startsWith('R')) {
|
|
382
|
+
rules = this.parseRules(d);
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
throw new Error(`Invalid data: ${d}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return new GridData(width ?? tiles?.[0].length ?? 0, height ?? tiles?.length ?? 0, tiles, connections, symbols, rules);
|
|
389
|
+
}
|
|
390
|
+
stringifyPuzzle(puzzle) {
|
|
391
|
+
let grid = puzzle.grid;
|
|
392
|
+
if (puzzle.solution !== null) {
|
|
393
|
+
const tiles = array(puzzle.grid.width, puzzle.grid.height, (x, y) => {
|
|
394
|
+
const tile = puzzle.grid.getTile(x, y);
|
|
395
|
+
const solutionTile = puzzle.solution.getTile(x, y);
|
|
396
|
+
return tile.exists &&
|
|
397
|
+
!tile.fixed &&
|
|
398
|
+
solutionTile.exists &&
|
|
399
|
+
solutionTile.color !== Color.Gray
|
|
400
|
+
? tile.copyWith({
|
|
401
|
+
color: puzzle.solution.tiles[y][x].color,
|
|
402
|
+
})
|
|
403
|
+
: tile;
|
|
404
|
+
});
|
|
405
|
+
grid = puzzle.grid.copyWith({ tiles });
|
|
406
|
+
}
|
|
407
|
+
return JSON.stringify({
|
|
408
|
+
title: puzzle.title,
|
|
409
|
+
grid: this.stringifyGrid(grid),
|
|
410
|
+
difficulty: puzzle.difficulty,
|
|
411
|
+
link: puzzle.link,
|
|
412
|
+
author: puzzle.author,
|
|
413
|
+
description: puzzle.description,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
parsePuzzle(input) {
|
|
417
|
+
const { grid: gridString, ...metadata } = JSON.parse(input);
|
|
418
|
+
const grid = this.parseGrid(gridString);
|
|
419
|
+
const reset = grid.resetTiles();
|
|
420
|
+
return {
|
|
421
|
+
...metadata,
|
|
422
|
+
grid: reset,
|
|
423
|
+
solution: grid.colorEquals(reset) ? null : grid,
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Color, Position } from './primitives';
|
|
2
|
+
import TileData from './tile';
|
|
3
|
+
export interface ShapeElement {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
color: Color;
|
|
7
|
+
}
|
|
8
|
+
export interface Shape {
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
elements: ShapeElement[];
|
|
12
|
+
}
|
|
13
|
+
export declare function shapeEquals(a: Shape, b: Shape): boolean;
|
|
14
|
+
export declare function tilesToShape(tiles: readonly (readonly TileData[])[]): Shape;
|
|
15
|
+
export declare function positionsToShape(positions: Position[], color: Color): Shape;
|
|
16
|
+
export declare function getShapeVariants(shape: Shape): Shape[];
|
|
17
|
+
export declare function normalizeShape(shape: Shape): Shape;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Color } from './primitives';
|
|
2
|
+
const colorIndex = {
|
|
3
|
+
[Color.Dark]: 2,
|
|
4
|
+
[Color.Light]: 1,
|
|
5
|
+
[Color.Gray]: 0,
|
|
6
|
+
};
|
|
7
|
+
function compareColor(a, b) {
|
|
8
|
+
return colorIndex[a] - colorIndex[b];
|
|
9
|
+
}
|
|
10
|
+
function compareElement(a, b) {
|
|
11
|
+
if (!a && !b)
|
|
12
|
+
return 0;
|
|
13
|
+
if (!a)
|
|
14
|
+
return -1;
|
|
15
|
+
if (!b)
|
|
16
|
+
return 1;
|
|
17
|
+
return a.y - b.y || a.x - b.x || compareColor(a.color, b.color);
|
|
18
|
+
}
|
|
19
|
+
function compareShape(a, b) {
|
|
20
|
+
for (let i = 0; i < Math.max(a.elements.length, b.elements.length); i++) {
|
|
21
|
+
const cmp = compareElement(a.elements[i], b.elements[i]);
|
|
22
|
+
if (cmp !== 0)
|
|
23
|
+
return cmp;
|
|
24
|
+
}
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
export function shapeEquals(a, b) {
|
|
28
|
+
return compareShape(a, b) === 0;
|
|
29
|
+
}
|
|
30
|
+
function recenterShape(shape) {
|
|
31
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
32
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
33
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
34
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
35
|
+
for (const element of shape.elements) {
|
|
36
|
+
minX = Math.min(minX, element.x);
|
|
37
|
+
minY = Math.min(minY, element.y);
|
|
38
|
+
maxX = Math.max(maxX, element.x);
|
|
39
|
+
maxY = Math.max(maxY, element.y);
|
|
40
|
+
}
|
|
41
|
+
for (const element of shape.elements) {
|
|
42
|
+
element.x -= minX;
|
|
43
|
+
element.y -= minY;
|
|
44
|
+
}
|
|
45
|
+
shape.width = maxX - minX + 1;
|
|
46
|
+
shape.height = maxY - minY + 1;
|
|
47
|
+
return shape;
|
|
48
|
+
}
|
|
49
|
+
export function tilesToShape(tiles) {
|
|
50
|
+
const shape = {
|
|
51
|
+
width: Math.max(...tiles.map(row => row.length)),
|
|
52
|
+
height: tiles.length,
|
|
53
|
+
elements: [],
|
|
54
|
+
};
|
|
55
|
+
for (let y = 0; y < tiles.length; y++) {
|
|
56
|
+
for (let x = 0; x < tiles[y].length; x++) {
|
|
57
|
+
const tile = tiles[y][x];
|
|
58
|
+
if (tile.exists && tile.color !== Color.Gray) {
|
|
59
|
+
shape.elements.push({ x, y, color: tile.color });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return recenterShape(shape);
|
|
64
|
+
}
|
|
65
|
+
export function positionsToShape(positions, color) {
|
|
66
|
+
return recenterShape({
|
|
67
|
+
width: 0,
|
|
68
|
+
height: 0,
|
|
69
|
+
elements: positions.map(p => ({ x: p.x, y: p.y, color })),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const shapeVariants = [
|
|
73
|
+
{ x: 'x', y: 'y' },
|
|
74
|
+
{ x: '-y', y: 'x' },
|
|
75
|
+
{ x: '-x', y: '-y' },
|
|
76
|
+
{ x: 'y', y: '-x' },
|
|
77
|
+
{ x: '-x', y: 'y' },
|
|
78
|
+
{ x: 'x', y: '-y' },
|
|
79
|
+
{ x: 'y', y: 'x' },
|
|
80
|
+
{ x: '-y', y: '-x' },
|
|
81
|
+
];
|
|
82
|
+
function mapCoord(map, x, y, width, height) {
|
|
83
|
+
switch (map) {
|
|
84
|
+
case 'x':
|
|
85
|
+
return x;
|
|
86
|
+
case 'y':
|
|
87
|
+
return y;
|
|
88
|
+
case '-x':
|
|
89
|
+
return width - 1 - x;
|
|
90
|
+
case '-y':
|
|
91
|
+
return height - 1 - y;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export function getShapeVariants(shape) {
|
|
95
|
+
const variants = shapeVariants.map(({ x, y }) => ({
|
|
96
|
+
width: x.endsWith('x') ? shape.width : shape.height,
|
|
97
|
+
height: y.endsWith('y') ? shape.height : shape.width,
|
|
98
|
+
elements: shape.elements
|
|
99
|
+
.map(element => ({
|
|
100
|
+
x: mapCoord(x, element.x, element.y, shape.width, shape.height),
|
|
101
|
+
y: mapCoord(y, element.x, element.y, shape.width, shape.height),
|
|
102
|
+
color: element.color,
|
|
103
|
+
}))
|
|
104
|
+
.sort(compareElement),
|
|
105
|
+
}));
|
|
106
|
+
const uniqueVariants = [];
|
|
107
|
+
for (const variant of variants) {
|
|
108
|
+
if (!uniqueVariants.some(shape => shapeEquals(shape, variant))) {
|
|
109
|
+
uniqueVariants.push(variant);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return uniqueVariants;
|
|
113
|
+
}
|
|
114
|
+
export function normalizeShape(shape) {
|
|
115
|
+
const variants = getShapeVariants(shape);
|
|
116
|
+
return variants.reduce((min, variant) => (compareShape(variant, min) < 0 ? variant : min), variants[0]);
|
|
117
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import UndercluedSolver from './underclued/undercluedSolver';
|
|
2
|
+
import BacktrackSolver from './backtrack/backtrackSolver';
|
|
3
|
+
import Z3Solver from './z3/z3Solver';
|
|
4
|
+
const allSolvers = new Map();
|
|
5
|
+
function register(prototype) {
|
|
6
|
+
allSolvers.set(prototype.id, prototype);
|
|
7
|
+
}
|
|
8
|
+
register(new BacktrackSolver());
|
|
9
|
+
register(new UndercluedSolver());
|
|
10
|
+
register(new Z3Solver());
|
|
11
|
+
export { allSolvers };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import GridData from '../../grid';
|
|
2
|
+
import Solver from '../solver';
|
|
3
|
+
export default class BacktrackSolver extends Solver {
|
|
4
|
+
private static readonly supportedInstrs;
|
|
5
|
+
readonly id = "backtrack";
|
|
6
|
+
readonly description = "Solves puzzles using backtracking with optimizations (blazingly fast). Support most rules and symbols (including underclued).";
|
|
7
|
+
solve(grid: GridData): AsyncGenerator<GridData | null>;
|
|
8
|
+
isInstructionSupported(instructionId: string): boolean;
|
|
9
|
+
}
|