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,520 @@
1
+ import { getSquareOneSlashabilityMoveCost, parseSquareOneAlgorithm, parseSquareOneMove } from "../../../../scramble-puzzle/src/square1/square1-parser.mjs";
2
+ import { applySquareOneMove, areSquareOneStatesEqual, canSquareOneSlash, getSquareOneScrambleSuccessors } from "../../../../scramble-puzzle/src/square1/square1-state.mjs";
3
+ import "../../../../scramble-puzzle/src/index.mjs";
4
+ import { getShapeTables, popCount } from "./shape.mjs";
5
+ import { createSquareCoordinate, getSquareTables } from "./square.mjs";
6
+ import { FullCube } from "./full-cube.mjs";
7
+ const ERROR_PREFIX = "@cubegin/scramble-core";
8
+ const WCA_TURN_METRIC = 1;
9
+ const PRUN_INC = WCA_TURN_METRIC === WCA_TURN_METRIC ? 2 : 1;
10
+ const MAX_OPT_LENGTH = 31;
11
+ const SQUARE_ONE_TURNS = [
12
+ -5,
13
+ -4,
14
+ -3,
15
+ -2,
16
+ -1,
17
+ 0,
18
+ 1,
19
+ 2,
20
+ 3,
21
+ 4,
22
+ 5,
23
+ 6
24
+ ];
25
+ var Search = class {
26
+ move = Array.from({ length: 100 }, () => 0);
27
+ workingCube = new FullCube();
28
+ square = createSquareCoordinate();
29
+ cube;
30
+ length1 = 0;
31
+ moveLength1 = 0;
32
+ maxLength2 = 0;
33
+ verbose = 0;
34
+ solutionString = null;
35
+ solution(cube, verbose = 0) {
36
+ this.cube = cube;
37
+ this.verbose = verbose;
38
+ this.solutionString = null;
39
+ const { shapePrun } = getShapeTables();
40
+ const shape = cube.getShapeIdx();
41
+ for (this.length1 = shapePrun[shape]; this.length1 < 100; this.length1 += 1) {
42
+ this.maxLength2 = Math.min(31 - this.length1, 17);
43
+ if (this.idaPhase1({
44
+ shape,
45
+ prunValue: shapePrun[shape],
46
+ maxLength: this.length1,
47
+ depth: 0,
48
+ lastMove: -1
49
+ })) break;
50
+ }
51
+ return this.solutionString;
52
+ }
53
+ solutionOpt(cube, maxLength, verbose = 0) {
54
+ validateSolveLength(maxLength);
55
+ this.cube = cube;
56
+ this.verbose = verbose;
57
+ this.solutionString = null;
58
+ const { shapePrunOpt } = getShapeTables();
59
+ const shape = cube.getShapeIdx();
60
+ for (this.length1 = shapePrunOpt[shape] * PRUN_INC; this.length1 <= maxLength * PRUN_INC; this.length1 += PRUN_INC) if (this.phase1Opt({
61
+ shape,
62
+ prunValue: shapePrunOpt[shape],
63
+ maxLength: this.length1,
64
+ depth: 0,
65
+ lastMove: -1,
66
+ lastTurns: 0
67
+ })) break;
68
+ return this.solutionString;
69
+ }
70
+ phase1Opt({ shape, maxLength, depth, lastMove, lastTurns }) {
71
+ const turnBalance = count0xf((lastTurns ^ -1) & 16711935) - count0xf((lastTurns ^ -6710887) & 16711935);
72
+ if (turnBalance < 0 || turnBalance === 0 && (lastTurns >> 20 & 15) >= 6) return false;
73
+ const remainingMoves = Math.floor(maxLength / PRUN_INC);
74
+ if (remainingMoves === 0) {
75
+ this.moveLength1 = depth;
76
+ if (this.isSolvedInPhase1()) return true;
77
+ if (maxLength === 0) return false;
78
+ }
79
+ const { shapePrunOpt, topMove, bottomMove, twistMove } = getShapeTables();
80
+ if (lastMove !== 0) {
81
+ const nextShape = twistMove[shape];
82
+ const prun = shapePrunOpt[nextShape];
83
+ if (prun < remainingMoves) {
84
+ this.move[depth] = 0;
85
+ const nextMaxLength = (remainingMoves - 1) * PRUN_INC;
86
+ if (this.phase1Opt({
87
+ shape: nextShape,
88
+ prunValue: prun,
89
+ maxLength: nextMaxLength,
90
+ depth: depth + 1,
91
+ lastMove: 0,
92
+ lastTurns: lastTurns << 8
93
+ })) return true;
94
+ }
95
+ }
96
+ if (lastMove <= 0) {
97
+ let move = 0;
98
+ let nextShape = shape;
99
+ while (true) {
100
+ const moved = move + topMove[nextShape];
101
+ nextShape = moved >> 4;
102
+ move = moved & 15;
103
+ if (move >= 12) break;
104
+ const prun = shapePrunOpt[nextShape];
105
+ if (prun * PRUN_INC > maxLength + PRUN_INC - 1) break;
106
+ if (prun * PRUN_INC < maxLength + PRUN_INC - 1) {
107
+ this.move[depth] = move;
108
+ if (this.phase1Opt({
109
+ shape: nextShape,
110
+ prunValue: prun,
111
+ maxLength: maxLength - 1,
112
+ depth: depth + 1,
113
+ lastMove: 1,
114
+ lastTurns: lastTurns | move << 4
115
+ })) return true;
116
+ }
117
+ }
118
+ }
119
+ if (lastMove <= 1) {
120
+ let move = 0;
121
+ let nextShape = shape;
122
+ while (true) {
123
+ const moved = move + bottomMove[nextShape];
124
+ nextShape = moved >> 4;
125
+ move = moved & 15;
126
+ if (move >= 12) break;
127
+ const prun = shapePrunOpt[nextShape];
128
+ if (prun * PRUN_INC > maxLength + PRUN_INC - 1) break;
129
+ if (prun * PRUN_INC < maxLength + PRUN_INC - 1) {
130
+ this.move[depth] = -move;
131
+ if (this.phase1Opt({
132
+ shape: nextShape,
133
+ prunValue: prun,
134
+ maxLength: maxLength - 1,
135
+ depth: depth + 1,
136
+ lastMove: 2,
137
+ lastTurns: lastTurns | move
138
+ })) return true;
139
+ }
140
+ }
141
+ }
142
+ return false;
143
+ }
144
+ idaPhase1({ shape, prunValue, maxLength, depth, lastMove }) {
145
+ if (prunValue === 0 && maxLength < 4) {
146
+ this.moveLength1 = depth;
147
+ return maxLength === 0 && this.initPhase2();
148
+ }
149
+ const { shapePrun, topMove, bottomMove, twistMove } = getShapeTables();
150
+ if (lastMove !== 0) {
151
+ const nextShape = twistMove[shape];
152
+ const prun = shapePrun[nextShape];
153
+ if (prun < maxLength) {
154
+ this.move[depth] = 0;
155
+ if (this.idaPhase1({
156
+ shape: nextShape,
157
+ prunValue: prun,
158
+ maxLength: maxLength - 1,
159
+ depth: depth + 1,
160
+ lastMove: 0
161
+ })) return true;
162
+ }
163
+ }
164
+ if (lastMove <= 0) {
165
+ let move = 0;
166
+ let nextShape = shape;
167
+ while (true) {
168
+ const moved = move + topMove[nextShape];
169
+ nextShape = moved >> 4;
170
+ move = moved & 15;
171
+ if (move >= 12) break;
172
+ const prun = shapePrun[nextShape];
173
+ if (prun > maxLength) break;
174
+ if (prun < maxLength) {
175
+ this.move[depth] = move;
176
+ if (this.idaPhase1({
177
+ shape: nextShape,
178
+ prunValue: prun,
179
+ maxLength: maxLength - 1,
180
+ depth: depth + 1,
181
+ lastMove: 1
182
+ })) return true;
183
+ }
184
+ }
185
+ }
186
+ if (lastMove <= 1) {
187
+ let move = 0;
188
+ let nextShape = shape;
189
+ while (true) {
190
+ const moved = move + bottomMove[nextShape];
191
+ nextShape = moved >> 4;
192
+ move = moved & 15;
193
+ if (move >= 6) break;
194
+ const prun = shapePrun[nextShape];
195
+ if (prun > maxLength) break;
196
+ if (prun < maxLength) {
197
+ this.move[depth] = -move;
198
+ if (this.idaPhase1({
199
+ shape: nextShape,
200
+ prunValue: prun,
201
+ maxLength: maxLength - 1,
202
+ depth: depth + 1,
203
+ lastMove: 2
204
+ })) return true;
205
+ }
206
+ }
207
+ }
208
+ return false;
209
+ }
210
+ isSolvedInPhase1() {
211
+ const cube = this.requireCube();
212
+ this.workingCube.copy(cube);
213
+ for (let index = 0; index < this.moveLength1; index += 1) this.workingCube.doMove(this.move[index]);
214
+ if (!this.workingCube.isSolved()) return false;
215
+ this.solutionString = this.move2string(this.moveLength1);
216
+ return true;
217
+ }
218
+ initPhase2() {
219
+ const cube = this.requireCube();
220
+ this.workingCube.copy(cube);
221
+ for (let index = 0; index < this.moveLength1; index += 1) this.workingCube.doMove(this.move[index]);
222
+ this.workingCube.getSquare(this.square);
223
+ const { squarePrun } = getSquareTables();
224
+ const edge = this.square.edgePerm;
225
+ const corner = this.square.cornPerm;
226
+ const ml = this.square.ml;
227
+ const prun = Math.max(squarePrun[edge << 1 | ml], squarePrun[corner << 1 | ml]);
228
+ for (let length = prun; length < this.maxLength2; length += 1) if (this.idaPhase2({
229
+ edge,
230
+ corner,
231
+ topEdgeFirst: this.square.topEdgeFirst,
232
+ botEdgeFirst: this.square.botEdgeFirst,
233
+ ml,
234
+ maxLength: length,
235
+ depth: this.moveLength1,
236
+ lastMove: 0
237
+ })) {
238
+ this.solutionString = this.move2string(length + this.moveLength1);
239
+ return true;
240
+ }
241
+ return false;
242
+ }
243
+ move2string(length) {
244
+ const outputMoves = Array.from({ length }, () => 0);
245
+ if ((this.verbose & 2) !== 0) for (let index = length - 1; index >= 0; index -= 1) {
246
+ const move = this.move[index];
247
+ outputMoves[length - 1 - index] = move > 0 ? 12 - move : move < 0 ? -12 - move : move;
248
+ }
249
+ else for (let index = 0; index < length; index += 1) outputMoves[index] = this.move[index];
250
+ let solution = "";
251
+ let top = 0;
252
+ let bottom = 0;
253
+ for (const move of outputMoves) if (move > 0) top = move > 6 ? move - 12 : move;
254
+ else if (move < 0) bottom = -move > 6 ? -move - 12 : -move;
255
+ else {
256
+ if (top === 0 && bottom === 0) solution += " / ";
257
+ else solution += `(${top},${bottom}) / `;
258
+ top = 0;
259
+ bottom = 0;
260
+ }
261
+ if (top !== 0 || bottom !== 0) solution += `(${top},${bottom})`;
262
+ return solution;
263
+ }
264
+ idaPhase2({ edge, corner, topEdgeFirst, botEdgeFirst, ml, maxLength, depth, lastMove }) {
265
+ if (maxLength === 0 && !topEdgeFirst && botEdgeFirst) return true;
266
+ const { squarePrun, twistMove, topMove, bottomMove } = getSquareTables();
267
+ if (lastMove !== 0 && topEdgeFirst === botEdgeFirst) {
268
+ const nextEdge = twistMove[edge];
269
+ const nextCorner = twistMove[corner];
270
+ if (squarePrun[nextEdge << 1 | 1 - ml] < maxLength && squarePrun[nextCorner << 1 | 1 - ml] < maxLength) {
271
+ this.move[depth] = 0;
272
+ if (this.idaPhase2({
273
+ edge: nextEdge,
274
+ corner: nextCorner,
275
+ topEdgeFirst,
276
+ botEdgeFirst,
277
+ ml: 1 - ml,
278
+ maxLength: maxLength - 1,
279
+ depth: depth + 1,
280
+ lastMove: 0
281
+ })) return true;
282
+ }
283
+ }
284
+ if (lastMove <= 0) {
285
+ let nextTopEdgeFirst = !topEdgeFirst;
286
+ let nextEdge = nextTopEdgeFirst ? topMove[edge] : edge;
287
+ let nextCorner = nextTopEdgeFirst ? corner : topMove[corner];
288
+ let move = nextTopEdgeFirst ? 1 : 2;
289
+ let edgePrun = squarePrun[nextEdge << 1 | ml];
290
+ let cornerPrun = squarePrun[nextCorner << 1 | ml];
291
+ while (move < 12 && edgePrun <= maxLength && edgePrun <= maxLength) {
292
+ if (edgePrun < maxLength && cornerPrun < maxLength) {
293
+ this.move[depth] = move;
294
+ if (this.idaPhase2({
295
+ edge: nextEdge,
296
+ corner: nextCorner,
297
+ topEdgeFirst: nextTopEdgeFirst,
298
+ botEdgeFirst,
299
+ ml,
300
+ maxLength: maxLength - 1,
301
+ depth: depth + 1,
302
+ lastMove: 1
303
+ })) return true;
304
+ }
305
+ nextTopEdgeFirst = !nextTopEdgeFirst;
306
+ if (nextTopEdgeFirst) {
307
+ nextEdge = topMove[nextEdge];
308
+ edgePrun = squarePrun[nextEdge << 1 | ml];
309
+ move += 1;
310
+ } else {
311
+ nextCorner = topMove[nextCorner];
312
+ cornerPrun = squarePrun[nextCorner << 1 | ml];
313
+ move += 2;
314
+ }
315
+ }
316
+ }
317
+ if (lastMove <= 1) {
318
+ let nextBotEdgeFirst = !botEdgeFirst;
319
+ let nextEdge = nextBotEdgeFirst ? bottomMove[edge] : edge;
320
+ let nextCorner = nextBotEdgeFirst ? corner : bottomMove[corner];
321
+ let move = nextBotEdgeFirst ? 1 : 2;
322
+ let edgePrun = squarePrun[nextEdge << 1 | ml];
323
+ let cornerPrun = squarePrun[nextCorner << 1 | ml];
324
+ while (move < (maxLength > 6 ? 6 : 12) && edgePrun <= maxLength && edgePrun <= maxLength) {
325
+ if (edgePrun < maxLength && cornerPrun < maxLength) {
326
+ this.move[depth] = -move;
327
+ if (this.idaPhase2({
328
+ edge: nextEdge,
329
+ corner: nextCorner,
330
+ topEdgeFirst,
331
+ botEdgeFirst: nextBotEdgeFirst,
332
+ ml,
333
+ maxLength: maxLength - 1,
334
+ depth: depth + 1,
335
+ lastMove: 2
336
+ })) return true;
337
+ }
338
+ nextBotEdgeFirst = !nextBotEdgeFirst;
339
+ if (nextBotEdgeFirst) {
340
+ nextEdge = bottomMove[nextEdge];
341
+ edgePrun = squarePrun[nextEdge << 1 | ml];
342
+ move += 1;
343
+ } else {
344
+ nextCorner = bottomMove[nextCorner];
345
+ cornerPrun = squarePrun[nextCorner << 1 | ml];
346
+ move += 2;
347
+ }
348
+ }
349
+ }
350
+ return false;
351
+ }
352
+ requireCube() {
353
+ if (!this.cube) throw new Error(`${ERROR_PREFIX}: Square-1 search has no cube state`);
354
+ return this.cube;
355
+ }
356
+ };
357
+ const solveSquareOneStateIn = (state, maxLength) => {
358
+ validateSolveLength(maxLength);
359
+ if (!canSquareOneSlash(state)) {
360
+ const bestSlashable = getBestSlashableSuccessor(state);
361
+ if (!bestSlashable) return null;
362
+ return solveWithSlashabilityIn(bestSlashable.state, maxLength, formatSquareOneMove(bestSlashable.move), state, maxLength - 1);
363
+ }
364
+ const solution = new Search().solutionOpt(FullCube.fromSquareOneState(state), maxLength);
365
+ return solution === null ? null : solution.trim();
366
+ };
367
+ const solveWithSlashabilityIn = (state, maxLength, slashabilityMove, preSlashabilityState, lowerThreshold) => {
368
+ if (!canSquareOneSlash(state)) return null;
369
+ if (maxLength < lowerThreshold) return null;
370
+ const nextBestSolution = solveSquareOneStateIn(state, maxLength);
371
+ if (nextBestSolution === null) return null;
372
+ const algorithmBuilder = new SquareOneAlgorithmBuilder(preSlashabilityState);
373
+ algorithmBuilder.appendMove(slashabilityMove);
374
+ algorithmBuilder.appendAlgorithm(nextBestSolution);
375
+ if (algorithmBuilder.totalCost > maxLength) return solveWithSlashabilityIn(state, maxLength - 1, slashabilityMove, preSlashabilityState, lowerThreshold);
376
+ return algorithmBuilder.toString();
377
+ };
378
+ var SquareOneAlgorithmBuilder = class {
379
+ moves = [];
380
+ states = [];
381
+ unNormalizedState;
382
+ totalCost = 0;
383
+ constructor(originalState) {
384
+ this.unNormalizedState = originalState;
385
+ this.states.push(originalState);
386
+ }
387
+ appendAlgorithm(algorithm) {
388
+ for (const move of parseSquareOneAlgorithm(algorithm)) this.appendMove(formatSquareOneMove(move));
389
+ }
390
+ appendMove(newMove) {
391
+ const moveIndex = this.findBestIndexForMove(newMove);
392
+ let oldCost;
393
+ let newCost;
394
+ if (moveIndex.index < this.moves.length) {
395
+ oldCost = 1;
396
+ if (moveIndex.moveName === null) {
397
+ this.moves.splice(moveIndex.index, 1);
398
+ this.states.splice(moveIndex.index + 1, 1);
399
+ newCost = 0;
400
+ } else {
401
+ this.moves[moveIndex.index] = moveIndex.moveName;
402
+ newCost = 1;
403
+ }
404
+ } else {
405
+ oldCost = 0;
406
+ newCost = 1;
407
+ this.moves.push(assertMoveName(moveIndex.moveName));
408
+ this.states.push(this.getState());
409
+ }
410
+ this.totalCost += newCost - oldCost;
411
+ for (let index = moveIndex.index + 1; index < this.states.length; index += 1) this.states[index] = applyMoveName(this.states[index - 1], this.moves[index - 1]);
412
+ this.unNormalizedState = applyMoveName(this.unNormalizedState, newMove);
413
+ }
414
+ getState() {
415
+ return this.states[this.states.length - 1];
416
+ }
417
+ toString() {
418
+ return this.moves.join(" ");
419
+ }
420
+ findBestIndexForMove(moveName) {
421
+ const newUnNormalizedState = applyMoveName(this.unNormalizedState, moveName);
422
+ if (areSquareOneStatesEqual(newUnNormalizedState, this.unNormalizedState)) return {
423
+ index: 0,
424
+ moveName: null
425
+ };
426
+ const canonicalMove = findCanonicalMoveToState(this.getState(), newUnNormalizedState);
427
+ if (canonicalMove === null) throw new Error(`${ERROR_PREFIX}: could not canonicalize Square-1 move ${moveName}`);
428
+ for (let lastMoveIndex = this.moves.length - 1; lastMoveIndex >= 0; lastMoveIndex -= 1) {
429
+ const lastMove = this.moves[lastMoveIndex];
430
+ const stateBeforeLastMove = this.states[lastMoveIndex];
431
+ if (!movesCommute(stateBeforeLastMove, lastMove, canonicalMove)) break;
432
+ const stateAfterLastMove = this.states[lastMoveIndex + 1];
433
+ const stateAfterBoth = applyMoveName(stateAfterLastMove, canonicalMove);
434
+ if (areSquareOneStatesEqual(stateBeforeLastMove, stateAfterBoth)) return {
435
+ index: lastMoveIndex,
436
+ moveName: null
437
+ };
438
+ const alternateLastMove = findCanonicalMoveToState(stateBeforeLastMove, stateAfterBoth);
439
+ if (alternateLastMove !== null) return {
440
+ index: lastMoveIndex,
441
+ moveName: alternateLastMove
442
+ };
443
+ }
444
+ return {
445
+ index: this.moves.length,
446
+ moveName: canonicalMove
447
+ };
448
+ }
449
+ };
450
+ const getBestSlashableSuccessor = (state) => {
451
+ let bestMove = null;
452
+ let bestCost = Number.POSITIVE_INFINITY;
453
+ for (const successor of getSquareOneScrambleSuccessors(state)) {
454
+ const cost = getSquareOneSlashabilityMoveCost(successor.move);
455
+ if (cost === void 0 || cost >= bestCost) continue;
456
+ bestCost = cost;
457
+ bestMove = successor;
458
+ }
459
+ return bestMove;
460
+ };
461
+ const findCanonicalMoveToState = (state, targetState) => {
462
+ for (const successor of getCanonicalMovesByState(state)) if (areSquareOneStatesEqual(successor.state, targetState)) return successor.moveName;
463
+ return null;
464
+ };
465
+ const getCanonicalMovesByState = (state) => {
466
+ const successors = [];
467
+ const seenStates = new Set([getStateKey(state)]);
468
+ for (const successor of getSuccessorsByName(state)) {
469
+ const stateKey = getStateKey(successor.state);
470
+ if (seenStates.has(stateKey)) continue;
471
+ successors.push(successor);
472
+ seenStates.add(stateKey);
473
+ }
474
+ return successors;
475
+ };
476
+ const getSuccessorsByName = (state) => {
477
+ const successors = [];
478
+ for (const top of SQUARE_ONE_TURNS) for (const bottom of SQUARE_ONE_TURNS) {
479
+ if (top === 0 && bottom === 0) continue;
480
+ const move = {
481
+ type: "tuple",
482
+ top,
483
+ bottom
484
+ };
485
+ successors.push({
486
+ moveName: formatSquareOneMove(move),
487
+ state: applySquareOneMove(state, move)
488
+ });
489
+ }
490
+ if (canSquareOneSlash(state)) successors.push({
491
+ moveName: "/",
492
+ state: applySquareOneMove(state, { type: "slash" })
493
+ });
494
+ return successors;
495
+ };
496
+ const movesCommute = (state, firstMove, secondMove) => {
497
+ try {
498
+ return areSquareOneStatesEqual(applyMoveName(applyMoveName(state, firstMove), secondMove), applyMoveName(applyMoveName(state, secondMove), firstMove));
499
+ } catch {
500
+ return false;
501
+ }
502
+ };
503
+ const applyMoveName = (state, moveName) => applySquareOneMove(state, parseSquareOneMove(moveName));
504
+ const formatSquareOneMove = (move) => move.type === "slash" ? "/" : `(${move.top},${move.bottom})`;
505
+ const getStateKey = (state) => `${state.sliceSolved ? 1 : 0}:${state.pieces.join(",")}`;
506
+ const assertMoveName = (moveName) => {
507
+ if (moveName === null) throw new Error(`${ERROR_PREFIX}: Square-1 canonical move is missing`);
508
+ return moveName;
509
+ };
510
+ const validateSolveLength = (maxLength) => {
511
+ if (!Number.isSafeInteger(maxLength) || maxLength < 0 || maxLength > MAX_OPT_LENGTH) throw new RangeError(`${ERROR_PREFIX}: Square-1 solve length must be an integer from 0 to ${MAX_OPT_LENGTH}`);
512
+ };
513
+ const count0xf = (value) => {
514
+ let nibbles = value;
515
+ nibbles &= nibbles >> 1;
516
+ nibbles &= nibbles >> 2;
517
+ return popCount(nibbles & 286331153);
518
+ };
519
+ //#endregion
520
+ export { Search, solveSquareOneStateIn };