cubegin 0.0.1
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/CHANGELOG.md +17 -0
- package/LICENSE +674 -0
- package/NOTICE +11 -0
- package/README.md +49 -0
- package/dist/scramble-core/src/batch.mjs +18 -0
- package/dist/scramble-core/src/generator.d.mts +35 -0
- package/dist/scramble-core/src/generator.mjs +136 -0
- package/dist/scramble-core/src/generators/clock.d.mts +11 -0
- package/dist/scramble-core/src/generators/clock.mjs +32 -0
- package/dist/scramble-core/src/generators/cube-random-turns.d.mts +11 -0
- package/dist/scramble-core/src/generators/cube-random-turns.mjs +54 -0
- package/dist/scramble-core/src/generators/four-by-four.d.mts +14 -0
- package/dist/scramble-core/src/generators/four-by-four.mjs +43 -0
- package/dist/scramble-core/src/generators/megaminx.d.mts +11 -0
- package/dist/scramble-core/src/generators/megaminx.mjs +18 -0
- package/dist/scramble-core/src/generators/pyraminx.d.mts +11 -0
- package/dist/scramble-core/src/generators/pyraminx.mjs +17 -0
- package/dist/scramble-core/src/generators/skewb.d.mts +11 -0
- package/dist/scramble-core/src/generators/skewb.mjs +17 -0
- package/dist/scramble-core/src/generators/square1.d.mts +11 -0
- package/dist/scramble-core/src/generators/square1.mjs +28 -0
- package/dist/scramble-core/src/generators/three-by-three.d.mts +25 -0
- package/dist/scramble-core/src/generators/three-by-three.mjs +85 -0
- package/dist/scramble-core/src/generators/two-by-two.d.mts +11 -0
- package/dist/scramble-core/src/generators/two-by-two.mjs +17 -0
- package/dist/scramble-core/src/random-source.d.mts +7 -0
- package/dist/scramble-core/src/random-source.mjs +8 -0
- package/dist/scramble-core/src/solvers/min2phase/coord-cube.mjs +10 -0
- package/dist/scramble-core/src/solvers/min2phase/cubie-cube.mjs +246 -0
- package/dist/scramble-core/src/solvers/min2phase/engine.mjs +1281 -0
- package/dist/scramble-core/src/solvers/min2phase/search-wca.mjs +21 -0
- package/dist/scramble-core/src/solvers/min2phase/search.mjs +25 -0
- package/dist/scramble-core/src/solvers/min2phase/tools.mjs +169 -0
- package/dist/scramble-core/src/solvers/min2phase/util.mjs +30 -0
- package/dist/scramble-core/src/solvers/pyraminx-solver.d.mts +17 -0
- package/dist/scramble-core/src/solvers/pyraminx-solver.mjs +350 -0
- package/dist/scramble-core/src/solvers/skewb-solver.d.mts +15 -0
- package/dist/scramble-core/src/solvers/skewb-solver.mjs +399 -0
- package/dist/scramble-core/src/solvers/sq12phase/full-cube.mjs +212 -0
- package/dist/scramble-core/src/solvers/sq12phase/search.mjs +520 -0
- package/dist/scramble-core/src/solvers/sq12phase/shape.mjs +214 -0
- package/dist/scramble-core/src/solvers/sq12phase/square.mjs +135 -0
- package/dist/scramble-core/src/solvers/threephase/center.mjs +798 -0
- package/dist/scramble-core/src/solvers/threephase/edge.mjs +632 -0
- package/dist/scramble-core/src/solvers/threephase/full-cube.mjs +554 -0
- package/dist/scramble-core/src/solvers/threephase/search.mjs +262 -0
- package/dist/scramble-core/src/solvers/threephase/tables.mjs +201 -0
- package/dist/scramble-core/src/solvers/two-by-two-solver.d.mts +15 -0
- package/dist/scramble-core/src/solvers/two-by-two-solver.mjs +298 -0
- package/dist/scramble-core.d.mts +15 -0
- package/dist/scramble-core.mjs +15 -0
- package/dist/scramble-image/src/color.d.mts +12 -0
- package/dist/scramble-image/src/color.mjs +11 -0
- package/dist/scramble-image/src/render.d.mts +10 -0
- package/dist/scramble-image/src/render.mjs +71 -0
- package/dist/scramble-image/src/renderers/clock.d.mts +6 -0
- package/dist/scramble-image/src/renderers/clock.mjs +145 -0
- package/dist/scramble-image/src/renderers/cube-isometric.d.mts +8 -0
- package/dist/scramble-image/src/renderers/cube-isometric.mjs +204 -0
- package/dist/scramble-image/src/renderers/cube-net.d.mts +8 -0
- package/dist/scramble-image/src/renderers/cube-net.mjs +52 -0
- package/dist/scramble-image/src/renderers/megaminx-isometric.d.mts +9 -0
- package/dist/scramble-image/src/renderers/megaminx-isometric.mjs +320 -0
- package/dist/scramble-image/src/renderers/megaminx.d.mts +9 -0
- package/dist/scramble-image/src/renderers/megaminx.mjs +173 -0
- package/dist/scramble-image/src/renderers/pyraminx-isometric.d.mts +9 -0
- package/dist/scramble-image/src/renderers/pyraminx-isometric.mjs +185 -0
- package/dist/scramble-image/src/renderers/pyraminx.d.mts +9 -0
- package/dist/scramble-image/src/renderers/pyraminx.mjs +111 -0
- package/dist/scramble-image/src/renderers/skewb-isometric.d.mts +9 -0
- package/dist/scramble-image/src/renderers/skewb-isometric.mjs +233 -0
- package/dist/scramble-image/src/renderers/skewb.d.mts +9 -0
- package/dist/scramble-image/src/renderers/skewb.mjs +187 -0
- package/dist/scramble-image/src/renderers/square1.d.mts +10 -0
- package/dist/scramble-image/src/renderers/square1.mjs +253 -0
- package/dist/scramble-image/src/svg/svg-document.d.mts +6 -0
- package/dist/scramble-image/src/svg/svg-document.mjs +7 -0
- package/dist/scramble-image/src/svg/svg-elements.d.mts +15 -0
- package/dist/scramble-image/src/svg/svg-elements.mjs +25 -0
- package/dist/scramble-image/src/svg/svg-serialize.mjs +29 -0
- package/dist/scramble-image.d.mts +15 -0
- package/dist/scramble-image.mjs +15 -0
- package/dist/scramble-puzzle/src/algorithm.d.mts +8 -0
- package/dist/scramble-puzzle/src/algorithm.mjs +16 -0
- package/dist/scramble-puzzle/src/algorithm2.mjs +16 -0
- package/dist/scramble-puzzle/src/clock/clock-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/clock/clock-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/clock/clock-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/clock/clock-parser.d.mts +18 -0
- package/dist/scramble-puzzle/src/clock/clock-parser.mjs +35 -0
- package/dist/scramble-puzzle/src/clock/clock-parser2.mjs +35 -0
- package/dist/scramble-puzzle/src/clock/clock-state.d.mts +8 -0
- package/dist/scramble-puzzle/src/clock/clock-state.mjs +212 -0
- package/dist/scramble-puzzle/src/clock/clock-state2.d.mts +13 -0
- package/dist/scramble-puzzle/src/clock/clock-state2.mjs +212 -0
- package/dist/scramble-puzzle/src/cube/cube-definition.d.mts +9 -0
- package/dist/scramble-puzzle/src/cube/cube-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/cube/cube-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/cube/cube-move.d.mts +4 -0
- package/dist/scramble-puzzle/src/cube/cube-move2.d.mts +17 -0
- package/dist/scramble-puzzle/src/cube/cube-parser.d.mts +7 -0
- package/dist/scramble-puzzle/src/cube/cube-parser.mjs +60 -0
- package/dist/scramble-puzzle/src/cube/cube-parser2.mjs +60 -0
- package/dist/scramble-puzzle/src/cube/cube-state.d.mts +12 -0
- package/dist/scramble-puzzle/src/cube/cube-state.mjs +187 -0
- package/dist/scramble-puzzle/src/cube/cube-state2.d.mts +15 -0
- package/dist/scramble-puzzle/src/cube/cube-state2.mjs +187 -0
- package/dist/scramble-puzzle/src/errors.d.mts +15 -0
- package/dist/scramble-puzzle/src/errors.mjs +24 -0
- package/dist/scramble-puzzle/src/errors2.mjs +30 -0
- package/dist/scramble-puzzle/src/events.d.mts +5 -0
- package/dist/scramble-puzzle/src/events.mjs +90 -0
- package/dist/scramble-puzzle/src/events2.d.mts +98 -0
- package/dist/scramble-puzzle/src/events2.mjs +109 -0
- package/dist/scramble-puzzle/src/index.mjs +22 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-parser.d.mts +5 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-parser.mjs +57 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-parser2.d.mts +20 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-parser2.mjs +57 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-state.d.mts +9 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-state.mjs +112 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-state2.d.mts +14 -0
- package/dist/scramble-puzzle/src/megaminx/megaminx-state2.mjs +112 -0
- package/dist/scramble-puzzle/src/puzzle-definition.d.mts +19 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser.d.mts +5 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser.mjs +34 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser2.d.mts +21 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser2.mjs +34 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-state.d.mts +11 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-state.mjs +90 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-state2.d.mts +14 -0
- package/dist/scramble-puzzle/src/pyraminx/pyraminx-state2.mjs +90 -0
- package/dist/scramble-puzzle/src/registry.d.mts +11 -0
- package/dist/scramble-puzzle/src/registry.mjs +13 -0
- package/dist/scramble-puzzle/src/skewb/skewb-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/skewb/skewb-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/skewb/skewb-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/skewb/skewb-parser.d.mts +5 -0
- package/dist/scramble-puzzle/src/skewb/skewb-parser.mjs +33 -0
- package/dist/scramble-puzzle/src/skewb/skewb-parser2.d.mts +14 -0
- package/dist/scramble-puzzle/src/skewb/skewb-parser2.mjs +33 -0
- package/dist/scramble-puzzle/src/skewb/skewb-state.d.mts +11 -0
- package/dist/scramble-puzzle/src/skewb/skewb-state.mjs +75 -0
- package/dist/scramble-puzzle/src/skewb/skewb-state2.d.mts +14 -0
- package/dist/scramble-puzzle/src/skewb/skewb-state2.mjs +75 -0
- package/dist/scramble-puzzle/src/square1/square1-definition.d.mts +8 -0
- package/dist/scramble-puzzle/src/square1/square1-definition.mjs +18 -0
- package/dist/scramble-puzzle/src/square1/square1-definition2.mjs +18 -0
- package/dist/scramble-puzzle/src/square1/square1-parser.d.mts +17 -0
- package/dist/scramble-puzzle/src/square1/square1-parser.mjs +43 -0
- package/dist/scramble-puzzle/src/square1/square1-parser2.mjs +47 -0
- package/dist/scramble-puzzle/src/square1/square1-state.d.mts +9 -0
- package/dist/scramble-puzzle/src/square1/square1-state.mjs +115 -0
- package/dist/scramble-puzzle/src/square1/square1-state2.d.mts +21 -0
- package/dist/scramble-puzzle/src/square1/square1-state2.mjs +115 -0
- package/dist/scramble-puzzle.d.mts +25 -0
- package/dist/scramble-puzzle.mjs +23 -0
- package/package.json +37 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { InvalidMoveError } from "../errors2.mjs";
|
|
2
|
+
import { CLOCK_TURN_NAMES } from "./clock-parser2.mjs";
|
|
3
|
+
//#region .build/vendor/scramble-puzzle/src/clock/clock-state.ts
|
|
4
|
+
const MALFORMED_MOVE = "<malformed>";
|
|
5
|
+
const CLOCK_MOVE_DELTAS = new Map([
|
|
6
|
+
["UR", [
|
|
7
|
+
0,
|
|
8
|
+
1,
|
|
9
|
+
1,
|
|
10
|
+
0,
|
|
11
|
+
1,
|
|
12
|
+
1,
|
|
13
|
+
0,
|
|
14
|
+
0,
|
|
15
|
+
0,
|
|
16
|
+
-1,
|
|
17
|
+
0,
|
|
18
|
+
0,
|
|
19
|
+
0,
|
|
20
|
+
0,
|
|
21
|
+
0,
|
|
22
|
+
0,
|
|
23
|
+
0,
|
|
24
|
+
0
|
|
25
|
+
]],
|
|
26
|
+
["DR", [
|
|
27
|
+
0,
|
|
28
|
+
0,
|
|
29
|
+
0,
|
|
30
|
+
0,
|
|
31
|
+
1,
|
|
32
|
+
1,
|
|
33
|
+
0,
|
|
34
|
+
1,
|
|
35
|
+
1,
|
|
36
|
+
0,
|
|
37
|
+
0,
|
|
38
|
+
0,
|
|
39
|
+
0,
|
|
40
|
+
0,
|
|
41
|
+
0,
|
|
42
|
+
-1,
|
|
43
|
+
0,
|
|
44
|
+
0
|
|
45
|
+
]],
|
|
46
|
+
["DL", [
|
|
47
|
+
0,
|
|
48
|
+
0,
|
|
49
|
+
0,
|
|
50
|
+
1,
|
|
51
|
+
1,
|
|
52
|
+
0,
|
|
53
|
+
1,
|
|
54
|
+
1,
|
|
55
|
+
0,
|
|
56
|
+
0,
|
|
57
|
+
0,
|
|
58
|
+
0,
|
|
59
|
+
0,
|
|
60
|
+
0,
|
|
61
|
+
0,
|
|
62
|
+
0,
|
|
63
|
+
0,
|
|
64
|
+
-1
|
|
65
|
+
]],
|
|
66
|
+
["UL", [
|
|
67
|
+
1,
|
|
68
|
+
1,
|
|
69
|
+
0,
|
|
70
|
+
1,
|
|
71
|
+
1,
|
|
72
|
+
0,
|
|
73
|
+
0,
|
|
74
|
+
0,
|
|
75
|
+
0,
|
|
76
|
+
0,
|
|
77
|
+
0,
|
|
78
|
+
-1,
|
|
79
|
+
0,
|
|
80
|
+
0,
|
|
81
|
+
0,
|
|
82
|
+
0,
|
|
83
|
+
0,
|
|
84
|
+
0
|
|
85
|
+
]],
|
|
86
|
+
["U", [
|
|
87
|
+
1,
|
|
88
|
+
1,
|
|
89
|
+
1,
|
|
90
|
+
1,
|
|
91
|
+
1,
|
|
92
|
+
1,
|
|
93
|
+
0,
|
|
94
|
+
0,
|
|
95
|
+
0,
|
|
96
|
+
-1,
|
|
97
|
+
0,
|
|
98
|
+
-1,
|
|
99
|
+
0,
|
|
100
|
+
0,
|
|
101
|
+
0,
|
|
102
|
+
0,
|
|
103
|
+
0,
|
|
104
|
+
0
|
|
105
|
+
]],
|
|
106
|
+
["R", [
|
|
107
|
+
0,
|
|
108
|
+
1,
|
|
109
|
+
1,
|
|
110
|
+
0,
|
|
111
|
+
1,
|
|
112
|
+
1,
|
|
113
|
+
0,
|
|
114
|
+
1,
|
|
115
|
+
1,
|
|
116
|
+
-1,
|
|
117
|
+
0,
|
|
118
|
+
0,
|
|
119
|
+
0,
|
|
120
|
+
0,
|
|
121
|
+
0,
|
|
122
|
+
-1,
|
|
123
|
+
0,
|
|
124
|
+
0
|
|
125
|
+
]],
|
|
126
|
+
["D", [
|
|
127
|
+
0,
|
|
128
|
+
0,
|
|
129
|
+
0,
|
|
130
|
+
1,
|
|
131
|
+
1,
|
|
132
|
+
1,
|
|
133
|
+
1,
|
|
134
|
+
1,
|
|
135
|
+
1,
|
|
136
|
+
0,
|
|
137
|
+
0,
|
|
138
|
+
0,
|
|
139
|
+
0,
|
|
140
|
+
0,
|
|
141
|
+
0,
|
|
142
|
+
-1,
|
|
143
|
+
0,
|
|
144
|
+
-1
|
|
145
|
+
]],
|
|
146
|
+
["L", [
|
|
147
|
+
1,
|
|
148
|
+
1,
|
|
149
|
+
0,
|
|
150
|
+
1,
|
|
151
|
+
1,
|
|
152
|
+
0,
|
|
153
|
+
1,
|
|
154
|
+
1,
|
|
155
|
+
0,
|
|
156
|
+
0,
|
|
157
|
+
0,
|
|
158
|
+
-1,
|
|
159
|
+
0,
|
|
160
|
+
0,
|
|
161
|
+
0,
|
|
162
|
+
0,
|
|
163
|
+
0,
|
|
164
|
+
-1
|
|
165
|
+
]],
|
|
166
|
+
["ALL", [
|
|
167
|
+
1,
|
|
168
|
+
1,
|
|
169
|
+
1,
|
|
170
|
+
1,
|
|
171
|
+
1,
|
|
172
|
+
1,
|
|
173
|
+
1,
|
|
174
|
+
1,
|
|
175
|
+
1,
|
|
176
|
+
-1,
|
|
177
|
+
0,
|
|
178
|
+
-1,
|
|
179
|
+
0,
|
|
180
|
+
0,
|
|
181
|
+
0,
|
|
182
|
+
-1,
|
|
183
|
+
0,
|
|
184
|
+
-1
|
|
185
|
+
]]
|
|
186
|
+
]);
|
|
187
|
+
const createClockState = (positions, rightSideUp) => {
|
|
188
|
+
if (positions.length !== 18) throw new RangeError(`clock state must contain 18 dial positions: ${positions.length}`);
|
|
189
|
+
return Object.freeze({
|
|
190
|
+
positions: Object.freeze([...positions]),
|
|
191
|
+
rightSideUp
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
const validateMove = (move) => {
|
|
195
|
+
if (typeof move !== "object" || move === null) throw new InvalidMoveError(MALFORMED_MOVE, "clock");
|
|
196
|
+
if (move.type === "rotation") return move;
|
|
197
|
+
if (move.type !== "turn" || !CLOCK_TURN_NAMES.includes(move.name) || move.direction !== "+" && move.direction !== "-" || !Number.isSafeInteger(move.amount) || move.amount < 0 || move.amount > 6 || move.direction === "-" && (move.amount === 0 || move.amount === 6)) throw new InvalidMoveError(MALFORMED_MOVE, "clock");
|
|
198
|
+
return move;
|
|
199
|
+
};
|
|
200
|
+
const moduloClock = (position) => (position % 12 + 12) % 12;
|
|
201
|
+
const createSolvedClockState = () => createClockState(Array(18).fill(0), true);
|
|
202
|
+
const applyClockMove = (state, move) => {
|
|
203
|
+
const validMove = validateMove(move);
|
|
204
|
+
if (validMove.type === "rotation") return createClockState([...state.positions.slice(9), ...state.positions.slice(0, 9)], !state.rightSideUp);
|
|
205
|
+
const deltas = CLOCK_MOVE_DELTAS.get(validMove.name);
|
|
206
|
+
if (deltas === void 0) throw new InvalidMoveError(MALFORMED_MOVE, "clock");
|
|
207
|
+
const signedAmount = validMove.direction === "+" ? validMove.amount : -validMove.amount;
|
|
208
|
+
return createClockState(state.positions.map((position, index) => moduloClock(position + signedAmount * (deltas[index] ?? 0))), state.rightSideUp);
|
|
209
|
+
};
|
|
210
|
+
const areClockStatesEqual = (a, b) => a.rightSideUp === b.rightSideUp && a.positions.every((position, index) => position === b.positions[index]);
|
|
211
|
+
//#endregion
|
|
212
|
+
export { applyClockMove, areClockStatesEqual, createSolvedClockState };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WcaEventId } from "../events2.mjs";
|
|
2
|
+
import { PuzzleDefinition } from "../puzzle-definition.mjs";
|
|
3
|
+
import { CubeMove } from "./cube-move2.mjs";
|
|
4
|
+
import { CubeState } from "./cube-state2.mjs";
|
|
5
|
+
|
|
6
|
+
//#region .build/vendor/scramble-puzzle/src/cube/cube-definition.d.ts
|
|
7
|
+
declare const createCubeDefinition: (size: number, eventIds: readonly WcaEventId[]) => PuzzleDefinition<CubeState, CubeMove>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { createCubeDefinition };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { applyAlgorithm } from "../algorithm.mjs";
|
|
2
|
+
import { parseCubeAlgorithm } from "./cube-parser.mjs";
|
|
3
|
+
import { applyCubeMove, areCubeStatesEqual, createSolvedCubeState } from "./cube-state.mjs";
|
|
4
|
+
//#region ../scramble-puzzle/src/cube/cube-definition.ts
|
|
5
|
+
const createCubeDefinition = (size, eventIds) => {
|
|
6
|
+
const definition = {
|
|
7
|
+
id: `cube-${size}`,
|
|
8
|
+
eventIds,
|
|
9
|
+
createSolvedState: () => createSolvedCubeState(size),
|
|
10
|
+
parseAlgorithm: parseCubeAlgorithm,
|
|
11
|
+
applyMove: applyCubeMove,
|
|
12
|
+
applyAlgorithm: (state, algorithm) => applyAlgorithm(definition, state, algorithm),
|
|
13
|
+
isSolved: (state) => areCubeStatesEqual(state, createSolvedCubeState(size))
|
|
14
|
+
};
|
|
15
|
+
return definition;
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { createCubeDefinition };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { applyAlgorithm } from "../algorithm2.mjs";
|
|
2
|
+
import { parseCubeAlgorithm } from "./cube-parser2.mjs";
|
|
3
|
+
import { applyCubeMove, areCubeStatesEqual, createSolvedCubeState } from "./cube-state2.mjs";
|
|
4
|
+
//#region .build/vendor/scramble-puzzle/src/cube/cube-definition.ts
|
|
5
|
+
const createCubeDefinition = (size, eventIds) => {
|
|
6
|
+
const definition = {
|
|
7
|
+
id: `cube-${size}`,
|
|
8
|
+
eventIds,
|
|
9
|
+
createSolvedState: () => createSolvedCubeState(size),
|
|
10
|
+
parseAlgorithm: parseCubeAlgorithm,
|
|
11
|
+
applyMove: applyCubeMove,
|
|
12
|
+
applyAlgorithm: (state, algorithm) => applyAlgorithm(definition, state, algorithm),
|
|
13
|
+
isSolved: (state) => areCubeStatesEqual(state, createSolvedCubeState(size))
|
|
14
|
+
};
|
|
15
|
+
return definition;
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { createCubeDefinition };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region .build/vendor/scramble-puzzle/src/cube/cube-move.d.ts
|
|
2
|
+
type CubeFace = 'R' | 'U' | 'F' | 'L' | 'D' | 'B';
|
|
3
|
+
interface CubeLayerMove {
|
|
4
|
+
face: CubeFace;
|
|
5
|
+
amount: 1 | 2 | 3;
|
|
6
|
+
width: number;
|
|
7
|
+
isRotation: false;
|
|
8
|
+
}
|
|
9
|
+
interface CubeRotationMove {
|
|
10
|
+
face: CubeFace;
|
|
11
|
+
amount: 1 | 2 | 3;
|
|
12
|
+
width: number;
|
|
13
|
+
isRotation: true;
|
|
14
|
+
}
|
|
15
|
+
type CubeMove = CubeLayerMove | CubeRotationMove;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { CubeFace, CubeLayerMove, CubeMove, CubeRotationMove };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CubeMove } from "./cube-move2.mjs";
|
|
2
|
+
|
|
3
|
+
//#region .build/vendor/scramble-puzzle/src/cube/cube-parser.d.ts
|
|
4
|
+
declare const parseCubeMove: (token: string) => CubeMove;
|
|
5
|
+
declare const parseCubeAlgorithm: (algorithm: string) => readonly CubeMove[];
|
|
6
|
+
//#endregion
|
|
7
|
+
export { parseCubeAlgorithm, parseCubeMove };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { InvalidMoveError } from "../errors.mjs";
|
|
2
|
+
import { splitAlgorithm } from "../algorithm.mjs";
|
|
3
|
+
//#region ../scramble-puzzle/src/cube/cube-parser.ts
|
|
4
|
+
const CUBE_MOVE_PATTERN = /^(?:(\d+)?([RUFLDB])w|([RUFLDB])|([xyz]))(2|')?$/;
|
|
5
|
+
const parseAmount = (suffix) => {
|
|
6
|
+
if (suffix === "2") return 2;
|
|
7
|
+
if (suffix === "'") return 3;
|
|
8
|
+
return 1;
|
|
9
|
+
};
|
|
10
|
+
const parseCubeFace = (face) => {
|
|
11
|
+
switch (face) {
|
|
12
|
+
case "R":
|
|
13
|
+
case "U":
|
|
14
|
+
case "F":
|
|
15
|
+
case "L":
|
|
16
|
+
case "D":
|
|
17
|
+
case "B": return face;
|
|
18
|
+
default: return;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const parseRotationFace = (rotation) => {
|
|
22
|
+
switch (rotation) {
|
|
23
|
+
case "x": return "R";
|
|
24
|
+
case "y": return "U";
|
|
25
|
+
case "z": return "F";
|
|
26
|
+
default: return;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const parseWideMoveWidth = (token, prefixWidth) => {
|
|
30
|
+
if (prefixWidth === void 0) return 2;
|
|
31
|
+
const width = Number(prefixWidth);
|
|
32
|
+
if (prefixWidth.startsWith("0") || !Number.isSafeInteger(width) || width < 3) throw new InvalidMoveError(token, "cube");
|
|
33
|
+
return width;
|
|
34
|
+
};
|
|
35
|
+
const parseCubeMove = (token) => {
|
|
36
|
+
const match = token.match(CUBE_MOVE_PATTERN);
|
|
37
|
+
if (!match) throw new InvalidMoveError(token, "cube");
|
|
38
|
+
const [, prefixWidth, wideFace, face, rotation, suffix] = match;
|
|
39
|
+
if (rotation !== void 0) {
|
|
40
|
+
const rotationFace = parseRotationFace(rotation);
|
|
41
|
+
if (rotationFace === void 0) throw new InvalidMoveError(token, "cube");
|
|
42
|
+
return {
|
|
43
|
+
face: rotationFace,
|
|
44
|
+
amount: parseAmount(suffix),
|
|
45
|
+
width: Number.POSITIVE_INFINITY,
|
|
46
|
+
isRotation: true
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const layerFace = parseCubeFace(wideFace ?? face);
|
|
50
|
+
if (layerFace === void 0) throw new InvalidMoveError(token, "cube");
|
|
51
|
+
return {
|
|
52
|
+
face: layerFace,
|
|
53
|
+
amount: parseAmount(suffix),
|
|
54
|
+
width: wideFace ? parseWideMoveWidth(token, prefixWidth) : 1,
|
|
55
|
+
isRotation: false
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
const parseCubeAlgorithm = (algorithm) => splitAlgorithm(algorithm).map(parseCubeMove);
|
|
59
|
+
//#endregion
|
|
60
|
+
export { parseCubeAlgorithm, parseCubeMove };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { InvalidMoveError } from "../errors2.mjs";
|
|
2
|
+
import { splitAlgorithm } from "../algorithm2.mjs";
|
|
3
|
+
//#region .build/vendor/scramble-puzzle/src/cube/cube-parser.ts
|
|
4
|
+
const CUBE_MOVE_PATTERN = /^(?:(\d+)?([RUFLDB])w|([RUFLDB])|([xyz]))(2|')?$/;
|
|
5
|
+
const parseAmount = (suffix) => {
|
|
6
|
+
if (suffix === "2") return 2;
|
|
7
|
+
if (suffix === "'") return 3;
|
|
8
|
+
return 1;
|
|
9
|
+
};
|
|
10
|
+
const parseCubeFace = (face) => {
|
|
11
|
+
switch (face) {
|
|
12
|
+
case "R":
|
|
13
|
+
case "U":
|
|
14
|
+
case "F":
|
|
15
|
+
case "L":
|
|
16
|
+
case "D":
|
|
17
|
+
case "B": return face;
|
|
18
|
+
default: return;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const parseRotationFace = (rotation) => {
|
|
22
|
+
switch (rotation) {
|
|
23
|
+
case "x": return "R";
|
|
24
|
+
case "y": return "U";
|
|
25
|
+
case "z": return "F";
|
|
26
|
+
default: return;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const parseWideMoveWidth = (token, prefixWidth) => {
|
|
30
|
+
if (prefixWidth === void 0) return 2;
|
|
31
|
+
const width = Number(prefixWidth);
|
|
32
|
+
if (prefixWidth.startsWith("0") || !Number.isSafeInteger(width) || width < 3) throw new InvalidMoveError(token, "cube");
|
|
33
|
+
return width;
|
|
34
|
+
};
|
|
35
|
+
const parseCubeMove = (token) => {
|
|
36
|
+
const match = token.match(CUBE_MOVE_PATTERN);
|
|
37
|
+
if (!match) throw new InvalidMoveError(token, "cube");
|
|
38
|
+
const [, prefixWidth, wideFace, face, rotation, suffix] = match;
|
|
39
|
+
if (rotation !== void 0) {
|
|
40
|
+
const rotationFace = parseRotationFace(rotation);
|
|
41
|
+
if (rotationFace === void 0) throw new InvalidMoveError(token, "cube");
|
|
42
|
+
return {
|
|
43
|
+
face: rotationFace,
|
|
44
|
+
amount: parseAmount(suffix),
|
|
45
|
+
width: Number.POSITIVE_INFINITY,
|
|
46
|
+
isRotation: true
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const layerFace = parseCubeFace(wideFace ?? face);
|
|
50
|
+
if (layerFace === void 0) throw new InvalidMoveError(token, "cube");
|
|
51
|
+
return {
|
|
52
|
+
face: layerFace,
|
|
53
|
+
amount: parseAmount(suffix),
|
|
54
|
+
width: wideFace ? parseWideMoveWidth(token, prefixWidth) : 1,
|
|
55
|
+
isRotation: false
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
const parseCubeAlgorithm = (algorithm) => splitAlgorithm(algorithm).map(parseCubeMove);
|
|
59
|
+
//#endregion
|
|
60
|
+
export { parseCubeAlgorithm, parseCubeMove };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CubeFace } from "./cube-move.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../scramble-puzzle/src/cube/cube-state.d.ts
|
|
4
|
+
type CubeFacelet = CubeFace;
|
|
5
|
+
type CubeFaceState = readonly (readonly CubeFacelet[])[];
|
|
6
|
+
type CubeImage = readonly CubeFaceState[];
|
|
7
|
+
interface CubeState {
|
|
8
|
+
readonly size: number;
|
|
9
|
+
readonly image: CubeImage;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { CubeFacelet, CubeState };
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { InvalidMoveError } from "../errors.mjs";
|
|
2
|
+
//#region ../scramble-puzzle/src/cube/cube-state.ts
|
|
3
|
+
const CUBE_FACES = [
|
|
4
|
+
"R",
|
|
5
|
+
"U",
|
|
6
|
+
"F",
|
|
7
|
+
"L",
|
|
8
|
+
"D",
|
|
9
|
+
"B"
|
|
10
|
+
];
|
|
11
|
+
const faceIndex = (face) => CUBE_FACES.indexOf(face);
|
|
12
|
+
const isCubeFace = (face) => typeof face === "string" && CUBE_FACES.includes(face);
|
|
13
|
+
const isMoveAmount = (amount) => amount === 1 || amount === 2 || amount === 3;
|
|
14
|
+
const oppositeFace = (face) => CUBE_FACES[(faceIndex(face) + 3) % CUBE_FACES.length];
|
|
15
|
+
const cloneCubeImage = (image) => image.map((face) => face.map((row) => [...row]));
|
|
16
|
+
const freezeCubeImage = (image) => {
|
|
17
|
+
const frozenFaces = image.map((face) => {
|
|
18
|
+
const frozenRows = face.map((row) => Object.freeze([...row]));
|
|
19
|
+
return Object.freeze(frozenRows);
|
|
20
|
+
});
|
|
21
|
+
return Object.freeze(frozenFaces);
|
|
22
|
+
};
|
|
23
|
+
const createCubeState = (size, image) => Object.freeze({
|
|
24
|
+
size,
|
|
25
|
+
image: freezeCubeImage(image)
|
|
26
|
+
});
|
|
27
|
+
const swap = (image, first, second, third, fourth, direction) => {
|
|
28
|
+
const [firstFace, firstRow, firstColumn] = first;
|
|
29
|
+
const [secondFace, secondRow, secondColumn] = second;
|
|
30
|
+
const [thirdFace, thirdRow, thirdColumn] = third;
|
|
31
|
+
const [fourthFace, fourthRow, fourthColumn] = fourth;
|
|
32
|
+
if (direction === 1) {
|
|
33
|
+
const firstSticker = image[firstFace][firstRow][firstColumn];
|
|
34
|
+
image[firstFace][firstRow][firstColumn] = image[secondFace][secondRow][secondColumn];
|
|
35
|
+
image[secondFace][secondRow][secondColumn] = image[thirdFace][thirdRow][thirdColumn];
|
|
36
|
+
image[thirdFace][thirdRow][thirdColumn] = image[fourthFace][fourthRow][fourthColumn];
|
|
37
|
+
image[fourthFace][fourthRow][fourthColumn] = firstSticker;
|
|
38
|
+
} else {
|
|
39
|
+
const fourthSticker = image[fourthFace][fourthRow][fourthColumn];
|
|
40
|
+
image[fourthFace][fourthRow][fourthColumn] = image[thirdFace][thirdRow][thirdColumn];
|
|
41
|
+
image[thirdFace][thirdRow][thirdColumn] = image[secondFace][secondRow][secondColumn];
|
|
42
|
+
image[secondFace][secondRow][secondColumn] = image[firstFace][firstRow][firstColumn];
|
|
43
|
+
image[firstFace][firstRow][firstColumn] = fourthSticker;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const rotateFace = (image, face, direction) => {
|
|
47
|
+
const size = image[0].length;
|
|
48
|
+
const facePosition = faceIndex(face);
|
|
49
|
+
const rowLimit = Math.floor((size + 1) / 2);
|
|
50
|
+
const columnLimit = Math.floor(size / 2);
|
|
51
|
+
for (let row = 0; row < rowLimit; row += 1) for (let column = 0; column < columnLimit; column += 1) {
|
|
52
|
+
const cycle = [
|
|
53
|
+
[
|
|
54
|
+
facePosition,
|
|
55
|
+
row,
|
|
56
|
+
column
|
|
57
|
+
],
|
|
58
|
+
[
|
|
59
|
+
facePosition,
|
|
60
|
+
column,
|
|
61
|
+
size - 1 - row
|
|
62
|
+
],
|
|
63
|
+
[
|
|
64
|
+
facePosition,
|
|
65
|
+
size - 1 - row,
|
|
66
|
+
size - 1 - column
|
|
67
|
+
],
|
|
68
|
+
[
|
|
69
|
+
facePosition,
|
|
70
|
+
size - 1 - column,
|
|
71
|
+
row
|
|
72
|
+
]
|
|
73
|
+
];
|
|
74
|
+
if (direction === 1) swap(image, cycle[0], cycle[1], cycle[2], cycle[3], 1);
|
|
75
|
+
else swap(image, cycle[0], cycle[1], cycle[2], cycle[3], 3);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const slice = (face, sliceIndex, image) => {
|
|
79
|
+
const size = image[0].length;
|
|
80
|
+
let sliceFace = face;
|
|
81
|
+
let stateSliceIndex = sliceIndex;
|
|
82
|
+
let direction = 1;
|
|
83
|
+
if (face !== "L" && face !== "D" && face !== "B") {
|
|
84
|
+
sliceFace = oppositeFace(face);
|
|
85
|
+
stateSliceIndex = size - 1 - sliceIndex;
|
|
86
|
+
direction = 3;
|
|
87
|
+
}
|
|
88
|
+
for (let position = 0; position < size; position += 1) if (sliceFace === "L") swap(image, [
|
|
89
|
+
faceIndex("U"),
|
|
90
|
+
position,
|
|
91
|
+
stateSliceIndex
|
|
92
|
+
], [
|
|
93
|
+
faceIndex("B"),
|
|
94
|
+
size - 1 - position,
|
|
95
|
+
size - 1 - stateSliceIndex
|
|
96
|
+
], [
|
|
97
|
+
faceIndex("D"),
|
|
98
|
+
position,
|
|
99
|
+
stateSliceIndex
|
|
100
|
+
], [
|
|
101
|
+
faceIndex("F"),
|
|
102
|
+
position,
|
|
103
|
+
stateSliceIndex
|
|
104
|
+
], direction);
|
|
105
|
+
else if (sliceFace === "D") swap(image, [
|
|
106
|
+
faceIndex("L"),
|
|
107
|
+
size - 1 - stateSliceIndex,
|
|
108
|
+
position
|
|
109
|
+
], [
|
|
110
|
+
faceIndex("B"),
|
|
111
|
+
size - 1 - stateSliceIndex,
|
|
112
|
+
position
|
|
113
|
+
], [
|
|
114
|
+
faceIndex("R"),
|
|
115
|
+
size - 1 - stateSliceIndex,
|
|
116
|
+
position
|
|
117
|
+
], [
|
|
118
|
+
faceIndex("F"),
|
|
119
|
+
size - 1 - stateSliceIndex,
|
|
120
|
+
position
|
|
121
|
+
], direction);
|
|
122
|
+
else swap(image, [
|
|
123
|
+
faceIndex("U"),
|
|
124
|
+
stateSliceIndex,
|
|
125
|
+
position
|
|
126
|
+
], [
|
|
127
|
+
faceIndex("R"),
|
|
128
|
+
position,
|
|
129
|
+
size - 1 - stateSliceIndex
|
|
130
|
+
], [
|
|
131
|
+
faceIndex("D"),
|
|
132
|
+
size - 1 - stateSliceIndex,
|
|
133
|
+
size - 1 - position
|
|
134
|
+
], [
|
|
135
|
+
faceIndex("L"),
|
|
136
|
+
size - 1 - position,
|
|
137
|
+
stateSliceIndex
|
|
138
|
+
], direction);
|
|
139
|
+
if (sliceIndex === 0) rotateFace(image, face, 3);
|
|
140
|
+
else if (sliceIndex === size - 1) rotateFace(image, oppositeFace(face), 1);
|
|
141
|
+
};
|
|
142
|
+
const moveSuffix = (amount) => {
|
|
143
|
+
if (amount === 2) return "2";
|
|
144
|
+
if (amount === 3) return "'";
|
|
145
|
+
return "";
|
|
146
|
+
};
|
|
147
|
+
const MALFORMED_MOVE = "<malformed>";
|
|
148
|
+
const rotationName = (face) => {
|
|
149
|
+
if (face === "R") return "x";
|
|
150
|
+
if (face === "U") return "y";
|
|
151
|
+
if (face === "F") return "z";
|
|
152
|
+
return face;
|
|
153
|
+
};
|
|
154
|
+
const moveToString = (move) => {
|
|
155
|
+
if (move.isRotation) return `${rotationName(move.face)}${moveSuffix(move.amount)}`;
|
|
156
|
+
if (move.width === 1) return `${move.face}${moveSuffix(move.amount)}`;
|
|
157
|
+
if (move.width === 2) return `${move.face}w${moveSuffix(move.amount)}`;
|
|
158
|
+
return `${move.width}${move.face}w${moveSuffix(move.amount)}`;
|
|
159
|
+
};
|
|
160
|
+
const validateMove = (state, move) => {
|
|
161
|
+
if (typeof move !== "object" || move === null || !isCubeFace(move.face) || !isMoveAmount(move.amount) || typeof move.isRotation !== "boolean") throw new InvalidMoveError(MALFORMED_MOVE, "cube");
|
|
162
|
+
if (move.isRotation) {
|
|
163
|
+
if (move.width !== Number.POSITIVE_INFINITY || move.face !== "R" && move.face !== "U" && move.face !== "F") throw new InvalidMoveError(MALFORMED_MOVE, "cube");
|
|
164
|
+
return move;
|
|
165
|
+
}
|
|
166
|
+
if (!Number.isSafeInteger(move.width)) throw new InvalidMoveError(MALFORMED_MOVE, "cube");
|
|
167
|
+
if (move.width < 1 || move.width > state.size) throw new InvalidMoveError(moveToString(move), "cube");
|
|
168
|
+
return move;
|
|
169
|
+
};
|
|
170
|
+
const createSolvedCubeState = (size) => {
|
|
171
|
+
if (!Number.isSafeInteger(size) || size < 1) throw new RangeError(`cube size must be a positive integer: ${size}`);
|
|
172
|
+
return createCubeState(size, CUBE_FACES.map((face) => Array.from({ length: size }, () => Array(size).fill(face))));
|
|
173
|
+
};
|
|
174
|
+
const applyCubeMove = (state, move) => {
|
|
175
|
+
const validMove = validateMove(state, move);
|
|
176
|
+
const nextImage = cloneCubeImage(state.image);
|
|
177
|
+
const width = validMove.isRotation ? state.size : validMove.width;
|
|
178
|
+
for (let turn = 0; turn < validMove.amount; turn += 1) for (let sliceIndex = 0; sliceIndex < width; sliceIndex += 1) slice(validMove.face, sliceIndex, nextImage);
|
|
179
|
+
return createCubeState(state.size, nextImage);
|
|
180
|
+
};
|
|
181
|
+
const areCubeStatesEqual = (a, b) => {
|
|
182
|
+
if (a.size !== b.size) return false;
|
|
183
|
+
for (let face = 0; face < CUBE_FACES.length; face += 1) for (let row = 0; row < a.size; row += 1) for (let column = 0; column < a.size; column += 1) if (a.image[face][row][column] !== b.image[face][row][column]) return false;
|
|
184
|
+
return true;
|
|
185
|
+
};
|
|
186
|
+
//#endregion
|
|
187
|
+
export { applyCubeMove, areCubeStatesEqual, createSolvedCubeState };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CubeFace, CubeMove } from "./cube-move2.mjs";
|
|
2
|
+
|
|
3
|
+
//#region .build/vendor/scramble-puzzle/src/cube/cube-state.d.ts
|
|
4
|
+
type CubeFacelet = CubeFace;
|
|
5
|
+
type CubeFaceState = readonly (readonly CubeFacelet[])[];
|
|
6
|
+
type CubeImage = readonly CubeFaceState[];
|
|
7
|
+
interface CubeState {
|
|
8
|
+
readonly size: number;
|
|
9
|
+
readonly image: CubeImage;
|
|
10
|
+
}
|
|
11
|
+
declare const createSolvedCubeState: (size: number) => CubeState;
|
|
12
|
+
declare const applyCubeMove: (state: CubeState, move: CubeMove) => CubeState;
|
|
13
|
+
declare const areCubeStatesEqual: (a: CubeState, b: CubeState) => boolean;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { CubeFaceState, CubeFacelet, CubeImage, CubeState, applyCubeMove, areCubeStatesEqual, createSolvedCubeState };
|