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,85 @@
1
+ import { axisForRestriction, splitAlgorithm } from "../solvers/min2phase/util.mjs";
2
+ import { SearchWCA } from "../solvers/min2phase/search-wca.mjs";
3
+ import { randomCube } from "../solvers/min2phase/tools.mjs";
4
+ //#region .build/vendor/scramble-core/src/generators/three-by-three.ts
5
+ const THREE_BY_THREE_MAX_SCRAMBLE_LENGTH = 21;
6
+ const THREE_BY_THREE_PROBE_MAX = 1e5;
7
+ const THREE_BY_THREE_PROBE_MIN = 0;
8
+ const THREE_BY_THREE_MAX_ATTEMPTS = 20;
9
+ const FMC_PADDING = "R' U' F";
10
+ const ORIENTATION_SEQUENCES = [
11
+ [],
12
+ ["Uw"],
13
+ ["Uw2"],
14
+ ["Uw'"],
15
+ ["Rw"],
16
+ ["Rw", "Uw"],
17
+ ["Rw", "Uw2"],
18
+ ["Rw", "Uw'"],
19
+ ["Rw2"],
20
+ ["Rw2", "Uw"],
21
+ ["Rw2", "Uw2"],
22
+ ["Rw2", "Uw'"],
23
+ ["Rw'"],
24
+ ["Rw'", "Uw"],
25
+ ["Rw'", "Uw2"],
26
+ ["Rw'", "Uw'"],
27
+ ["Fw"],
28
+ ["Fw", "Uw"],
29
+ ["Fw", "Uw2"],
30
+ ["Fw", "Uw'"],
31
+ ["Fw'"],
32
+ ["Fw'", "Uw"],
33
+ ["Fw'", "Uw2"],
34
+ ["Fw'", "Uw'"]
35
+ ];
36
+ const generateThreeByThreeScramble = ({ random }) => generateInverseSolution({ random });
37
+ const generateThreeByThreeNoInspectionScramble = ({ random }) => {
38
+ const orientation = chooseOrientation(random);
39
+ return [...splitAlgorithm(generateInverseSolution({
40
+ random,
41
+ lastAxisRestriction: orientation[0]?.[0] ?? null
42
+ })), ...orientation].join(" ");
43
+ };
44
+ const generateThreeByThreeFewestMovesScramble = ({ random }) => {
45
+ return `${FMC_PADDING} ${generateInverseSolution({
46
+ random,
47
+ firstAxisRestriction: "F",
48
+ lastAxisRestriction: "R"
49
+ })} ${FMC_PADDING}`;
50
+ };
51
+ const generateMultiBlindScramble = ({ random, cubeCount }) => {
52
+ validateCubeCount(cubeCount);
53
+ return Array.from({ length: cubeCount }, () => generateThreeByThreeNoInspectionScramble({ random })).join("\n");
54
+ };
55
+ const generateInverseSolution = ({ random, firstAxisRestriction, lastAxisRestriction }) => {
56
+ const search = new SearchWCA();
57
+ for (let attempt = 0; attempt < THREE_BY_THREE_MAX_ATTEMPTS; attempt += 1) {
58
+ const solution = search.solution(randomCube(random), THREE_BY_THREE_MAX_SCRAMBLE_LENGTH, THREE_BY_THREE_PROBE_MAX, THREE_BY_THREE_PROBE_MIN, 2, firstAxisRestriction, lastAxisRestriction).trim();
59
+ if (!solution.startsWith("Error")) {
60
+ if (satisfiesAxisRestrictions(solution, firstAxisRestriction, lastAxisRestriction)) return solution;
61
+ continue;
62
+ }
63
+ if (solution !== "Error 7" && solution !== "Error 8") throw new Error(`@cubegin/scramble-core: min2phase returned ${solution}`);
64
+ }
65
+ throw new Error("@cubegin/scramble-core: min2phase could not find a 3x3 scramble within retry limit");
66
+ };
67
+ const satisfiesAxisRestrictions = (scramble, firstAxisRestriction, lastAxisRestriction) => {
68
+ const moves = splitAlgorithm(scramble);
69
+ return !violatesAxisRestriction(moves[0], firstAxisRestriction) && !violatesAxisRestriction(moves.at(-1), lastAxisRestriction);
70
+ };
71
+ const violatesAxisRestriction = (move, restriction) => {
72
+ if (move === void 0 || restriction === null || restriction === void 0) return false;
73
+ return axisForRestriction(move[0]) === axisForRestriction(restriction);
74
+ };
75
+ const chooseOrientation = (random) => {
76
+ const index = random.nextInt(ORIENTATION_SEQUENCES.length);
77
+ const orientation = ORIENTATION_SEQUENCES[index];
78
+ if (orientation === void 0) throw new RangeError(`@cubegin/scramble-core: random source returned ${index} for max ${ORIENTATION_SEQUENCES.length}`);
79
+ return orientation;
80
+ };
81
+ const validateCubeCount = (cubeCount) => {
82
+ if (!Number.isSafeInteger(cubeCount) || cubeCount <= 0) throw new Error("@cubegin/scramble-core: multi-blind cubeCount must be a positive safe integer");
83
+ };
84
+ //#endregion
85
+ export { generateMultiBlindScramble, generateThreeByThreeFewestMovesScramble, generateThreeByThreeNoInspectionScramble, generateThreeByThreeScramble };
@@ -0,0 +1,11 @@
1
+ import { RandomSource } from "../random-source.mjs";
2
+
3
+ //#region .build/vendor/scramble-core/src/generators/two-by-two.d.ts
4
+ interface TwoByTwoScrambleOptions {
5
+ random: RandomSource;
6
+ }
7
+ declare const generateTwoByTwoScramble: ({
8
+ random
9
+ }: TwoByTwoScrambleOptions) => string;
10
+ //#endregion
11
+ export { TwoByTwoScrambleOptions, generateTwoByTwoScramble };
@@ -0,0 +1,17 @@
1
+ import { TwoByTwoSolver } from "../solvers/two-by-two-solver.mjs";
2
+ //#region .build/vendor/scramble-core/src/generators/two-by-two.ts
3
+ const ERROR_PREFIX = "@cubegin/scramble-core";
4
+ const SCRAMBLE_LENGTH = 11;
5
+ const WCA_MIN_SCRAMBLE_DISTANCE = 4;
6
+ const MAX_WCA_ATTEMPTS = 100;
7
+ const generateTwoByTwoScramble = ({ random }) => {
8
+ const solver = new TwoByTwoSolver();
9
+ for (let attempt = 0; attempt < MAX_WCA_ATTEMPTS; attempt += 1) {
10
+ const state = solver.randomState(random);
11
+ if (solver.solveIn(state, WCA_MIN_SCRAMBLE_DISTANCE - 1) !== null) continue;
12
+ return solver.generateExactly(state, SCRAMBLE_LENGTH);
13
+ }
14
+ throw new Error(`${ERROR_PREFIX}: could not generate a 2x2 WCA scramble after ${MAX_WCA_ATTEMPTS} attempts`);
15
+ };
16
+ //#endregion
17
+ export { generateTwoByTwoScramble };
@@ -0,0 +1,7 @@
1
+ //#region .build/vendor/scramble-core/src/random-source.d.ts
2
+ interface RandomSource {
3
+ nextInt(maxExclusive: number): number;
4
+ }
5
+ declare const createMathRandomSource: () => RandomSource;
6
+ //#endregion
7
+ export { RandomSource, createMathRandomSource };
@@ -0,0 +1,8 @@
1
+ //#region .build/vendor/scramble-core/src/random-source.ts
2
+ const ERROR_PREFIX = "@cubegin/scramble-core";
3
+ const createMathRandomSource = () => ({ nextInt(maxExclusive) {
4
+ if (!Number.isSafeInteger(maxExclusive) || maxExclusive <= 0) throw new Error(`${ERROR_PREFIX}: random maxExclusive must be a positive safe integer`);
5
+ return Math.floor(Math.random() * maxExclusive);
6
+ } });
7
+ //#endregion
8
+ export { createMathRandomSource };
@@ -0,0 +1,10 @@
1
+ import { initialize } from "./engine.mjs";
2
+ //#region .build/vendor/scramble-core/src/solvers/min2phase/coord-cube.ts
3
+ let isInitialized = false;
4
+ const initCoordCube = () => {
5
+ if (isInitialized) return;
6
+ initialize();
7
+ isInitialized = true;
8
+ };
9
+ //#endregion
10
+ export { initCoordCube };
@@ -0,0 +1,246 @@
1
+ import { SOLVED_FACE_CUBE } from "./util.mjs";
2
+ //#region .build/vendor/scramble-core/src/solvers/min2phase/cubie-cube.ts
3
+ const CORNER_FACELET = [
4
+ [
5
+ 8,
6
+ 9,
7
+ 20
8
+ ],
9
+ [
10
+ 6,
11
+ 18,
12
+ 38
13
+ ],
14
+ [
15
+ 0,
16
+ 36,
17
+ 47
18
+ ],
19
+ [
20
+ 2,
21
+ 45,
22
+ 11
23
+ ],
24
+ [
25
+ 29,
26
+ 26,
27
+ 15
28
+ ],
29
+ [
30
+ 27,
31
+ 44,
32
+ 24
33
+ ],
34
+ [
35
+ 33,
36
+ 53,
37
+ 42
38
+ ],
39
+ [
40
+ 35,
41
+ 17,
42
+ 51
43
+ ]
44
+ ];
45
+ const EDGE_FACELET = [
46
+ [5, 10],
47
+ [7, 19],
48
+ [3, 37],
49
+ [1, 46],
50
+ [32, 16],
51
+ [28, 25],
52
+ [30, 43],
53
+ [34, 52],
54
+ [23, 12],
55
+ [21, 41],
56
+ [50, 39],
57
+ [48, 14]
58
+ ];
59
+ const FACE_NAMES = [
60
+ "U",
61
+ "R",
62
+ "F",
63
+ "D",
64
+ "L",
65
+ "B"
66
+ ];
67
+ var CubieCube = class CubieCube {
68
+ cp;
69
+ co;
70
+ ep;
71
+ eo;
72
+ constructor(cp = [
73
+ 0,
74
+ 1,
75
+ 2,
76
+ 3,
77
+ 4,
78
+ 5,
79
+ 6,
80
+ 7
81
+ ], co = [
82
+ 0,
83
+ 0,
84
+ 0,
85
+ 0,
86
+ 0,
87
+ 0,
88
+ 0,
89
+ 0
90
+ ], ep = [
91
+ 0,
92
+ 1,
93
+ 2,
94
+ 3,
95
+ 4,
96
+ 5,
97
+ 6,
98
+ 7,
99
+ 8,
100
+ 9,
101
+ 10,
102
+ 11
103
+ ], eo = [
104
+ 0,
105
+ 0,
106
+ 0,
107
+ 0,
108
+ 0,
109
+ 0,
110
+ 0,
111
+ 0,
112
+ 0,
113
+ 0,
114
+ 0,
115
+ 0
116
+ ]) {
117
+ this.cp = [...cp];
118
+ this.co = [...co];
119
+ this.ep = [...ep];
120
+ this.eo = [...eo];
121
+ }
122
+ static solved() {
123
+ return new CubieCube();
124
+ }
125
+ static fromCoordinates(cperm, twist, eperm, flip) {
126
+ const cube = new CubieCube();
127
+ setNPerm(cube.cp, cperm, 8);
128
+ setTwist(cube.co, twist);
129
+ setNPerm(cube.ep, eperm, 12);
130
+ setFlip(cube.eo, flip);
131
+ return cube;
132
+ }
133
+ static fromFaceCube(facelets) {
134
+ if (facelets.length !== 54) return null;
135
+ const centerColors = [
136
+ facelets[4],
137
+ facelets[13],
138
+ facelets[22],
139
+ facelets[31],
140
+ facelets[40],
141
+ facelets[49]
142
+ ];
143
+ const colors = Array.from(facelets, (facelet) => centerColors.indexOf(facelet));
144
+ if (colors.some((color) => color < 0)) return null;
145
+ const cp = Array(8).fill(0);
146
+ const co = Array(8).fill(0);
147
+ const ep = Array(12).fill(0);
148
+ const eo = Array(12).fill(0);
149
+ for (let corner = 0; corner < 8; corner += 1) {
150
+ let orientation = 0;
151
+ while (orientation < 3 && colors[CORNER_FACELET[corner][orientation]] !== 0 && colors[CORNER_FACELET[corner][orientation]] !== 3) orientation += 1;
152
+ if (orientation === 3) return null;
153
+ const color1 = colors[CORNER_FACELET[corner][(orientation + 1) % 3]];
154
+ const color2 = colors[CORNER_FACELET[corner][(orientation + 2) % 3]];
155
+ const cubie = CORNER_FACELET.findIndex(([, facelet1, facelet2]) => color1 === Math.floor(facelet1 / 9) && color2 === Math.floor(facelet2 / 9));
156
+ if (cubie < 0) return null;
157
+ cp[corner] = cubie;
158
+ co[corner] = orientation % 3;
159
+ }
160
+ for (let edge = 0; edge < 12; edge += 1) {
161
+ const color0 = colors[EDGE_FACELET[edge][0]];
162
+ const color1 = colors[EDGE_FACELET[edge][1]];
163
+ const cubie = EDGE_FACELET.findIndex(([facelet0, facelet1]) => color0 === Math.floor(facelet0 / 9) && color1 === Math.floor(facelet1 / 9));
164
+ if (cubie >= 0) {
165
+ ep[edge] = cubie;
166
+ eo[edge] = 0;
167
+ continue;
168
+ }
169
+ const flippedCubie = EDGE_FACELET.findIndex(([facelet0, facelet1]) => color0 === Math.floor(facelet1 / 9) && color1 === Math.floor(facelet0 / 9));
170
+ if (flippedCubie < 0) return null;
171
+ ep[edge] = flippedCubie;
172
+ eo[edge] = 1;
173
+ }
174
+ return new CubieCube(cp, co, ep, eo);
175
+ }
176
+ toFaceCube() {
177
+ const facelets = Array.from(SOLVED_FACE_CUBE);
178
+ for (let corner = 0; corner < 8; corner += 1) {
179
+ const cubie = this.cp[corner];
180
+ const orientation = this.co[corner];
181
+ for (let index = 0; index < 3; index += 1) facelets[CORNER_FACELET[corner][(index + orientation) % 3]] = FACE_NAMES[Math.floor(CORNER_FACELET[cubie][index] / 9)] ?? "U";
182
+ }
183
+ for (let edge = 0; edge < 12; edge += 1) {
184
+ const cubie = this.ep[edge];
185
+ const orientation = this.eo[edge];
186
+ for (let index = 0; index < 2; index += 1) facelets[EDGE_FACELET[edge][(index + orientation) % 2]] = FACE_NAMES[Math.floor(EDGE_FACELET[cubie][index] / 9)] ?? "U";
187
+ }
188
+ return facelets.join("");
189
+ }
190
+ verify() {
191
+ if (this.ep.reduce((mask, edge) => mask | 1 << edge, 0) !== 4095) return -2;
192
+ if (this.eo.reduce((sum, orientation) => sum ^ orientation, 0) !== 0) return -3;
193
+ if (this.cp.reduce((mask, corner) => mask | 1 << corner, 0) !== 255) return -4;
194
+ if (this.co.reduce((sum, orientation) => sum + orientation, 0) % 3 !== 0) return -5;
195
+ if ((getNParity(getNPerm(this.ep, 12), 12) ^ getNParity(getNPerm(this.cp, 8), 8)) !== 0) return -6;
196
+ return 0;
197
+ }
198
+ };
199
+ const getNParity = (index, n) => {
200
+ let parity = 0;
201
+ let value = index;
202
+ for (let current = n - 2; current >= 0; current -= 1) {
203
+ parity ^= value % (n - current);
204
+ value = Math.floor(value / (n - current));
205
+ }
206
+ return parity & 1;
207
+ };
208
+ const getNPerm = (permutation, n) => {
209
+ let index = 0;
210
+ for (let i = 0; i < n; i += 1) {
211
+ index *= n - i;
212
+ for (let j = i + 1; j < n; j += 1) if ((permutation[j] ?? 0) < (permutation[i] ?? 0)) index += 1;
213
+ }
214
+ return index;
215
+ };
216
+ const setNPerm = (permutation, index, n) => {
217
+ for (let i = n - 1; i >= 0; i -= 1) {
218
+ permutation[i] = index % (n - i);
219
+ index = Math.floor(index / (n - i));
220
+ for (let j = i + 1; j < n; j += 1) if ((permutation[j] ?? 0) >= (permutation[i] ?? 0)) permutation[j] = (permutation[j] ?? 0) + 1;
221
+ }
222
+ };
223
+ const setTwist = (orientations, index) => {
224
+ let twist = 0;
225
+ let value = index;
226
+ for (let i = 6; i >= 0; i -= 1) {
227
+ const orientation = value % 3;
228
+ orientations[i] = orientation;
229
+ twist += orientation;
230
+ value = Math.floor(value / 3);
231
+ }
232
+ orientations[7] = (15 - twist) % 3;
233
+ };
234
+ const setFlip = (orientations, index) => {
235
+ let parity = 0;
236
+ let value = index;
237
+ for (let i = 10; i >= 0; i -= 1) {
238
+ const orientation = value & 1;
239
+ orientations[i] = orientation;
240
+ parity ^= orientation;
241
+ value >>= 1;
242
+ }
243
+ orientations[11] = parity;
244
+ };
245
+ //#endregion
246
+ export { CubieCube, getNParity, getNPerm };