@rednaxela101/cubing 0.63.5

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 (136) hide show
  1. package/README.md +120 -0
  2. package/alg/index.d.ts +1 -0
  3. package/bluetooth/index.d.ts +1 -0
  4. package/dist/bin/chunks/chunk-22VWCGBC.js +13 -0
  5. package/dist/bin/chunks/chunk-22VWCGBC.js.map +7 -0
  6. package/dist/bin/order.js +59 -0
  7. package/dist/bin/order.js.map +7 -0
  8. package/dist/bin/puzzle-geometry-bin.js +407 -0
  9. package/dist/bin/puzzle-geometry-bin.js.map +7 -0
  10. package/dist/bin/scramble.js +188 -0
  11. package/dist/bin/scramble.js.map +7 -0
  12. package/dist/bin/svg.js +56 -0
  13. package/dist/bin/svg.js.map +7 -0
  14. package/dist/lib/cubing/alg/index.d.ts +2 -0
  15. package/dist/lib/cubing/alg/index.js +43 -0
  16. package/dist/lib/cubing/alg/index.js.map +7 -0
  17. package/dist/lib/cubing/bluetooth/index.d.ts +189 -0
  18. package/dist/lib/cubing/bluetooth/index.js +2271 -0
  19. package/dist/lib/cubing/bluetooth/index.js.map +7 -0
  20. package/dist/lib/cubing/chunks/big-puzzle-orientation-BA6QHO5C.js +68 -0
  21. package/dist/lib/cubing/chunks/big-puzzle-orientation-BA6QHO5C.js.map +7 -0
  22. package/dist/lib/cubing/chunks/chunk-2VJB4TMH.js +1774 -0
  23. package/dist/lib/cubing/chunks/chunk-2VJB4TMH.js.map +7 -0
  24. package/dist/lib/cubing/chunks/chunk-52ZXJEUO.js +665 -0
  25. package/dist/lib/cubing/chunks/chunk-52ZXJEUO.js.map +7 -0
  26. package/dist/lib/cubing/chunks/chunk-56VZAEPF.js +274 -0
  27. package/dist/lib/cubing/chunks/chunk-56VZAEPF.js.map +7 -0
  28. package/dist/lib/cubing/chunks/chunk-7GUL3OBQ.js +9 -0
  29. package/dist/lib/cubing/chunks/chunk-7GUL3OBQ.js.map +7 -0
  30. package/dist/lib/cubing/chunks/chunk-7L7BJSIM.js +21 -0
  31. package/dist/lib/cubing/chunks/chunk-7L7BJSIM.js.map +7 -0
  32. package/dist/lib/cubing/chunks/chunk-AESPJKN6.js +265 -0
  33. package/dist/lib/cubing/chunks/chunk-AESPJKN6.js.map +7 -0
  34. package/dist/lib/cubing/chunks/chunk-C2Q347XS.js +89 -0
  35. package/dist/lib/cubing/chunks/chunk-C2Q347XS.js.map +7 -0
  36. package/dist/lib/cubing/chunks/chunk-CGBMJBU3.js +1195 -0
  37. package/dist/lib/cubing/chunks/chunk-CGBMJBU3.js.map +7 -0
  38. package/dist/lib/cubing/chunks/chunk-HZQONEMD.js +249 -0
  39. package/dist/lib/cubing/chunks/chunk-HZQONEMD.js.map +7 -0
  40. package/dist/lib/cubing/chunks/chunk-IAGCVPL3.js +1069 -0
  41. package/dist/lib/cubing/chunks/chunk-IAGCVPL3.js.map +7 -0
  42. package/dist/lib/cubing/chunks/chunk-NAPITA3L.js +1 -0
  43. package/dist/lib/cubing/chunks/chunk-NAPITA3L.js.map +7 -0
  44. package/dist/lib/cubing/chunks/chunk-XPDJUSZ7.js +1876 -0
  45. package/dist/lib/cubing/chunks/chunk-XPDJUSZ7.js.map +7 -0
  46. package/dist/lib/cubing/chunks/chunk-YSI6PF35.js +619 -0
  47. package/dist/lib/cubing/chunks/chunk-YSI6PF35.js.map +7 -0
  48. package/dist/lib/cubing/chunks/inside-LG2EAKCL.js +557 -0
  49. package/dist/lib/cubing/chunks/inside-LG2EAKCL.js.map +7 -0
  50. package/dist/lib/cubing/chunks/puzzles-dynamic-2x2x2-JYJJXB4V.js +142 -0
  51. package/dist/lib/cubing/chunks/puzzles-dynamic-2x2x2-JYJJXB4V.js.map +7 -0
  52. package/dist/lib/cubing/chunks/puzzles-dynamic-3x3x3-FYXD7SIU.js +365 -0
  53. package/dist/lib/cubing/chunks/puzzles-dynamic-3x3x3-FYXD7SIU.js.map +7 -0
  54. package/dist/lib/cubing/chunks/puzzles-dynamic-4x4x4-AIGABOAR.js +132 -0
  55. package/dist/lib/cubing/chunks/puzzles-dynamic-4x4x4-AIGABOAR.js.map +7 -0
  56. package/dist/lib/cubing/chunks/puzzles-dynamic-5x5x5-JUNRX27W.js +277 -0
  57. package/dist/lib/cubing/chunks/puzzles-dynamic-5x5x5-JUNRX27W.js.map +7 -0
  58. package/dist/lib/cubing/chunks/puzzles-dynamic-clock-USGQTDPO.js +836 -0
  59. package/dist/lib/cubing/chunks/puzzles-dynamic-clock-USGQTDPO.js.map +7 -0
  60. package/dist/lib/cubing/chunks/puzzles-dynamic-fto-WJHMLYCJ.js +100 -0
  61. package/dist/lib/cubing/chunks/puzzles-dynamic-fto-WJHMLYCJ.js.map +7 -0
  62. package/dist/lib/cubing/chunks/puzzles-dynamic-megaminx-2LVHIDL4.js +224 -0
  63. package/dist/lib/cubing/chunks/puzzles-dynamic-megaminx-2LVHIDL4.js.map +7 -0
  64. package/dist/lib/cubing/chunks/puzzles-dynamic-pyraminx-7UWX4HHI.js +93 -0
  65. package/dist/lib/cubing/chunks/puzzles-dynamic-pyraminx-7UWX4HHI.js.map +7 -0
  66. package/dist/lib/cubing/chunks/puzzles-dynamic-square1-PQEKBPFN.js +842 -0
  67. package/dist/lib/cubing/chunks/puzzles-dynamic-square1-PQEKBPFN.js.map +7 -0
  68. package/dist/lib/cubing/chunks/search-dynamic-sgs-2x2x2-XFKQ4VJS.js +125 -0
  69. package/dist/lib/cubing/chunks/search-dynamic-sgs-2x2x2-XFKQ4VJS.js.map +7 -0
  70. package/dist/lib/cubing/chunks/search-dynamic-sgs-megaminx-ZDOOLEDW.js +1564 -0
  71. package/dist/lib/cubing/chunks/search-dynamic-sgs-megaminx-ZDOOLEDW.js.map +7 -0
  72. package/dist/lib/cubing/chunks/search-dynamic-sgs-pyraminx-W6UJWBYY.js +108 -0
  73. package/dist/lib/cubing/chunks/search-dynamic-sgs-pyraminx-W6UJWBYY.js.map +7 -0
  74. package/dist/lib/cubing/chunks/search-dynamic-sgs-skewb-FXGKV4KD.js +125 -0
  75. package/dist/lib/cubing/chunks/search-dynamic-sgs-skewb-FXGKV4KD.js.map +7 -0
  76. package/dist/lib/cubing/chunks/search-dynamic-sgs-unofficial-YK6HA7BK.js +644 -0
  77. package/dist/lib/cubing/chunks/search-dynamic-sgs-unofficial-YK6HA7BK.js.map +7 -0
  78. package/dist/lib/cubing/chunks/search-dynamic-solve-3x3x3-DLMAGPXS.js +2549 -0
  79. package/dist/lib/cubing/chunks/search-dynamic-solve-3x3x3-DLMAGPXS.js.map +7 -0
  80. package/dist/lib/cubing/chunks/search-dynamic-solve-4x4x4-NONXQHOJ.js +2923 -0
  81. package/dist/lib/cubing/chunks/search-dynamic-solve-4x4x4-NONXQHOJ.js.map +7 -0
  82. package/dist/lib/cubing/chunks/search-dynamic-solve-fto-3GQ2HLSW.js +1405 -0
  83. package/dist/lib/cubing/chunks/search-dynamic-solve-fto-3GQ2HLSW.js.map +7 -0
  84. package/dist/lib/cubing/chunks/search-worker-entry.js +19 -0
  85. package/dist/lib/cubing/chunks/search-worker-entry.js.map +7 -0
  86. package/dist/lib/cubing/chunks/square1-stickerings-W2ZLZWIN.js +73 -0
  87. package/dist/lib/cubing/chunks/square1-stickerings-W2ZLZWIN.js.map +7 -0
  88. package/dist/lib/cubing/chunks/twips-2RNTWYNZ.js +433 -0
  89. package/dist/lib/cubing/chunks/twips-2RNTWYNZ.js.map +7 -0
  90. package/dist/lib/cubing/chunks/twips_wasm_bg-TJNYGA2C-23XTPLIK.js +10 -0
  91. package/dist/lib/cubing/chunks/twips_wasm_bg-TJNYGA2C-23XTPLIK.js.map +7 -0
  92. package/dist/lib/cubing/chunks/twisty-dynamic-3d-JO6OGKOF.js +2424 -0
  93. package/dist/lib/cubing/chunks/twisty-dynamic-3d-JO6OGKOF.js.map +7 -0
  94. package/dist/lib/cubing/index-BX6f56uo.d.ts +76 -0
  95. package/dist/lib/cubing/index-CcRu94bx.d.ts +2622 -0
  96. package/dist/lib/cubing/kpuzzle/index.d.ts +2 -0
  97. package/dist/lib/cubing/kpuzzle/index.js +12 -0
  98. package/dist/lib/cubing/kpuzzle/index.js.map +7 -0
  99. package/dist/lib/cubing/notation/index.d.ts +32 -0
  100. package/dist/lib/cubing/notation/index.js +20 -0
  101. package/dist/lib/cubing/notation/index.js.map +7 -0
  102. package/dist/lib/cubing/outside-BCzgSYQ_.d.ts +38 -0
  103. package/dist/lib/cubing/protocol/index.d.ts +28 -0
  104. package/dist/lib/cubing/protocol/index.js +20 -0
  105. package/dist/lib/cubing/protocol/index.js.map +7 -0
  106. package/dist/lib/cubing/puzzle-geometry/index.d.ts +2 -0
  107. package/dist/lib/cubing/puzzle-geometry/index.js +5024 -0
  108. package/dist/lib/cubing/puzzle-geometry/index.js.map +7 -0
  109. package/dist/lib/cubing/puzzles/index.d.ts +2 -0
  110. package/dist/lib/cubing/puzzles/index.js +23 -0
  111. package/dist/lib/cubing/puzzles/index.js.map +7 -0
  112. package/dist/lib/cubing/scramble/index.d.ts +2 -0
  113. package/dist/lib/cubing/scramble/index.js +16 -0
  114. package/dist/lib/cubing/scramble/index.js.map +7 -0
  115. package/dist/lib/cubing/search/index.d.ts +7 -0
  116. package/dist/lib/cubing/search/index.js +37 -0
  117. package/dist/lib/cubing/search/index.js.map +7 -0
  118. package/dist/lib/cubing/stream/index.d.ts +2 -0
  119. package/dist/lib/cubing/stream/index.js +111 -0
  120. package/dist/lib/cubing/stream/index.js.map +7 -0
  121. package/dist/lib/cubing/twisty/index.d.ts +2 -0
  122. package/dist/lib/cubing/twisty/index.js +6236 -0
  123. package/dist/lib/cubing/twisty/index.js.map +7 -0
  124. package/experimental-json-schema/kpuzzle/KPatternData.schema.json +34 -0
  125. package/experimental-json-schema/kpuzzle/KPuzzleDefinition.schema.json +97 -0
  126. package/experimental-json-schema/kpuzzle/KTransformationData.schema.json +27 -0
  127. package/kpuzzle/index.d.ts +1 -0
  128. package/notation/index.d.ts +1 -0
  129. package/package.json +146 -0
  130. package/protocol/index.d.ts +1 -0
  131. package/puzzle-geometry/index.d.ts +1 -0
  132. package/puzzles/index.d.ts +1 -0
  133. package/scramble/index.d.ts +1 -0
  134. package/search/index.d.ts +1 -0
  135. package/stream/index.d.ts +1 -0
  136. package/twisty/index.d.ts +1 -0
