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.
Files changed (164) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +674 -0
  3. package/NOTICE +11 -0
  4. package/README.md +49 -0
  5. package/dist/scramble-core/src/batch.mjs +18 -0
  6. package/dist/scramble-core/src/generator.d.mts +35 -0
  7. package/dist/scramble-core/src/generator.mjs +136 -0
  8. package/dist/scramble-core/src/generators/clock.d.mts +11 -0
  9. package/dist/scramble-core/src/generators/clock.mjs +32 -0
  10. package/dist/scramble-core/src/generators/cube-random-turns.d.mts +11 -0
  11. package/dist/scramble-core/src/generators/cube-random-turns.mjs +54 -0
  12. package/dist/scramble-core/src/generators/four-by-four.d.mts +14 -0
  13. package/dist/scramble-core/src/generators/four-by-four.mjs +43 -0
  14. package/dist/scramble-core/src/generators/megaminx.d.mts +11 -0
  15. package/dist/scramble-core/src/generators/megaminx.mjs +18 -0
  16. package/dist/scramble-core/src/generators/pyraminx.d.mts +11 -0
  17. package/dist/scramble-core/src/generators/pyraminx.mjs +17 -0
  18. package/dist/scramble-core/src/generators/skewb.d.mts +11 -0
  19. package/dist/scramble-core/src/generators/skewb.mjs +17 -0
  20. package/dist/scramble-core/src/generators/square1.d.mts +11 -0
  21. package/dist/scramble-core/src/generators/square1.mjs +28 -0
  22. package/dist/scramble-core/src/generators/three-by-three.d.mts +25 -0
  23. package/dist/scramble-core/src/generators/three-by-three.mjs +85 -0
  24. package/dist/scramble-core/src/generators/two-by-two.d.mts +11 -0
  25. package/dist/scramble-core/src/generators/two-by-two.mjs +17 -0
  26. package/dist/scramble-core/src/random-source.d.mts +7 -0
  27. package/dist/scramble-core/src/random-source.mjs +8 -0
  28. package/dist/scramble-core/src/solvers/min2phase/coord-cube.mjs +10 -0
  29. package/dist/scramble-core/src/solvers/min2phase/cubie-cube.mjs +246 -0
  30. package/dist/scramble-core/src/solvers/min2phase/engine.mjs +1281 -0
  31. package/dist/scramble-core/src/solvers/min2phase/search-wca.mjs +21 -0
  32. package/dist/scramble-core/src/solvers/min2phase/search.mjs +25 -0
  33. package/dist/scramble-core/src/solvers/min2phase/tools.mjs +169 -0
  34. package/dist/scramble-core/src/solvers/min2phase/util.mjs +30 -0
  35. package/dist/scramble-core/src/solvers/pyraminx-solver.d.mts +17 -0
  36. package/dist/scramble-core/src/solvers/pyraminx-solver.mjs +350 -0
  37. package/dist/scramble-core/src/solvers/skewb-solver.d.mts +15 -0
  38. package/dist/scramble-core/src/solvers/skewb-solver.mjs +399 -0
  39. package/dist/scramble-core/src/solvers/sq12phase/full-cube.mjs +212 -0
  40. package/dist/scramble-core/src/solvers/sq12phase/search.mjs +520 -0
  41. package/dist/scramble-core/src/solvers/sq12phase/shape.mjs +214 -0
  42. package/dist/scramble-core/src/solvers/sq12phase/square.mjs +135 -0
  43. package/dist/scramble-core/src/solvers/threephase/center.mjs +798 -0
  44. package/dist/scramble-core/src/solvers/threephase/edge.mjs +632 -0
  45. package/dist/scramble-core/src/solvers/threephase/full-cube.mjs +554 -0
  46. package/dist/scramble-core/src/solvers/threephase/search.mjs +262 -0
  47. package/dist/scramble-core/src/solvers/threephase/tables.mjs +201 -0
  48. package/dist/scramble-core/src/solvers/two-by-two-solver.d.mts +15 -0
  49. package/dist/scramble-core/src/solvers/two-by-two-solver.mjs +298 -0
  50. package/dist/scramble-core.d.mts +15 -0
  51. package/dist/scramble-core.mjs +15 -0
  52. package/dist/scramble-image/src/color.d.mts +12 -0
  53. package/dist/scramble-image/src/color.mjs +11 -0
  54. package/dist/scramble-image/src/render.d.mts +10 -0
  55. package/dist/scramble-image/src/render.mjs +71 -0
  56. package/dist/scramble-image/src/renderers/clock.d.mts +6 -0
  57. package/dist/scramble-image/src/renderers/clock.mjs +145 -0
  58. package/dist/scramble-image/src/renderers/cube-isometric.d.mts +8 -0
  59. package/dist/scramble-image/src/renderers/cube-isometric.mjs +204 -0
  60. package/dist/scramble-image/src/renderers/cube-net.d.mts +8 -0
  61. package/dist/scramble-image/src/renderers/cube-net.mjs +52 -0
  62. package/dist/scramble-image/src/renderers/megaminx-isometric.d.mts +9 -0
  63. package/dist/scramble-image/src/renderers/megaminx-isometric.mjs +320 -0
  64. package/dist/scramble-image/src/renderers/megaminx.d.mts +9 -0
  65. package/dist/scramble-image/src/renderers/megaminx.mjs +173 -0
  66. package/dist/scramble-image/src/renderers/pyraminx-isometric.d.mts +9 -0
  67. package/dist/scramble-image/src/renderers/pyraminx-isometric.mjs +185 -0
  68. package/dist/scramble-image/src/renderers/pyraminx.d.mts +9 -0
  69. package/dist/scramble-image/src/renderers/pyraminx.mjs +111 -0
  70. package/dist/scramble-image/src/renderers/skewb-isometric.d.mts +9 -0
  71. package/dist/scramble-image/src/renderers/skewb-isometric.mjs +233 -0
  72. package/dist/scramble-image/src/renderers/skewb.d.mts +9 -0
  73. package/dist/scramble-image/src/renderers/skewb.mjs +187 -0
  74. package/dist/scramble-image/src/renderers/square1.d.mts +10 -0
  75. package/dist/scramble-image/src/renderers/square1.mjs +253 -0
  76. package/dist/scramble-image/src/svg/svg-document.d.mts +6 -0
  77. package/dist/scramble-image/src/svg/svg-document.mjs +7 -0
  78. package/dist/scramble-image/src/svg/svg-elements.d.mts +15 -0
  79. package/dist/scramble-image/src/svg/svg-elements.mjs +25 -0
  80. package/dist/scramble-image/src/svg/svg-serialize.mjs +29 -0
  81. package/dist/scramble-image.d.mts +15 -0
  82. package/dist/scramble-image.mjs +15 -0
  83. package/dist/scramble-puzzle/src/algorithm.d.mts +8 -0
  84. package/dist/scramble-puzzle/src/algorithm.mjs +16 -0
  85. package/dist/scramble-puzzle/src/algorithm2.mjs +16 -0
  86. package/dist/scramble-puzzle/src/clock/clock-definition.d.mts +8 -0
  87. package/dist/scramble-puzzle/src/clock/clock-definition.mjs +18 -0
  88. package/dist/scramble-puzzle/src/clock/clock-definition2.mjs +18 -0
  89. package/dist/scramble-puzzle/src/clock/clock-parser.d.mts +18 -0
  90. package/dist/scramble-puzzle/src/clock/clock-parser.mjs +35 -0
  91. package/dist/scramble-puzzle/src/clock/clock-parser2.mjs +35 -0
  92. package/dist/scramble-puzzle/src/clock/clock-state.d.mts +8 -0
  93. package/dist/scramble-puzzle/src/clock/clock-state.mjs +212 -0
  94. package/dist/scramble-puzzle/src/clock/clock-state2.d.mts +13 -0
  95. package/dist/scramble-puzzle/src/clock/clock-state2.mjs +212 -0
  96. package/dist/scramble-puzzle/src/cube/cube-definition.d.mts +9 -0
  97. package/dist/scramble-puzzle/src/cube/cube-definition.mjs +18 -0
  98. package/dist/scramble-puzzle/src/cube/cube-definition2.mjs +18 -0
  99. package/dist/scramble-puzzle/src/cube/cube-move.d.mts +4 -0
  100. package/dist/scramble-puzzle/src/cube/cube-move2.d.mts +17 -0
  101. package/dist/scramble-puzzle/src/cube/cube-parser.d.mts +7 -0
  102. package/dist/scramble-puzzle/src/cube/cube-parser.mjs +60 -0
  103. package/dist/scramble-puzzle/src/cube/cube-parser2.mjs +60 -0
  104. package/dist/scramble-puzzle/src/cube/cube-state.d.mts +12 -0
  105. package/dist/scramble-puzzle/src/cube/cube-state.mjs +187 -0
  106. package/dist/scramble-puzzle/src/cube/cube-state2.d.mts +15 -0
  107. package/dist/scramble-puzzle/src/cube/cube-state2.mjs +187 -0
  108. package/dist/scramble-puzzle/src/errors.d.mts +15 -0
  109. package/dist/scramble-puzzle/src/errors.mjs +24 -0
  110. package/dist/scramble-puzzle/src/errors2.mjs +30 -0
  111. package/dist/scramble-puzzle/src/events.d.mts +5 -0
  112. package/dist/scramble-puzzle/src/events.mjs +90 -0
  113. package/dist/scramble-puzzle/src/events2.d.mts +98 -0
  114. package/dist/scramble-puzzle/src/events2.mjs +109 -0
  115. package/dist/scramble-puzzle/src/index.mjs +22 -0
  116. package/dist/scramble-puzzle/src/megaminx/megaminx-definition.d.mts +8 -0
  117. package/dist/scramble-puzzle/src/megaminx/megaminx-definition.mjs +18 -0
  118. package/dist/scramble-puzzle/src/megaminx/megaminx-definition2.mjs +18 -0
  119. package/dist/scramble-puzzle/src/megaminx/megaminx-parser.d.mts +5 -0
  120. package/dist/scramble-puzzle/src/megaminx/megaminx-parser.mjs +57 -0
  121. package/dist/scramble-puzzle/src/megaminx/megaminx-parser2.d.mts +20 -0
  122. package/dist/scramble-puzzle/src/megaminx/megaminx-parser2.mjs +57 -0
  123. package/dist/scramble-puzzle/src/megaminx/megaminx-state.d.mts +9 -0
  124. package/dist/scramble-puzzle/src/megaminx/megaminx-state.mjs +112 -0
  125. package/dist/scramble-puzzle/src/megaminx/megaminx-state2.d.mts +14 -0
  126. package/dist/scramble-puzzle/src/megaminx/megaminx-state2.mjs +112 -0
  127. package/dist/scramble-puzzle/src/puzzle-definition.d.mts +19 -0
  128. package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition.d.mts +8 -0
  129. package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition.mjs +18 -0
  130. package/dist/scramble-puzzle/src/pyraminx/pyraminx-definition2.mjs +18 -0
  131. package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser.d.mts +5 -0
  132. package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser.mjs +34 -0
  133. package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser2.d.mts +21 -0
  134. package/dist/scramble-puzzle/src/pyraminx/pyraminx-parser2.mjs +34 -0
  135. package/dist/scramble-puzzle/src/pyraminx/pyraminx-state.d.mts +11 -0
  136. package/dist/scramble-puzzle/src/pyraminx/pyraminx-state.mjs +90 -0
  137. package/dist/scramble-puzzle/src/pyraminx/pyraminx-state2.d.mts +14 -0
  138. package/dist/scramble-puzzle/src/pyraminx/pyraminx-state2.mjs +90 -0
  139. package/dist/scramble-puzzle/src/registry.d.mts +11 -0
  140. package/dist/scramble-puzzle/src/registry.mjs +13 -0
  141. package/dist/scramble-puzzle/src/skewb/skewb-definition.d.mts +8 -0
  142. package/dist/scramble-puzzle/src/skewb/skewb-definition.mjs +18 -0
  143. package/dist/scramble-puzzle/src/skewb/skewb-definition2.mjs +18 -0
  144. package/dist/scramble-puzzle/src/skewb/skewb-parser.d.mts +5 -0
  145. package/dist/scramble-puzzle/src/skewb/skewb-parser.mjs +33 -0
  146. package/dist/scramble-puzzle/src/skewb/skewb-parser2.d.mts +14 -0
  147. package/dist/scramble-puzzle/src/skewb/skewb-parser2.mjs +33 -0
  148. package/dist/scramble-puzzle/src/skewb/skewb-state.d.mts +11 -0
  149. package/dist/scramble-puzzle/src/skewb/skewb-state.mjs +75 -0
  150. package/dist/scramble-puzzle/src/skewb/skewb-state2.d.mts +14 -0
  151. package/dist/scramble-puzzle/src/skewb/skewb-state2.mjs +75 -0
  152. package/dist/scramble-puzzle/src/square1/square1-definition.d.mts +8 -0
  153. package/dist/scramble-puzzle/src/square1/square1-definition.mjs +18 -0
  154. package/dist/scramble-puzzle/src/square1/square1-definition2.mjs +18 -0
  155. package/dist/scramble-puzzle/src/square1/square1-parser.d.mts +17 -0
  156. package/dist/scramble-puzzle/src/square1/square1-parser.mjs +43 -0
  157. package/dist/scramble-puzzle/src/square1/square1-parser2.mjs +47 -0
  158. package/dist/scramble-puzzle/src/square1/square1-state.d.mts +9 -0
  159. package/dist/scramble-puzzle/src/square1/square1-state.mjs +115 -0
  160. package/dist/scramble-puzzle/src/square1/square1-state2.d.mts +21 -0
  161. package/dist/scramble-puzzle/src/square1/square1-state2.mjs +115 -0
  162. package/dist/scramble-puzzle.d.mts +25 -0
  163. package/dist/scramble-puzzle.mjs +23 -0
  164. 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,4 @@
1
+ //#region ../scramble-puzzle/src/cube/cube-move.d.ts
2
+ type CubeFace = 'R' | 'U' | 'F' | 'L' | 'D' | 'B';
3
+ //#endregion
4
+ export { CubeFace };
@@ -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 };