@@ -0,0 +1,1876 @@
1
+ // src/cubing/alg/common.ts
2
+ var writeAlgDebugField = false;
3
+ var Comparable = class {
4
+ is(c) {
5
+ return this instanceof c;
6
+ }
7
+ as(c) {
8
+ return this instanceof c ? this : null;
9
+ }
10
+ };
11
+ var AlgCommon = class extends Comparable {
12
+ constructor() {
13
+ super();
14
+ if (writeAlgDebugField) {
15
+ Object.defineProperty(this, "_debugStr", {
16
+ get: () => {
17
+ return this.toString();
18
+ }
19
+ });
20
+ }
21
+ }
22
+ get log() {
23
+ return console.log.bind(console, this, this.toString());
24
+ }
25
+ };
26
+
27
+ // src/cubing/alg/iteration.ts
28
+ function toggleDirection(iterationDirection, flip = true) {
29
+ if (!flip) {
30
+ return iterationDirection;
31
+ }
32
+ switch (iterationDirection) {
33
+ case 1 /* Forwards */:
34
+ return -1 /* Backwards */;
35
+ case -1 /* Backwards */:
36
+ return 1 /* Forwards */;
37
+ }
38
+ }
39
+ function direct(g, iterDir) {
40
+ return iterDir === -1 /* Backwards */ ? Array.from(g).reverse() : g;
41
+ }
42
+ function reverse(g) {
43
+ return Array.from(g).reverse();
44
+ }
45
+ function* directedGenerator(g, direction) {
46
+ direction === -1 /* Backwards */ ? yield* reverseGenerator(g) : yield* g;
47
+ }
48
+ function* reverseGenerator(g) {
49
+ for (const t of Array.from(g).reverse()) {
50
+ yield t;
51
+ }
52
+ }
53
+
54
+ // src/cubing/alg/alg-nodes/containers/Commutator.ts
55
+ var Commutator = class _Commutator extends AlgCommon {
56
+ #A;
57
+ #B;
58
+ constructor(aSource, bSource) {
59
+ super();
60
+ this.#A = experimentalEnsureAlg(aSource);
61
+ this.#B = experimentalEnsureAlg(bSource);
62
+ }
63
+ get A() {
64
+ return this.#A;
65
+ }
66
+ get B() {
67
+ return this.#B;
68
+ }
69
+ isIdentical(other) {
70
+ const otherAsCommutator = other.as(_Commutator);
71
+ return !!(otherAsCommutator?.A.isIdentical(this.A) && otherAsCommutator?.B.isIdentical(this.B));
72
+ }
73
+ invert() {
74
+ return new _Commutator(this.#B, this.#A);
75
+ }
76
+ *experimentalExpand(iterDir = 1 /* Forwards */, depth) {
77
+ depth ??= Infinity;
78
+ if (depth === 0) {
79
+ yield iterDir === 1 /* Forwards */ ? this : this.invert();
80
+ } else {
81
+ if (iterDir === 1 /* Forwards */) {
82
+ yield* this.A.experimentalExpand(
83
+ 1 /* Forwards */,
84
+ depth - 1
85
+ );
86
+ yield* this.B.experimentalExpand(
87
+ 1 /* Forwards */,
88
+ depth - 1
89
+ );
90
+ yield* this.A.experimentalExpand(
91
+ -1 /* Backwards */,
92
+ depth - 1
93
+ );
94
+ yield* this.B.experimentalExpand(
95
+ -1 /* Backwards */,
96
+ depth - 1
97
+ );
98
+ } else {
99
+ yield* this.B.experimentalExpand(
100
+ 1 /* Forwards */,
101
+ depth - 1
102
+ );
103
+ yield* this.A.experimentalExpand(
104
+ 1 /* Forwards */,
105
+ depth - 1
106
+ );
107
+ yield* this.B.experimentalExpand(
108
+ -1 /* Backwards */,
109
+ depth - 1
110
+ );
111
+ yield* this.A.experimentalExpand(
112
+ -1 /* Backwards */,
113
+ depth - 1
114
+ );
115
+ }
116
+ }
117
+ }
118
+ toString(experimentalSerializationOptions) {
119
+ return `[${this.#A.toString(experimentalSerializationOptions)}, ${this.#B.toString(experimentalSerializationOptions)}]`;
120
+ }
121
+ };
122
+
123
+ // src/cubing/alg/alg-nodes/containers/Conjugate.ts
124
+ var Conjugate = class _Conjugate extends AlgCommon {
125
+ #A;
126
+ #B;
127
+ constructor(aSource, bSource) {
128
+ super();
129
+ this.#A = experimentalEnsureAlg(aSource);
130
+ this.#B = experimentalEnsureAlg(bSource);
131
+ }
132
+ get A() {
133
+ return this.#A;
134
+ }
135
+ get B() {
136
+ return this.#B;
137
+ }
138
+ isIdentical(other) {
139
+ const otherAsConjugate = other.as(_Conjugate);
140
+ return !!(otherAsConjugate?.A.isIdentical(this.A) && otherAsConjugate?.B.isIdentical(this.B));
141
+ }
142
+ invert() {
143
+ return new _Conjugate(this.#A, this.#B.invert());
144
+ }
145
+ *experimentalExpand(iterDir, depth) {
146
+ depth ??= Infinity;
147
+ if (depth === 0) {
148
+ yield iterDir === 1 /* Forwards */ ? this : this.invert();
149
+ } else {
150
+ yield* this.A.experimentalExpand(1 /* Forwards */, depth - 1);
151
+ yield* this.B.experimentalExpand(iterDir, depth - 1);
152
+ yield* this.A.experimentalExpand(-1 /* Backwards */, depth - 1);
153
+ }
154
+ }
155
+ toString(experimentalSerializationOptions) {
156
+ return `[${this.A.toString(experimentalSerializationOptions)}: ${this.B.toString(experimentalSerializationOptions)}]`;
157
+ }
158
+ };
159
+
160
+ // src/cubing/alg/limits.ts
161
+ var MAX_INT = 2147483647;
162
+ var MAX_INT_DESCRIPTION = "2^31 - 1";
163
+ var MIN_INT = -2147483648;
164
+
165
+ // src/cubing/alg/AlgBuilder.ts
166
+ var AlgBuilder = class {
167
+ #algNodes = [];
168
+ push(u) {
169
+ this.#algNodes.push(u);
170
+ }
171
+ // TODO: Allow FlexibleAlgSource?
172
+ /** @deprecated */
173
+ experimentalPushAlg(alg) {
174
+ for (const u of alg.childAlgNodes()) {
175
+ this.push(u);
176
+ }
177
+ }
178
+ // TODO: can we guarantee this to be fast in the permanent API?
179
+ experimentalNumAlgNodes() {
180
+ return this.#algNodes.length;
181
+ }
182
+ // can be called multiple times, even if you push alg nodes inbetween.
183
+ toAlg() {
184
+ return new Alg(this.#algNodes);
185
+ }
186
+ reset() {
187
+ this.#algNodes = [];
188
+ }
189
+ };
190
+
191
+ // src/cubing/alg/alg-nodes/leaves/LineComment.ts
192
+ var LineComment = class _LineComment extends AlgCommon {
193
+ #text;
194
+ constructor(commentText) {
195
+ super();
196
+ if (commentText.includes("\n") || commentText.includes("\r")) {
197
+ throw new Error("LineComment cannot contain newline");
198
+ }
199
+ this.#text = commentText;
200
+ }
201
+ get text() {
202
+ return this.#text;
203
+ }
204
+ isIdentical(other) {
205
+ const otherAsLineComment = other;
206
+ return other.is(_LineComment) && this.#text === otherAsLineComment.#text;
207
+ }
208
+ invert() {
209
+ return this;
210
+ }
211
+ *experimentalExpand(_iterDir = 1 /* Forwards */, _depth = Infinity) {
212
+ yield this;
213
+ }
214
+ toString(_experimentalSerializationOptions) {
215
+ return `//${this.#text}`;
216
+ }
217
+ // toJSON(): LineCommentJSON {
218
+ // return {
219
+ // type: "comment",
220
+ // text: this.#text,
221
+ // };
222
+ // }
223
+ };
224
+
225
+ // src/cubing/alg/alg-nodes/leaves/Newline.ts
226
+ var Newline = class _Newline extends AlgCommon {
227
+ toString(_experimentalSerializationOptions) {
228
+ return "\n";
229
+ }
230
+ isIdentical(other) {
231
+ return other.is(_Newline);
232
+ }
233
+ invert() {
234
+ return this;
235
+ }
236
+ *experimentalExpand(_iterDir = 1 /* Forwards */, _depth = Infinity) {
237
+ yield this;
238
+ }
239
+ };
240
+
241
+ // src/cubing/alg/alg-nodes/leaves/Pause.ts
242
+ var Pause = class _Pause extends AlgCommon {
243
+ experimentalNISSGrouping;
244
+ // TODO: tie this to the alg
245
+ toString(_experimentalSerializationOptions) {
246
+ return ".";
247
+ }
248
+ isIdentical(other) {
249
+ return other.is(_Pause);
250
+ }
251
+ invert() {
252
+ return this;
253
+ }
254
+ *experimentalExpand(_iterDir = 1 /* Forwards */, _depth = Infinity) {
255
+ yield this;
256
+ }
257
+ };
258
+
259
+ // src/cubing/alg/debug.ts
260
+ var algDebugGlobals = {
261
+ caretNISSNotationEnabled: true
262
+ };
263
+ function setAlgDebug(options) {
264
+ if ("caretNISSNotationEnabled" in options) {
265
+ algDebugGlobals.caretNISSNotationEnabled = !!options.caretNISSNotationEnabled;
266
+ }
267
+ }
268
+
269
+ // src/cubing/alg/parseAlg.ts
270
+ function parseIntWithEmptyFallback(n, emptyFallback) {
271
+ return n ? parseInt(n, 10) : emptyFallback;
272
+ }
273
+ var AMOUNT_REGEX = /^(\d+)?('?)/;
274
+ var MOVE_START_REGEX = /^[_\dA-Za-z]/;
275
+ var QUANTUM_MOVE_REGEX = /^((([1-9]\d*)-)?([1-9]\d*))?([_A-Za-z]+)/;
276
+ var COMMENT_TEXT_REGEX = /^[^\n]*/;
277
+ var SQUARE1_PAIR_START_REGEX = /^(-?\d+), ?/;
278
+ var SQUARE1_PAIR_END_REGEX = /^(-?\d+)\)/;
279
+ function parseAlg(s) {
280
+ return new AlgParser().parseAlg(s);
281
+ }
282
+ function parseMove(s) {
283
+ return new AlgParser().parseMove(s);
284
+ }
285
+ function parseQuantumMove(s) {
286
+ return new AlgParser().parseQuantumMove(s);
287
+ }
288
+ var startCharIndexKey = /* @__PURE__ */ Symbol("startCharIndex");
289
+ var endCharIndexKey = /* @__PURE__ */ Symbol("endCharIndex");
290
+ function addCharIndices(t, startCharIndex, endCharIndex) {
291
+ const parsedT = t;
292
+ parsedT[startCharIndexKey] = startCharIndex;
293
+ parsedT[endCharIndexKey] = endCharIndex;
294
+ return parsedT;
295
+ }
296
+ function transferCharIndex(from, to) {
297
+ if (startCharIndexKey in from) {
298
+ to[startCharIndexKey] = from[startCharIndexKey];
299
+ }
300
+ if (endCharIndexKey in from) {
301
+ to[endCharIndexKey] = from[endCharIndexKey];
302
+ }
303
+ return to;
304
+ }
305
+ var AlgParser = class {
306
+ #input = "";
307
+ #idx = 0;
308
+ #nissQueue = [];
309
+ parseAlg(input) {
310
+ this.#input = input;
311
+ this.#idx = 0;
312
+ const alg = this.parseAlgWithStopping([]);
313
+ this.mustBeAtEndOfInput();
314
+ const algNodes = Array.from(alg.childAlgNodes());
315
+ if (this.#nissQueue.length > 0) {
316
+ for (const nissGrouping of this.#nissQueue.reverse()) {
317
+ algNodes.push(nissGrouping);
318
+ }
319
+ }
320
+ const newAlg = new Alg(algNodes);
321
+ const {
322
+ [startCharIndexKey]: startCharIndex,
323
+ [endCharIndexKey]: endCharIndex
324
+ } = alg;
325
+ addCharIndices(newAlg, startCharIndex, endCharIndex);
326
+ return newAlg;
327
+ }
328
+ parseMove(input) {
329
+ this.#input = input;
330
+ this.#idx = 0;
331
+ const move = this.parseMoveImpl();
332
+ this.mustBeAtEndOfInput();
333
+ return move;
334
+ }
335
+ parseQuantumMove(input) {
336
+ this.#input = input;
337
+ this.#idx = 0;
338
+ const quantumMove = this.parseQuantumMoveImpl();
339
+ this.mustBeAtEndOfInput();
340
+ return quantumMove;
341
+ }
342
+ mustBeAtEndOfInput() {
343
+ if (this.#idx !== this.#input.length) {
344
+ throw new Error("parsing unexpectedly ended early");
345
+ }
346
+ }
347
+ parseAlgWithStopping(stopBefore) {
348
+ let algStartIdx = this.#idx;
349
+ let algEndIdx = this.#idx;
350
+ const algBuilder = new AlgBuilder();
351
+ let crowded = false;
352
+ const mustNotBeCrowded = (idx) => {
353
+ if (crowded) {
354
+ throw new Error(
355
+ `Unexpected character at index ${idx}. Are you missing a space?`
356
+ );
357
+ }
358
+ };
359
+ while (this.#idx < this.#input.length) {
360
+ const savedCharIndex = this.#idx;
361
+ if (stopBefore.includes(this.#input[this.#idx])) {
362
+ return addCharIndices(algBuilder.toAlg(), algStartIdx, algEndIdx);
363
+ }
364
+ if (this.tryConsumeNext(" ")) {
365
+ crowded = false;
366
+ if (algBuilder.experimentalNumAlgNodes() === 0) {
367
+ algStartIdx = this.#idx;
368
+ }
369
+ } else if (MOVE_START_REGEX.test(this.#input[this.#idx])) {
370
+ mustNotBeCrowded(savedCharIndex);
371
+ const move = this.parseMoveImpl();
372
+ algBuilder.push(move);
373
+ crowded = true;
374
+ algEndIdx = this.#idx;
375
+ } else if (this.tryConsumeNext("(")) {
376
+ mustNotBeCrowded(savedCharIndex);
377
+ const sq1PairStartMatch = this.tryRegex(SQUARE1_PAIR_START_REGEX);
378
+ if (sq1PairStartMatch) {
379
+ const topAmountString = sq1PairStartMatch[1];
380
+ const savedCharIndexD = this.#idx;
381
+ const sq1PairEndMatch = this.parseRegex(SQUARE1_PAIR_END_REGEX);
382
+ const uMove = addCharIndices(
383
+ new Move(new QuantumMove("U_SQ_"), parseInt(topAmountString, 10)),
384
+ savedCharIndex + 1,
385
+ savedCharIndex + 1 + topAmountString.length
386
+ );
387
+ const dMove = addCharIndices(
388
+ new Move(
389
+ new QuantumMove("D_SQ_"),
390
+ parseInt(sq1PairEndMatch[1], 10)
391
+ ),
392
+ savedCharIndexD,
393
+ this.#idx - 1
394
+ );
395
+ const alg = addCharIndices(
396
+ new Alg([uMove, dMove]),
397
+ savedCharIndex + 1,
398
+ this.#idx - 1
399
+ );
400
+ algBuilder.push(
401
+ addCharIndices(new Grouping(alg), savedCharIndex, this.#idx)
402
+ );
403
+ crowded = true;
404
+ algEndIdx = this.#idx;
405
+ } else {
406
+ const alg = this.parseAlgWithStopping([")"]);
407
+ this.mustConsumeNext(")");
408
+ const amount = this.parseAmount();
409
+ algBuilder.push(
410
+ addCharIndices(
411
+ new Grouping(alg, amount),
412
+ savedCharIndex,
413
+ this.#idx
414
+ )
415
+ );
416
+ crowded = true;
417
+ algEndIdx = this.#idx;
418
+ }
419
+ } else if (this.tryConsumeNext("^")) {
420
+ if (!algDebugGlobals.caretNISSNotationEnabled) {
421
+ throw new Error(
422
+ "Alg contained a caret but caret NISS notation is not enabled."
423
+ );
424
+ }
425
+ this.mustConsumeNext("(");
426
+ const alg = this.parseAlgWithStopping([")"]);
427
+ this.popNext();
428
+ const grouping = new Grouping(alg, -1);
429
+ const placeholder = new Pause();
430
+ grouping.experimentalNISSPlaceholder = placeholder;
431
+ placeholder.experimentalNISSGrouping = grouping;
432
+ this.#nissQueue.push(grouping);
433
+ algBuilder.push(placeholder);
434
+ } else if (this.tryConsumeNext("[")) {
435
+ mustNotBeCrowded(savedCharIndex);
436
+ const A = this.parseAlgWithStopping([",", ":"]);
437
+ const separator = this.popNext();
438
+ const B = this.parseAlgWithStopping(["]"]);
439
+ this.mustConsumeNext("]");
440
+ let unrepeated;
441
+ switch (separator) {
442
+ case ":": {
443
+ unrepeated = addCharIndices(
444
+ new Conjugate(A, B),
445
+ savedCharIndex,
446
+ this.#idx
447
+ );
448
+ crowded = true;
449
+ algEndIdx = this.#idx;
450
+ break;
451
+ }
452
+ case ",": {
453
+ unrepeated = addCharIndices(
454
+ new Commutator(A, B),
455
+ savedCharIndex,
456
+ this.#idx
457
+ );
458
+ crowded = true;
459
+ algEndIdx = this.#idx;
460
+ break;
461
+ }
462
+ default:
463
+ throw new Error("unexpected parsing error");
464
+ }
465
+ const afterClosingBracketIdx = this.#idx;
466
+ const amount = this.parseAmount();
467
+ if (amount === 1) {
468
+ algBuilder.push(unrepeated);
469
+ } else {
470
+ const unrepeatedAlg = addCharIndices(
471
+ new Alg([unrepeated]),
472
+ savedCharIndex,
473
+ afterClosingBracketIdx
474
+ );
475
+ const grouping = addCharIndices(
476
+ new Grouping(unrepeatedAlg, amount),
477
+ savedCharIndex,
478
+ this.#idx
479
+ );
480
+ algBuilder.push(grouping);
481
+ }
482
+ crowded = true;
483
+ algEndIdx = this.#idx;
484
+ } else if (this.tryConsumeNext("\n")) {
485
+ algBuilder.push(
486
+ addCharIndices(new Newline(), savedCharIndex, this.#idx)
487
+ );
488
+ crowded = false;
489
+ algEndIdx = this.#idx;
490
+ } else if (this.tryConsumeNext("/")) {
491
+ if (this.tryConsumeNext("/")) {
492
+ mustNotBeCrowded(savedCharIndex);
493
+ const [text] = this.parseRegex(COMMENT_TEXT_REGEX);
494
+ algBuilder.push(
495
+ addCharIndices(new LineComment(text), savedCharIndex, this.#idx)
496
+ );
497
+ crowded = false;
498
+ algEndIdx = this.#idx;
499
+ } else {
500
+ algBuilder.push(
501
+ addCharIndices(new Move("_SLASH_"), savedCharIndex, this.#idx)
502
+ );
503
+ crowded = true;
504
+ algEndIdx = this.#idx;
505
+ }
506
+ } else if (this.tryConsumeNext(".")) {
507
+ mustNotBeCrowded(savedCharIndex);
508
+ algBuilder.push(addCharIndices(new Pause(), savedCharIndex, this.#idx));
509
+ crowded = true;
510
+ algEndIdx = this.#idx;
511
+ } else {
512
+ throw new Error(`Unexpected character: ${this.popNext()}`);
513
+ }
514
+ }
515
+ if (this.#idx !== this.#input.length) {
516
+ throw new Error("did not finish parsing?");
517
+ }
518
+ if (stopBefore.length > 0) {
519
+ throw new Error("expected stopping");
520
+ }
521
+ return addCharIndices(algBuilder.toAlg(), algStartIdx, algEndIdx);
522
+ }
523
+ parseQuantumMoveImpl() {
524
+ const [, , , outerLayerStr, innerLayerStr, family] = this.parseRegex(QUANTUM_MOVE_REGEX);
525
+ return new QuantumMove(
526
+ family,
527
+ parseIntWithEmptyFallback(innerLayerStr, void 0),
528
+ parseIntWithEmptyFallback(outerLayerStr, void 0)
529
+ );
530
+ }
531
+ parseMoveImpl() {
532
+ const savedCharIndex = this.#idx;
533
+ if (this.tryConsumeNext("/")) {
534
+ return addCharIndices(new Move("_SLASH_"), savedCharIndex, this.#idx);
535
+ }
536
+ let quantumMove = this.parseQuantumMoveImpl();
537
+ let [amount, hadEmptyAbsAmount] = this.parseAmountAndTrackEmptyAbsAmount();
538
+ const suffix = this.parseMoveSuffix();
539
+ if (suffix) {
540
+ if (amount < 0) {
541
+ throw new Error("uh-oh");
542
+ }
543
+ if ((suffix === "++" || suffix === "--") && amount !== 1) {
544
+ throw new Error(
545
+ "Pochmann ++ or -- moves cannot have an amount other than 1."
546
+ );
547
+ }
548
+ if ((suffix === "++" || suffix === "--") && !hadEmptyAbsAmount) {
549
+ throw new Error(
550
+ "Pochmann ++ or -- moves cannot have an amount written as a number."
551
+ );
552
+ }
553
+ if ((suffix === "+" || suffix === "-") && hadEmptyAbsAmount) {
554
+ throw new Error(
555
+ "Clock dial moves must have an amount written as a natural number followed by + or -."
556
+ );
557
+ }
558
+ if (suffix.startsWith("+")) {
559
+ quantumMove = quantumMove.modified({
560
+ family: `${quantumMove.family}_${suffix === "+" ? "PLUS" : "PLUSPLUS"}_`
561
+ // TODO
562
+ });
563
+ }
564
+ if (suffix.startsWith("-")) {
565
+ quantumMove = quantumMove.modified({
566
+ family: `${quantumMove.family}_${suffix === "-" ? "PLUS" : "PLUSPLUS"}_`
567
+ // TODO
568
+ });
569
+ amount *= -1;
570
+ }
571
+ }
572
+ const move = addCharIndices(
573
+ new Move(quantumMove, amount),
574
+ savedCharIndex,
575
+ this.#idx
576
+ );
577
+ return move;
578
+ }
579
+ parseMoveSuffix() {
580
+ if (this.tryConsumeNext("+")) {
581
+ if (this.tryConsumeNext("+")) {
582
+ return "++";
583
+ }
584
+ return "+";
585
+ }
586
+ if (this.tryConsumeNext("-")) {
587
+ if (this.tryConsumeNext("-")) {
588
+ return "--";
589
+ }
590
+ return "-";
591
+ }
592
+ return null;
593
+ }
594
+ parseAmountAndTrackEmptyAbsAmount() {
595
+ const savedIdx = this.#idx;
596
+ const [, absAmountStr, primeStr] = this.parseRegex(AMOUNT_REGEX);
597
+ if (absAmountStr?.startsWith("0") && absAmountStr !== "0") {
598
+ throw new Error(
599
+ `Error at char index ${savedIdx}: An amount can only start with 0 if it's exactly the digit 0.`
600
+ );
601
+ }
602
+ return [
603
+ parseIntWithEmptyFallback(absAmountStr, 1) * (primeStr === "'" ? -1 : 1),
604
+ !absAmountStr
605
+ ];
606
+ }
607
+ parseAmount() {
608
+ const savedIdx = this.#idx;
609
+ const [, absAmountStr, primeStr] = this.parseRegex(AMOUNT_REGEX);
610
+ if (absAmountStr?.startsWith("0") && absAmountStr !== "0") {
611
+ throw new Error(
612
+ `Error at char index ${savedIdx}: An amount number can only start with 0 if it's exactly the digit 0.`
613
+ );
614
+ }
615
+ return parseIntWithEmptyFallback(absAmountStr, 1) * (primeStr === "'" ? -1 : 1);
616
+ }
617
+ parseRegex(regex) {
618
+ const arr = regex.exec(this.remaining());
619
+ if (arr === null) {
620
+ throw new Error("internal parsing error");
621
+ }
622
+ this.#idx += arr[0].length;
623
+ return arr;
624
+ }
625
+ // TOD: can we avoid this?
626
+ tryRegex(regex) {
627
+ const arr = regex.exec(this.remaining());
628
+ if (arr === null) {
629
+ return null;
630
+ }
631
+ this.#idx += arr[0].length;
632
+ return arr;
633
+ }
634
+ remaining() {
635
+ return this.#input.slice(this.#idx);
636
+ }
637
+ popNext() {
638
+ const next = this.#input[this.#idx];
639
+ this.#idx++;
640
+ return next;
641
+ }
642
+ tryConsumeNext(expected) {
643
+ if (this.#input[this.#idx] === expected) {
644
+ this.#idx++;
645
+ return true;
646
+ }
647
+ return false;
648
+ }
649
+ mustConsumeNext(expected) {
650
+ const next = this.popNext();
651
+ if (next !== expected) {
652
+ throw new Error(
653
+ `expected \`${expected}\` while parsing, encountered ${next}`
654
+ );
655
+ }
656
+ return next;
657
+ }
658
+ };
659
+
660
+ // src/cubing/alg/warnOnce.ts
661
+ var warned = /* @__PURE__ */ new Set();
662
+ function warnOnce(s) {
663
+ if (!warned.has(s)) {
664
+ console.warn(s);
665
+ warned.add(s);
666
+ }
667
+ }
668
+
669
+ // src/cubing/alg/alg-nodes/QuantumWithAmount.ts
670
+ var QuantumWithAmount = class {
671
+ quantum;
672
+ amount;
673
+ constructor(quantum, amount = 1) {
674
+ this.quantum = quantum;
675
+ this.amount = amount;
676
+ if (!Number.isInteger(this.amount) || this.amount < MIN_INT || this.amount > MAX_INT) {
677
+ throw new Error(
678
+ `AlgNode amount absolute value must be a non-negative integer below ${MAX_INT_DESCRIPTION}.`
679
+ );
680
+ }
681
+ }
682
+ suffix() {
683
+ let s = "";
684
+ const absAmount = Math.abs(this.amount);
685
+ if (absAmount !== 1) {
686
+ s += absAmount;
687
+ }
688
+ if (this.amount < 0) {
689
+ s += "'";
690
+ }
691
+ return s;
692
+ }
693
+ isIdentical(other) {
694
+ return this.quantum.isIdentical(other.quantum) && this.amount === other.amount;
695
+ }
696
+ // TODO: `Conjugate` and `Commutator` decrement `depth` inside the quantum, `Grouping` has to do it outside the quantum.
697
+ *experimentalExpand(iterDir, depth) {
698
+ const absAmount = Math.abs(this.amount);
699
+ const newIterDir = toggleDirection(iterDir, this.amount < 0);
700
+ for (let i = 0; i < absAmount; i++) {
701
+ yield* this.quantum.experimentalExpand(newIterDir, depth);
702
+ }
703
+ }
704
+ };
705
+
706
+ // src/cubing/alg/alg-nodes/leaves/Move.ts
707
+ var QuantumMove = class _QuantumMove extends Comparable {
708
+ #family;
709
+ #innerLayer;
710
+ #outerLayer;
711
+ constructor(family, innerLayer, outerLayer) {
712
+ super();
713
+ this.#family = family;
714
+ this.#innerLayer = innerLayer ?? null;
715
+ this.#outerLayer = outerLayer ?? null;
716
+ Object.freeze(this);
717
+ if (this.#innerLayer !== null && (!Number.isInteger(this.#innerLayer) || this.#innerLayer < 1 || this.#innerLayer > MAX_INT)) {
718
+ throw new Error(
719
+ `QuantumMove inner layer must be a positive integer below ${MAX_INT_DESCRIPTION}.`
720
+ );
721
+ }
722
+ if (this.#outerLayer !== null && (!Number.isInteger(this.#outerLayer) || this.#outerLayer < 1 || this.#outerLayer > MAX_INT)) {
723
+ throw new Error(
724
+ `QuantumMove outer layer must be a positive integer below ${MAX_INT_DESCRIPTION}.`
725
+ );
726
+ }
727
+ if (this.#outerLayer !== null && this.#innerLayer !== null && this.#innerLayer <= this.#outerLayer) {
728
+ throw new Error(
729
+ "QuantumMove outer layer must be smaller than inner layer."
730
+ );
731
+ }
732
+ if (this.#outerLayer !== null && this.#innerLayer === null) {
733
+ throw new Error(
734
+ "QuantumMove with an outer layer must have an inner layer"
735
+ );
736
+ }
737
+ }
738
+ static fromString(s) {
739
+ return parseQuantumMove(s);
740
+ }
741
+ // TODO: `modify`?
742
+ modified(modifications) {
743
+ return new _QuantumMove(
744
+ modifications.family ?? this.#family,
745
+ modifications.innerLayer ?? this.#innerLayer,
746
+ modifications.outerLayer ?? this.#outerLayer
747
+ );
748
+ }
749
+ isIdentical(other) {
750
+ const otherAsQuantumMove = other;
751
+ return other.is(_QuantumMove) && this.#family === otherAsQuantumMove.#family && this.#innerLayer === otherAsQuantumMove.#innerLayer && this.#outerLayer === otherAsQuantumMove.#outerLayer;
752
+ }
753
+ // TODO: provide something more useful on average.
754
+ /** @deprecated */
755
+ get family() {
756
+ return this.#family;
757
+ }
758
+ // TODO: provide something more useful on average.
759
+ /** @deprecated */
760
+ get outerLayer() {
761
+ return this.#outerLayer;
762
+ }
763
+ // TODO: provide something more useful on average.
764
+ /** @deprecated */
765
+ get innerLayer() {
766
+ return this.#innerLayer;
767
+ }
768
+ experimentalExpand() {
769
+ throw new Error(
770
+ "experimentalExpand() cannot be called on a `QuantumMove` directly."
771
+ );
772
+ }
773
+ toString(_experimentalSerializationOptions) {
774
+ let s = this.#family;
775
+ if (this.#innerLayer !== null) {
776
+ s = String(this.#innerLayer) + s;
777
+ if (this.#outerLayer !== null) {
778
+ s = `${String(this.#outerLayer)}-${s}`;
779
+ }
780
+ }
781
+ return s;
782
+ }
783
+ };
784
+ var Move = class _Move extends AlgCommon {
785
+ // @ts-expect-error False positive due to the `return` in the constructor.
786
+ #quantumWithAmount;
787
+ constructor(...args) {
788
+ super();
789
+ if (typeof args[0] === "string") {
790
+ if (args[1] ?? null) {
791
+ this.#quantumWithAmount = new QuantumWithAmount(
792
+ QuantumMove.fromString(args[0]),
793
+ args[1]
794
+ );
795
+ return;
796
+ } else {
797
+ return _Move.fromString(args[0]);
798
+ }
799
+ }
800
+ this.#quantumWithAmount = new QuantumWithAmount(
801
+ args[0],
802
+ args[1]
803
+ );
804
+ }
805
+ isIdentical(other) {
806
+ const otherAsMove = other.as(_Move);
807
+ return !!otherAsMove && this.#quantumWithAmount.isIdentical(otherAsMove.#quantumWithAmount);
808
+ }
809
+ invert() {
810
+ return transferCharIndex(
811
+ this,
812
+ new _Move(
813
+ this.#quantumWithAmount.quantum,
814
+ this.#isSlash() ? this.amount : -this.amount
815
+ )
816
+ );
817
+ }
818
+ *experimentalExpand(iterDir = 1 /* Forwards */) {
819
+ if (iterDir === 1 /* Forwards */) {
820
+ yield this;
821
+ } else {
822
+ yield this.modified({
823
+ amount: -this.amount
824
+ });
825
+ }
826
+ }
827
+ get quantum() {
828
+ return this.#quantumWithAmount.quantum;
829
+ }
830
+ // TODO: `modify`?
831
+ modified(modifications) {
832
+ return new _Move(
833
+ this.#quantumWithAmount.quantum.modified(modifications),
834
+ modifications.amount ?? this.amount
835
+ );
836
+ }
837
+ static fromString(s) {
838
+ return parseMove(s);
839
+ }
840
+ get amount() {
841
+ return this.#quantumWithAmount.amount;
842
+ }
843
+ /** @deprecated */
844
+ get type() {
845
+ warnOnce("deprecated: type");
846
+ return "blockMove";
847
+ }
848
+ /** @deprecated */
849
+ get family() {
850
+ return this.#quantumWithAmount.quantum.family ?? void 0;
851
+ }
852
+ /** @deprecated */
853
+ get outerLayer() {
854
+ return this.#quantumWithAmount.quantum.outerLayer ?? void 0;
855
+ }
856
+ /** @deprecated */
857
+ get innerLayer() {
858
+ return this.#quantumWithAmount.quantum.innerLayer ?? void 0;
859
+ }
860
+ #cachedSlashMove;
861
+ #isSlash() {
862
+ return this.isIdentical(this.#cachedSlashMove ??= new _Move("_SLASH_"));
863
+ }
864
+ toString(experimentalSerializationOptions) {
865
+ if (experimentalSerializationOptions?.notation !== "LGN") {
866
+ if (this.#isSlash()) {
867
+ return "/";
868
+ }
869
+ if (this.family.endsWith("_PLUS_")) {
870
+ return this.#quantumWithAmount.quantum.toString().slice(0, -6) + Math.abs(this.amount) + (this.amount < 0 ? "-" : "+");
871
+ }
872
+ if (this.family.endsWith("_PLUSPLUS_")) {
873
+ const absAmount = Math.abs(this.amount);
874
+ return this.#quantumWithAmount.quantum.toString().slice(0, -10) + (absAmount === 1 ? "" : absAmount) + (this.amount < 0 ? "--" : "++");
875
+ }
876
+ }
877
+ return this.#quantumWithAmount.quantum.toString(
878
+ experimentalSerializationOptions
879
+ ) + this.#quantumWithAmount.suffix();
880
+ }
881
+ // // TODO: Serialize as a string?
882
+ // toJSON(): MoveJSON {
883
+ // return {
884
+ // type: "move",
885
+ // family: this.family,
886
+ // innerLayer: this.innerLayer,
887
+ // outerLayer: this.outerLayer,
888
+ // };
889
+ // }
890
+ };
891
+
892
+ // src/cubing/alg/alg-nodes/containers/Grouping.ts
893
+ var Square1TupleFormatter = class {
894
+ quantumU_SQ_ = null;
895
+ quantumD_SQ_ = null;
896
+ format(grouping, experimentalSerializationOptions) {
897
+ if (experimentalSerializationOptions?.notation === "LGN") {
898
+ return null;
899
+ }
900
+ if (grouping.amount !== 1) {
901
+ return null;
902
+ }
903
+ const amounts = this.tuple(grouping);
904
+ if (!amounts) {
905
+ return null;
906
+ }
907
+ return `(${amounts.map((move) => move.amount).join(", ")})`;
908
+ }
909
+ tuple(grouping) {
910
+ if (grouping.amount !== 1) {
911
+ return null;
912
+ }
913
+ this.quantumU_SQ_ ||= new QuantumMove("U_SQ_");
914
+ this.quantumD_SQ_ ||= new QuantumMove("D_SQ_");
915
+ const quantumAlg = grouping.alg;
916
+ if (quantumAlg.experimentalNumChildAlgNodes() === 2) {
917
+ const [U, D] = quantumAlg.childAlgNodes();
918
+ if (U.as(Move)?.quantum.isIdentical(this.quantumU_SQ_) && D.as(Move)?.quantum.isIdentical(this.quantumD_SQ_)) {
919
+ return [U, D];
920
+ }
921
+ }
922
+ return null;
923
+ }
924
+ };
925
+ var square1TupleFormatterInstance = new Square1TupleFormatter();
926
+ var Grouping = class _Grouping extends AlgCommon {
927
+ #quantumWithAmount;
928
+ experimentalNISSPlaceholder;
929
+ // TODO: tie this to the alg
930
+ constructor(algSource, amount) {
931
+ super();
932
+ const alg = experimentalEnsureAlg(algSource);
933
+ this.#quantumWithAmount = new QuantumWithAmount(alg, amount);
934
+ }
935
+ isIdentical(other) {
936
+ const otherAsGrouping = other;
937
+ return other.is(_Grouping) && this.#quantumWithAmount.isIdentical(otherAsGrouping.#quantumWithAmount);
938
+ }
939
+ get alg() {
940
+ return this.#quantumWithAmount.quantum;
941
+ }
942
+ get amount() {
943
+ return this.#quantumWithAmount.amount;
944
+ }
945
+ modified(modifications) {
946
+ return new _Grouping(
947
+ modifications.alg ?? this.alg,
948
+ modifications.amount ?? this.amount
949
+ );
950
+ }
951
+ /** @deprecated */
952
+ get experimentalRepetitionSuffix() {
953
+ return this.#quantumWithAmount.suffix();
954
+ }
955
+ invert() {
956
+ const amounts = square1TupleFormatterInstance.tuple(this);
957
+ if (amounts) {
958
+ const [moveU, moveD] = amounts;
959
+ return new _Grouping(new Alg([moveU.invert(), moveD.invert()]));
960
+ }
961
+ return new _Grouping(
962
+ this.#quantumWithAmount.quantum,
963
+ -this.#quantumWithAmount.amount
964
+ );
965
+ }
966
+ *experimentalExpand(iterDir = 1 /* Forwards */, depth) {
967
+ depth ??= Infinity;
968
+ if (depth === 0) {
969
+ yield iterDir === 1 /* Forwards */ ? this : this.invert();
970
+ } else {
971
+ yield* this.#quantumWithAmount.experimentalExpand(iterDir, depth - 1);
972
+ }
973
+ }
974
+ static fromString() {
975
+ throw new Error("unimplemented");
976
+ }
977
+ #unrepeatedString(experimentalSerializationOptions) {
978
+ const insideString = this.#quantumWithAmount.quantum.toString(
979
+ experimentalSerializationOptions
980
+ );
981
+ const iter = this.alg.childAlgNodes();
982
+ const { value } = iter.next();
983
+ if (iter.next().done && (value?.is(Commutator) || value?.is(Conjugate))) {
984
+ return insideString;
985
+ }
986
+ return `(${insideString})`;
987
+ }
988
+ toString(experimentalSerializationOptions) {
989
+ return square1TupleFormatterInstance.format(
990
+ this,
991
+ experimentalSerializationOptions
992
+ ) ?? `${this.#unrepeatedString(experimentalSerializationOptions)}${this.#quantumWithAmount.suffix()}`;
993
+ }
994
+ experimentalAsSquare1Tuple() {
995
+ return square1TupleFormatterInstance.tuple(this);
996
+ }
997
+ // toJSON(): GroupingJSON {
998
+ // return {
999
+ // type: "grouping",
1000
+ // alg: this.#quanta.quantum.toJSON(),
1001
+ // };
1002
+ // }
1003
+ };
1004
+
1005
+ // src/cubing/alg/is.ts
1006
+ function experimentalIs(v, c) {
1007
+ return v instanceof c;
1008
+ }
1009
+ function experimentalIsAlgNode(v) {
1010
+ return experimentalIs(v, Grouping) || experimentalIs(v, LineComment) || experimentalIs(v, Commutator) || experimentalIs(v, Conjugate) || experimentalIs(v, Move) || experimentalIs(v, Newline) || experimentalIs(v, Pause);
1011
+ }
1012
+
1013
+ // src/cubing/alg/simplify/options.ts
1014
+ var DEFAULT_DIRECTIONAL = "any-direction";
1015
+ var AppendOptionsHelper = class {
1016
+ constructor(config = {}) {
1017
+ this.config = config;
1018
+ }
1019
+ config;
1020
+ cancelQuantum() {
1021
+ const { cancel } = this.config;
1022
+ if (cancel === true) {
1023
+ return DEFAULT_DIRECTIONAL;
1024
+ }
1025
+ if (cancel === false) {
1026
+ return "none";
1027
+ }
1028
+ return cancel?.directional ?? "none";
1029
+ }
1030
+ cancelAny() {
1031
+ return this.config.cancel && this.cancelQuantum() !== "none";
1032
+ }
1033
+ cancelPuzzleSpecificModWrap() {
1034
+ const { cancel } = this.config;
1035
+ if (cancel === true || cancel === false) {
1036
+ return "canonical-centered";
1037
+ }
1038
+ if (cancel?.puzzleSpecificModWrap) {
1039
+ return cancel?.puzzleSpecificModWrap;
1040
+ }
1041
+ return cancel?.directional === "same-direction" ? "preserve-sign" : "canonical-centered";
1042
+ }
1043
+ puzzleSpecificSimplifyOptions() {
1044
+ return this.config.puzzleLoader?.puzzleSpecificSimplifyOptions ?? this.config.puzzleSpecificSimplifyOptions;
1045
+ }
1046
+ };
1047
+
1048
+ // src/cubing/alg/simplify/append.ts
1049
+ function areSameDirection(direction, move2) {
1050
+ return direction * Math.sign(move2.amount) >= 0;
1051
+ }
1052
+ function offsetMod(x, positiveMod, offset = 0) {
1053
+ return ((x - offset) % positiveMod + positiveMod) % positiveMod + offset;
1054
+ }
1055
+ function experimentalAppendMove(alg, addedMove, options) {
1056
+ const optionsHelper = new AppendOptionsHelper(options);
1057
+ const outputPrefix = Array.from(alg.childAlgNodes());
1058
+ let outputSuffix = [addedMove];
1059
+ function output() {
1060
+ return new Alg([...outputPrefix, ...outputSuffix]);
1061
+ }
1062
+ function modMove(move) {
1063
+ if (optionsHelper.cancelPuzzleSpecificModWrap() === "none") {
1064
+ return move;
1065
+ }
1066
+ const quantumMoveOrder = optionsHelper.puzzleSpecificSimplifyOptions()?.quantumMoveOrder;
1067
+ if (!quantumMoveOrder) {
1068
+ return move;
1069
+ }
1070
+ const mod = quantumMoveOrder(addedMove.quantum);
1071
+ let offset;
1072
+ switch (optionsHelper.cancelPuzzleSpecificModWrap()) {
1073
+ case "gravity": {
1074
+ offset = -Math.floor((mod - (move.amount < 0 ? 0 : 1)) / 2);
1075
+ break;
1076
+ }
1077
+ case "canonical-centered": {
1078
+ offset = -Math.floor((mod - 1) / 2);
1079
+ break;
1080
+ }
1081
+ case "canonical-positive": {
1082
+ offset = 0;
1083
+ break;
1084
+ }
1085
+ case "preserve-sign": {
1086
+ offset = move.amount < 0 ? 1 - mod : 0;
1087
+ break;
1088
+ }
1089
+ default: {
1090
+ throw new Error("Unknown mod wrap");
1091
+ }
1092
+ }
1093
+ const offsetAmount = offsetMod(move.amount, mod, offset);
1094
+ return move.modified({ amount: offsetAmount });
1095
+ }
1096
+ if (optionsHelper.cancelAny()) {
1097
+ let canCancelMoveBasedOnQuantum;
1098
+ const axis = optionsHelper.puzzleSpecificSimplifyOptions()?.axis;
1099
+ if (axis) {
1100
+ canCancelMoveBasedOnQuantum = (move) => axis.areQuantumMovesSameAxis(addedMove.quantum, move.quantum);
1101
+ } else {
1102
+ const newMoveQuantumString = addedMove.quantum.toString();
1103
+ canCancelMoveBasedOnQuantum = (move) => move.quantum.toString() === newMoveQuantumString;
1104
+ }
1105
+ const sameDirectionOnly = optionsHelper.cancelQuantum() === "same-direction";
1106
+ const quantumDirections = /* @__PURE__ */ new Map();
1107
+ quantumDirections.set(
1108
+ addedMove.quantum.toString(),
1109
+ Math.sign(addedMove.amount)
1110
+ );
1111
+ let i;
1112
+ for (i = outputPrefix.length - 1; i >= 0; i--) {
1113
+ const move = outputPrefix[i].as(Move);
1114
+ if (!move) {
1115
+ break;
1116
+ }
1117
+ if (!canCancelMoveBasedOnQuantum(move)) {
1118
+ break;
1119
+ }
1120
+ const quantumKey = move.quantum.toString();
1121
+ if (sameDirectionOnly) {
1122
+ const existingQuantumDirectionOnAxis = quantumDirections.get(quantumKey);
1123
+ if (existingQuantumDirectionOnAxis && // Short-circuits, but that's actually okay here.
1124
+ !areSameDirection(existingQuantumDirectionOnAxis, move)) {
1125
+ break;
1126
+ }
1127
+ quantumDirections.set(quantumKey, Math.sign(move.amount));
1128
+ }
1129
+ }
1130
+ const suffix = [...outputPrefix.splice(i + 1), addedMove];
1131
+ if (axis) {
1132
+ outputSuffix = axis.simplifySameAxisMoves(
1133
+ suffix,
1134
+ optionsHelper.cancelPuzzleSpecificModWrap() !== "none"
1135
+ );
1136
+ } else {
1137
+ const amount = suffix.reduce(
1138
+ (sum, move) => sum + move.amount,
1139
+ 0
1140
+ );
1141
+ if (quantumDirections.size !== 1) {
1142
+ throw new Error(
1143
+ "Internal error: multiple quantums when one was expected"
1144
+ );
1145
+ }
1146
+ outputSuffix = [new Move(addedMove.quantum, amount)];
1147
+ }
1148
+ }
1149
+ outputSuffix = outputSuffix.map((m) => modMove(m)).filter((move) => move.amount !== 0);
1150
+ return output();
1151
+ }
1152
+ function experimentalAppendNode(alg, leaf, options) {
1153
+ const maybeMove = leaf.as(Move);
1154
+ if (maybeMove) {
1155
+ return experimentalAppendMove(alg, maybeMove, options);
1156
+ } else {
1157
+ return new Alg([...alg.childAlgNodes(), leaf]);
1158
+ }
1159
+ }
1160
+
1161
+ // src/cubing/alg/traversal.ts
1162
+ function dispatch(t, algNode, dataDown) {
1163
+ if (algNode.is(Grouping)) {
1164
+ return t.traverseGrouping(algNode, dataDown);
1165
+ }
1166
+ if (algNode.is(Move)) {
1167
+ return t.traverseMove(algNode, dataDown);
1168
+ }
1169
+ if (algNode.is(Commutator)) {
1170
+ return t.traverseCommutator(algNode, dataDown);
1171
+ }
1172
+ if (algNode.is(Conjugate)) {
1173
+ return t.traverseConjugate(algNode, dataDown);
1174
+ }
1175
+ if (algNode.is(Pause)) {
1176
+ return t.traversePause(algNode, dataDown);
1177
+ }
1178
+ if (algNode.is(Newline)) {
1179
+ return t.traverseNewline(algNode, dataDown);
1180
+ }
1181
+ if (algNode.is(LineComment)) {
1182
+ return t.traverseLineComment(algNode, dataDown);
1183
+ }
1184
+ throw new Error("unknown AlgNode");
1185
+ }
1186
+ function mustBeAlgNode(t) {
1187
+ if (t.is(Grouping) || t.is(Move) || t.is(Commutator) || t.is(Conjugate) || t.is(Pause) || t.is(Newline) || t.is(LineComment)) {
1188
+ return t;
1189
+ }
1190
+ throw new Error("internal error: expected AlgNode");
1191
+ }
1192
+ var TraversalDownUp = class {
1193
+ // Immediate subclasses should overwrite this.
1194
+ traverseAlgNode(algNode, dataDown) {
1195
+ return dispatch(this, algNode, dataDown);
1196
+ }
1197
+ traverseIntoAlgNode(algNode, dataDown) {
1198
+ return mustBeAlgNode(this.traverseAlgNode(algNode, dataDown));
1199
+ }
1200
+ };
1201
+ var TraversalUp = class extends TraversalDownUp {
1202
+ traverseAlgNode(algNode) {
1203
+ return dispatch(
1204
+ this,
1205
+ algNode,
1206
+ void 0
1207
+ );
1208
+ }
1209
+ traverseIntoAlgNode(algNode) {
1210
+ return mustBeAlgNode(this.traverseAlgNode(algNode));
1211
+ }
1212
+ };
1213
+ function functionFromTraversal(traversalConstructor, constructorArgs) {
1214
+ const instance = new traversalConstructor(
1215
+ ...constructorArgs ?? []
1216
+ );
1217
+ return instance.traverseAlg.bind(instance);
1218
+ }
1219
+
1220
+ // src/cubing/alg/simplify/simplify.ts
1221
+ var Simplify = class extends TraversalDownUp {
1222
+ #newPlaceholderAssociationsMap;
1223
+ #newPlaceholderAssociations() {
1224
+ return this.#newPlaceholderAssociationsMap ??= /* @__PURE__ */ new Map();
1225
+ }
1226
+ // TODO: avoid allocations?
1227
+ #descendOptions(options) {
1228
+ return {
1229
+ ...options,
1230
+ depth: options.depth ? options.depth - 1 : null
1231
+ };
1232
+ }
1233
+ // TODO: Handle
1234
+ *traverseAlg(alg, options) {
1235
+ if (options.depth === 0) {
1236
+ yield* alg.childAlgNodes();
1237
+ return;
1238
+ }
1239
+ let output = [];
1240
+ const newOptions = this.#descendOptions(options);
1241
+ for (const algNode of alg.childAlgNodes()) {
1242
+ for (const traversedNode of this.traverseAlgNode(algNode, newOptions)) {
1243
+ output = Array.from(
1244
+ experimentalAppendNode(
1245
+ new Alg(output),
1246
+ traversedNode,
1247
+ newOptions
1248
+ ).childAlgNodes()
1249
+ );
1250
+ }
1251
+ }
1252
+ for (const newAlgNode of output) {
1253
+ yield newAlgNode;
1254
+ }
1255
+ }
1256
+ *traverseGrouping(grouping, options) {
1257
+ if (options.depth === 0) {
1258
+ yield grouping;
1259
+ return;
1260
+ }
1261
+ if (grouping.amount === 0) {
1262
+ return;
1263
+ }
1264
+ const newGrouping = new Grouping(
1265
+ this.traverseAlg(grouping.alg, this.#descendOptions(options)),
1266
+ grouping.amount
1267
+ );
1268
+ if (newGrouping.alg.experimentalIsEmpty()) {
1269
+ return;
1270
+ }
1271
+ const newPlaceholder = this.#newPlaceholderAssociations().get(grouping);
1272
+ if (newPlaceholder) {
1273
+ newGrouping.experimentalNISSPlaceholder = newPlaceholder;
1274
+ newPlaceholder.experimentalNISSGrouping = newGrouping;
1275
+ }
1276
+ yield newGrouping;
1277
+ }
1278
+ *traverseMove(move, _options) {
1279
+ yield move;
1280
+ }
1281
+ #doChildrenCommute(A, B, options) {
1282
+ if (A.experimentalNumChildAlgNodes() === 1 && B.experimentalNumChildAlgNodes() === 1) {
1283
+ const aMove = Array.from(A.childAlgNodes())[0]?.as(Move);
1284
+ const bMove = Array.from(B.childAlgNodes())[0]?.as(Move);
1285
+ if (!(aMove && bMove)) {
1286
+ return false;
1287
+ }
1288
+ if (bMove.quantum.isIdentical(aMove.quantum)) {
1289
+ return true;
1290
+ }
1291
+ const appendOptionsHelper = new AppendOptionsHelper(options);
1292
+ if (appendOptionsHelper.puzzleSpecificSimplifyOptions()?.axis?.areQuantumMovesSameAxis(aMove.quantum, bMove.quantum)) {
1293
+ return true;
1294
+ }
1295
+ }
1296
+ return false;
1297
+ }
1298
+ *traverseCommutator(commutator, options) {
1299
+ if (options.depth === 0) {
1300
+ yield commutator;
1301
+ return;
1302
+ }
1303
+ const newOptions = this.#descendOptions(options);
1304
+ const newCommutator = new Commutator(
1305
+ this.traverseAlg(commutator.A, newOptions),
1306
+ this.traverseAlg(commutator.B, newOptions)
1307
+ );
1308
+ if (newCommutator.A.experimentalIsEmpty() || newCommutator.B.experimentalIsEmpty() || newCommutator.A.isIdentical(newCommutator.B) || newCommutator.A.isIdentical(newCommutator.B.invert()) || this.#doChildrenCommute(newCommutator.A, newCommutator.B, options)) {
1309
+ return;
1310
+ }
1311
+ yield newCommutator;
1312
+ }
1313
+ *traverseConjugate(conjugate, options) {
1314
+ if (options.depth === 0) {
1315
+ yield conjugate;
1316
+ return;
1317
+ }
1318
+ const newOptions = this.#descendOptions(options);
1319
+ const newConjugate = new Conjugate(
1320
+ this.traverseAlg(conjugate.A, newOptions),
1321
+ this.traverseAlg(conjugate.B, newOptions)
1322
+ );
1323
+ if (newConjugate.B.experimentalIsEmpty()) {
1324
+ return;
1325
+ }
1326
+ if (newConjugate.A.experimentalIsEmpty() || newConjugate.A.isIdentical(newConjugate.B) || newConjugate.A.isIdentical(newConjugate.B.invert()) || this.#doChildrenCommute(newConjugate.A, newConjugate.B, options)) {
1327
+ yield* conjugate.B.childAlgNodes();
1328
+ return;
1329
+ }
1330
+ yield newConjugate;
1331
+ }
1332
+ *traversePause(pause, _options) {
1333
+ if (pause.experimentalNISSGrouping) {
1334
+ const newPause = new Pause();
1335
+ this.#newPlaceholderAssociations().set(
1336
+ pause.experimentalNISSGrouping,
1337
+ newPause
1338
+ );
1339
+ yield newPause;
1340
+ } else {
1341
+ yield pause;
1342
+ }
1343
+ }
1344
+ *traverseNewline(newline, _options) {
1345
+ yield newline;
1346
+ }
1347
+ *traverseLineComment(comment, _options) {
1348
+ yield comment;
1349
+ }
1350
+ };
1351
+ var simplify = functionFromTraversal(Simplify);
1352
+
1353
+ // src/cubing/alg/Alg.ts
1354
+ function toIterable(input) {
1355
+ if (!input) {
1356
+ return [];
1357
+ }
1358
+ if (experimentalIs(input, Alg)) {
1359
+ return input.childAlgNodes();
1360
+ }
1361
+ if (typeof input === "string") {
1362
+ return parseAlg(input).childAlgNodes();
1363
+ }
1364
+ const iter = input;
1365
+ if (typeof iter[Symbol.iterator] === "function") {
1366
+ return iter;
1367
+ }
1368
+ throw new Error("Invalid AlgNode");
1369
+ }
1370
+ function experimentalEnsureAlg(alg) {
1371
+ if (experimentalIs(alg, Alg)) {
1372
+ return alg;
1373
+ }
1374
+ return new Alg(alg);
1375
+ }
1376
+ var Alg = class _Alg extends AlgCommon {
1377
+ // #debugString: string;
1378
+ #algNodes;
1379
+ // TODO: freeze?
1380
+ constructor(alg) {
1381
+ super();
1382
+ this.#algNodes = Array.from(toIterable(alg));
1383
+ for (const algNode of this.#algNodes) {
1384
+ if (!experimentalIsAlgNode(algNode)) {
1385
+ throw new Error("An alg can only contain alg nodes.");
1386
+ }
1387
+ }
1388
+ }
1389
+ /**
1390
+ * Checks whether this Alg is structurally identical to another Alg. This
1391
+ * essentially means that they are written identically apart from whitespace.
1392
+ *
1393
+ * const alg1 = new Alg("R U L'");
1394
+ * const alg2 = new Alg("L U' R'").invert();
1395
+ * // true
1396
+ * alg1.isIdentical(alg2);
1397
+ *
1398
+ * // false
1399
+ * new Alg("[R, U]").isIdentical(new Alg("R U R' U'"));
1400
+ * // true
1401
+ * new Alg("[R, U]").expand().isIdentical(new Alg("R U R' U'"));
1402
+ *
1403
+ * Note that .isIdentical() efficiently compares algorithms, but mainly exists
1404
+ * to help optimize code when the structure of an algorithm hasn't changed.
1405
+ * There are many ways to write the "same" alg on most puzzles, but is
1406
+ * *highly* recommended to avoid expanding two Alg instances to compare them,
1407
+ * since that can easily slow your program to a crawl if someone inputs an alg
1408
+ * containing a large repetition. In general, you should use `cubing/kpuzzle`
1409
+ * to compare if two algs have the same effect on a puzzle.
1410
+ *
1411
+ * Also note that parser annotations are not taken into account while comparing
1412
+ * algs:
1413
+ *
1414
+ * const alg = new Alg([new Move("R"), new Move("U2")]);
1415
+ * // true, even though one of the algs has parser annotations
1416
+ * alg.isIdentical(new Alg("R U2"))
1417
+ *
1418
+ */
1419
+ isIdentical(other) {
1420
+ const otherAsAlg = other;
1421
+ if (!other.is(_Alg)) {
1422
+ return false;
1423
+ }
1424
+ const l1 = Array.from(this.#algNodes);
1425
+ const l2 = Array.from(otherAsAlg.#algNodes);
1426
+ if (l1.length !== l2.length) {
1427
+ return false;
1428
+ }
1429
+ for (let i = 0; i < l1.length; i++) {
1430
+ if (!l1[i].isIdentical(l2[i])) {
1431
+ return false;
1432
+ }
1433
+ }
1434
+ return true;
1435
+ }
1436
+ /**
1437
+ * Returns the inverse of the given alg.
1438
+ *
1439
+ * Note that that this does not make any assumptions about what puzzle the alg
1440
+ * is for. For example, U2 is its own inverse on a cube, but U2' has the same
1441
+ * effect U3 (and not U2) on Megaminx:
1442
+ *
1443
+ * // Outputs: R U2' L'
1444
+ * new Alg("L U2 R'").invert().log();
1445
+ */
1446
+ invert() {
1447
+ return new _Alg(reverse(Array.from(this.#algNodes).map((u) => u.invert())));
1448
+ }
1449
+ /** @deprecated Use {@link Alg.expand} instead. */
1450
+ *experimentalExpand(iterDir = 1 /* Forwards */, depth) {
1451
+ depth ??= Infinity;
1452
+ for (const algNode of direct(this.#algNodes, iterDir)) {
1453
+ yield* algNode.experimentalExpand(iterDir, depth);
1454
+ }
1455
+ }
1456
+ /**
1457
+ * Expands all Grouping, Commutator, and Conjugate parts nested inside the
1458
+ * alg.
1459
+ *
1460
+ * // F R U R' U' F'
1461
+ * new Alg("[F: [R, U]]").expand().log();
1462
+ *
1463
+ * // F [R, U] F'
1464
+ * new Alg("[F: [R, U]]").expand(({ depth: 1 }).log();
1465
+ *
1466
+ * Avoid calling this on a user-provided alg unless the user explicitly asks
1467
+ * to see the expanded alg. Otherwise, it's easy to make your program freeze
1468
+ * when someone passes in an alg like: (R U)10000000
1469
+ *
1470
+ * Generally, if you want to perform an operation on an entire alg, you'll
1471
+ * want to use something based on the `Traversal` mechanism, like countMoves()
1472
+ * from `cubing/notation`.
1473
+ */
1474
+ expand(options) {
1475
+ return new _Alg(
1476
+ this.experimentalExpand(
1477
+ 1 /* Forwards */,
1478
+ options?.depth ?? Infinity
1479
+ )
1480
+ );
1481
+ }
1482
+ /** @deprecated */
1483
+ *experimentalLeafMoves() {
1484
+ for (const leaf of this.experimentalExpand()) {
1485
+ if (leaf.is(Move)) {
1486
+ yield leaf;
1487
+ }
1488
+ }
1489
+ }
1490
+ concat(input) {
1491
+ return new _Alg(
1492
+ Array.from(this.#algNodes).concat(Array.from(toIterable(input)))
1493
+ );
1494
+ }
1495
+ /** @deprecated */
1496
+ experimentalIsEmpty() {
1497
+ for (const _ of this.#algNodes) {
1498
+ return false;
1499
+ }
1500
+ return true;
1501
+ }
1502
+ static fromString(s) {
1503
+ return parseAlg(s);
1504
+ }
1505
+ /** @deprecated */
1506
+ units() {
1507
+ return this.childAlgNodes();
1508
+ }
1509
+ *childAlgNodes() {
1510
+ for (const algNode of this.#algNodes) {
1511
+ yield algNode;
1512
+ }
1513
+ }
1514
+ /** @deprecated */
1515
+ experimentalNumUnits() {
1516
+ return this.experimentalNumChildAlgNodes();
1517
+ }
1518
+ experimentalNumChildAlgNodes() {
1519
+ return Array.from(this.#algNodes).length;
1520
+ }
1521
+ /** @deprecated */
1522
+ get type() {
1523
+ warnOnce("deprecated: type");
1524
+ return "sequence";
1525
+ }
1526
+ /**
1527
+ * Converts the Alg to a string:
1528
+ *
1529
+ * const alg = new Alg([new Move("R"), new Move("U2"), new Move("L")])
1530
+ * // R U2 L
1531
+ * console.log(alg.toString())
1532
+ */
1533
+ toString(experimentalSerializationOptions) {
1534
+ let output = "";
1535
+ let previousVisibleAlgNode = null;
1536
+ for (const algNode of this.#algNodes) {
1537
+ if (previousVisibleAlgNode) {
1538
+ output += spaceBetween(previousVisibleAlgNode, algNode);
1539
+ }
1540
+ const nissGrouping = algNode.as(Pause)?.experimentalNISSGrouping;
1541
+ if (nissGrouping) {
1542
+ if (nissGrouping.amount !== -1) {
1543
+ throw new Error("Invalid NISS Grouping amount!");
1544
+ }
1545
+ output += `^(${nissGrouping.alg.toString(experimentalSerializationOptions)})`;
1546
+ } else if (algNode.as(Grouping)?.experimentalNISSPlaceholder) {
1547
+ } else {
1548
+ output += algNode.toString(experimentalSerializationOptions);
1549
+ }
1550
+ previousVisibleAlgNode = algNode;
1551
+ }
1552
+ return output;
1553
+ }
1554
+ /**
1555
+ * `experimentalSimplify` can perform several mostly-syntactic simplifications on an alg:
1556
+ *
1557
+ * // Logs: R' U3
1558
+ * import { Alg } from "@rednaxela101/cubing/alg";
1559
+ * new Alg("R R2' U U2").experimentalSimplify({ cancel: true }).log()
1560
+ *
1561
+ * You can pass in a `PuzzleLoader` (currently only for 3x3x3) for puzzle-specific simplifications:
1562
+ *
1563
+ * // Logs: R' U'
1564
+ * import { Alg } from "@rednaxela101/cubing/alg";
1565
+ * import { cube3x3x3 } from "@rednaxela101/cubing/puzzles";
1566
+ * new Alg("R R2' U U2").experimentalSimplify({ cancel: true, puzzleLoader: cube3x3x3 }).log()
1567
+ *
1568
+ * You can also cancel only moves that are in the same direction:
1569
+ *
1570
+ * // Logs: R R2' U'
1571
+ * import { Alg } from "@rednaxela101/cubing/alg";
1572
+ * import { cube3x3x3 } from "@rednaxela101/cubing/puzzles";
1573
+ * new Alg("R R2' U U2").experimentalSimplify({
1574
+ * cancel: { directional: "same-direction" },
1575
+ * puzzleLoader: cube3x3x3
1576
+ * }).log()
1577
+ *
1578
+ * Additionally, you can specify how moves are "wrapped":
1579
+ *
1580
+ * import { Alg } from "@rednaxela101/cubing/alg";
1581
+ * import { cube3x3x3 } from "@rednaxela101/cubing/puzzles";
1582
+ *
1583
+ * function example(puzzleSpecificModWrap) {
1584
+ * alg.experimentalSimplify({
1585
+ * cancel: { puzzleSpecificModWrap },
1586
+ * puzzleLoader: cube3x3x3
1587
+ * }).log()
1588
+ * }
1589
+ *
1590
+ * const alg = new Alg("R7' . R6' . R5' . R6")
1591
+ * example("none") // R7' . R6' . R5' . R6
1592
+ * example("gravity") // R . R2' . R' . R2
1593
+ * example("canonical-centered") // R . R2 . R' . R2
1594
+ * example("canonical-positive") // R . R2 . R3 . R2
1595
+ * example("preserve-sign") // R3' . R2' . R' . R2
1596
+ *
1597
+ * Same-axis and simultaneous move canonicalization is not implemented yet:
1598
+ *
1599
+ * // Logs: R L R
1600
+ * import { Alg } from "@rednaxela101/cubing/alg";
1601
+ * import { cube3x3x3 } from "@rednaxela101/cubing/puzzles";
1602
+ * new Alg("R L R").experimentalSimplify({ cancel: true, puzzleLoader: cube3x3x3 }).log()
1603
+ */
1604
+ experimentalSimplify(options) {
1605
+ return new _Alg(simplify(this, options ?? {}));
1606
+ }
1607
+ /** @deprecated See {@link experimentalSimplify} */
1608
+ simplify(options) {
1609
+ return this.experimentalSimplify(options);
1610
+ }
1611
+ };
1612
+ function spaceBetween(u1, u2) {
1613
+ if (u1.is(Newline) || u2.is(Newline)) {
1614
+ return "";
1615
+ }
1616
+ if (u2.as(Grouping)?.experimentalNISSPlaceholder) {
1617
+ return "";
1618
+ }
1619
+ if (u1.is(LineComment) && !u2.is(Newline)) {
1620
+ return "\n";
1621
+ }
1622
+ return " ";
1623
+ }
1624
+
1625
+ // src/cubing/alg/example.ts
1626
+ var Example = {
1627
+ Sune: new Alg([
1628
+ new Move("R", 1),
1629
+ new Move("U", 1),
1630
+ new Move("R", -1),
1631
+ new Move("U", 1),
1632
+ new Move("R", 1),
1633
+ new Move("U", -2),
1634
+ new Move("R", -1)
1635
+ ]),
1636
+ AntiSune: new Alg([
1637
+ new Move("R", 1),
1638
+ new Move("U", 2),
1639
+ new Move("R", -1),
1640
+ new Move("U", -1),
1641
+ new Move("R", 1),
1642
+ new Move("U", -1),
1643
+ new Move("R", -1)
1644
+ ]),
1645
+ SuneCommutator: new Alg([
1646
+ new Commutator(
1647
+ new Alg([new Move("R", 1), new Move("U", 1), new Move("R", -2)]),
1648
+ new Alg([
1649
+ new Conjugate(new Alg([new Move("R", 1)]), new Alg([new Move("U", 1)]))
1650
+ ])
1651
+ )
1652
+ ]),
1653
+ Niklas: new Alg([
1654
+ new Move("R", 1),
1655
+ new Move("U", -1),
1656
+ new Move("L", -1),
1657
+ new Move("U", 1),
1658
+ new Move("R", -1),
1659
+ new Move("U", -1),
1660
+ new Move("L", 1),
1661
+ new Move("U", 1)
1662
+ ]),
1663
+ EPerm: new Alg([
1664
+ new Move("x", -1),
1665
+ new Commutator(
1666
+ new Alg([
1667
+ new Conjugate(
1668
+ new Alg([new Move("R", 1)]),
1669
+ new Alg([new Move("U", -1)])
1670
+ )
1671
+ ]),
1672
+ new Alg([new Move("D", 1)])
1673
+ ),
1674
+ new Commutator(
1675
+ new Alg([
1676
+ new Conjugate(new Alg([new Move("R", 1)]), new Alg([new Move("U", 1)]))
1677
+ ]),
1678
+ new Alg([new Move("D", 1)])
1679
+ ),
1680
+ new Move("x", 1)
1681
+ ]),
1682
+ FURURFCompact: new Alg([
1683
+ new Conjugate(
1684
+ new Alg([new Move("F", 1)]),
1685
+ new Alg([
1686
+ new Commutator(
1687
+ new Alg([new Move("U", 1)]),
1688
+ new Alg([new Move("R", 1)])
1689
+ )
1690
+ ])
1691
+ )
1692
+ ]),
1693
+ APermCompact: new Alg([
1694
+ new Conjugate(
1695
+ new Alg([new Move("R", 2)]),
1696
+ new Alg([
1697
+ new Commutator(
1698
+ new Alg([new Move("F", 2)]),
1699
+ new Alg([new Move("R", -1), new Move("B", -1), new Move("R", 1)])
1700
+ )
1701
+ ])
1702
+ )
1703
+ ]),
1704
+ FURURFMoves: new Alg([
1705
+ new Move("F", 1),
1706
+ new Move("U", 1),
1707
+ new Move("R", 1),
1708
+ new Move("U", -1),
1709
+ new Move("R", -1),
1710
+ new Move("F", -1)
1711
+ ]),
1712
+ TPerm: new Alg([
1713
+ new Move("R", 1),
1714
+ new Move("U", 1),
1715
+ new Move("R", -1),
1716
+ new Move("U", -1),
1717
+ new Move("R", -1),
1718
+ new Move("F", 1),
1719
+ new Move("R", 2),
1720
+ new Move("U", -1),
1721
+ new Move("R", -1),
1722
+ new Move("U", -1),
1723
+ new Move("R", 1),
1724
+ new Move("U", 1),
1725
+ new Move("R", -1),
1726
+ new Move("F", -1)
1727
+ ]),
1728
+ HeadlightSwaps: new Alg([
1729
+ new Conjugate(
1730
+ new Alg([new Move("F", 1)]),
1731
+ new Alg([
1732
+ new Grouping(
1733
+ new Alg([
1734
+ new Commutator(
1735
+ new Alg([new Move("R", 1)]),
1736
+ new Alg([new Move("U", 1)])
1737
+ )
1738
+ ]),
1739
+ 3
1740
+ )
1741
+ ])
1742
+ )
1743
+ ]),
1744
+ TriplePause: new Alg([new Pause(), new Pause(), new Pause()])
1745
+ // AllAlgParts: [
1746
+ // new Alg([new Move("R", 1), new Move("U", -1)]),
1747
+ // new Grouping(new Alg([new Move("F", 1)]), 2),
1748
+ // // new Rotation("y", -1),
1749
+ // new Move("R", 2),
1750
+ // new Commutator(new Alg([new Move("R", 2)]), new Alg([new Move("U", 2)]), 2),
1751
+ // new Conjugate(new Alg([new Move("L", 2)]), new Alg([new Move("D", -1)]), 2),
1752
+ // new Pause(),
1753
+ // new Newline(),
1754
+ // new LineComment("line comment"),
1755
+ // ],
1756
+ };
1757
+
1758
+ // src/cubing/alg/keyboard.ts
1759
+ function keyToMove(keyMapping, e) {
1760
+ if (e.altKey || e.ctrlKey) {
1761
+ return null;
1762
+ }
1763
+ const layoutIndepdendentCode = e.code;
1764
+ return keyMapping?.[layoutIndepdendentCode] ?? null;
1765
+ }
1766
+
1767
+ // src/cubing/alg/url.ts
1768
+ function serializeURLParam(a) {
1769
+ let escaped = a.toString();
1770
+ escaped = escaped.replace(/_/g, "&#95;").replace(/ /g, "_");
1771
+ escaped = escaped.replace(/\+/g, "&#2b;");
1772
+ escaped = escaped.replace(/-/g, "&#45;").replace(/'/g, "-");
1773
+ return escaped;
1774
+ }
1775
+ function experimentalAlgCubingNetLink(options) {
1776
+ const url = new URL("https://alg.cubing.net");
1777
+ if (!options.alg) {
1778
+ throw new Error("An alg parameter is required.");
1779
+ }
1780
+ url.searchParams.set("alg", serializeURLParam(options.alg));
1781
+ if (options.setup) {
1782
+ url.searchParams.set("setup", serializeURLParam(options.setup));
1783
+ }
1784
+ if (options.title) {
1785
+ url.searchParams.set("title", options.title);
1786
+ }
1787
+ if (options.puzzle) {
1788
+ if (![
1789
+ "1x1x1",
1790
+ "2x2x2",
1791
+ "3x3x3",
1792
+ "4x4x4",
1793
+ "5x5x5",
1794
+ "6x6x6",
1795
+ "7x7x7",
1796
+ "8x8x8",
1797
+ "9x9x9",
1798
+ "10x10x10",
1799
+ "11x11x11",
1800
+ "12x12x12",
1801
+ "13x13x13",
1802
+ "14x14x14",
1803
+ "16x16x16",
1804
+ "17x17x17"
1805
+ ].includes(options.puzzle)) {
1806
+ throw new Error(`Invalid puzzle parameter: ${options.puzzle}`);
1807
+ }
1808
+ url.searchParams.set("puzzle", options.puzzle);
1809
+ }
1810
+ if (options.stage) {
1811
+ if (![
1812
+ "full",
1813
+ "cross",
1814
+ "F2L",
1815
+ "LL",
1816
+ "OLL",
1817
+ "PLL",
1818
+ "CLS",
1819
+ "ELS",
1820
+ "L6E",
1821
+ "CMLL",
1822
+ "WV",
1823
+ "ZBLL",
1824
+ "void"
1825
+ ].includes(options.stage)) {
1826
+ throw new Error(`Invalid stage parameter: ${options.stage}`);
1827
+ }
1828
+ url.searchParams.set("stage", options.stage);
1829
+ }
1830
+ if (options.view) {
1831
+ if (!["editor", "playback", "fullscreen"].includes(options.view)) {
1832
+ throw new Error(`Invalid view parameter: ${options.view}`);
1833
+ }
1834
+ url.searchParams.set("view", options.view);
1835
+ }
1836
+ if (options.type) {
1837
+ if (![
1838
+ "moves",
1839
+ "reconstruction",
1840
+ "alg",
1841
+ "reconstruction-end-with-setup"
1842
+ ].includes(options.type)) {
1843
+ throw new Error(`Invalid type parameter: ${options.type}`);
1844
+ }
1845
+ url.searchParams.set("type", options.type);
1846
+ }
1847
+ return url.toString();
1848
+ }
1849
+
1850
+ export {
1851
+ direct,
1852
+ directedGenerator,
1853
+ Commutator,
1854
+ Conjugate,
1855
+ AlgBuilder,
1856
+ LineComment,
1857
+ Newline,
1858
+ Pause,
1859
+ setAlgDebug,
1860
+ startCharIndexKey,
1861
+ endCharIndexKey,
1862
+ QuantumMove,
1863
+ Move,
1864
+ Grouping,
1865
+ experimentalIs,
1866
+ offsetMod,
1867
+ experimentalAppendMove,
1868
+ TraversalDownUp,
1869
+ TraversalUp,
1870
+ functionFromTraversal,
1871
+ Alg,
1872
+ Example,
1873
+ keyToMove,
1874
+ experimentalAlgCubingNetLink
1875
+ };
1876
+ //# sourceMappingURL=chunk-XPDJUSZ7.js.map