@cubingcenter/scrambler 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/puzzles/clock/scrambler.js +2 -2
- package/dist/puzzles/index.d.ts +1 -0
- package/dist/puzzles/index.d.ts.map +1 -1
- package/dist/puzzles/index.js +3 -0
- package/dist/puzzles/megaminx/scrambler.js +2 -2
- package/dist/puzzles/pyraminx/scrambler.js +2 -2
- package/dist/puzzles/skewb/facelets.d.ts +6 -0
- package/dist/puzzles/skewb/facelets.d.ts.map +1 -0
- package/dist/puzzles/skewb/facelets.js +71 -0
- package/dist/puzzles/skewb/index.d.ts +10 -0
- package/dist/puzzles/skewb/index.d.ts.map +1 -0
- package/dist/puzzles/skewb/index.js +8 -0
- package/dist/puzzles/skewb/moves.d.ts +19 -0
- package/dist/puzzles/skewb/moves.d.ts.map +1 -0
- package/dist/puzzles/skewb/moves.js +84 -0
- package/dist/puzzles/skewb/random-state.d.ts +3 -0
- package/dist/puzzles/skewb/random-state.d.ts.map +1 -0
- package/dist/puzzles/skewb/random-state.js +27 -0
- package/dist/puzzles/skewb/scrambler.d.ts +6 -0
- package/dist/puzzles/skewb/scrambler.d.ts.map +1 -0
- package/dist/puzzles/skewb/scrambler.js +52 -0
- package/dist/puzzles/skewb/solver.d.ts +11 -0
- package/dist/puzzles/skewb/solver.d.ts.map +1 -0
- package/dist/puzzles/skewb/solver.js +149 -0
- package/dist/puzzles/skewb/state.d.ts +6 -0
- package/dist/puzzles/skewb/state.d.ts.map +1 -0
- package/dist/puzzles/skewb/state.js +31 -0
- package/dist/puzzles/skewb/types.d.ts +25 -0
- package/dist/puzzles/skewb/types.d.ts.map +1 -0
- package/dist/puzzles/skewb/types.js +13 -0
- package/dist/puzzles/skewb/validation.d.ts +6 -0
- package/dist/puzzles/skewb/validation.d.ts.map +1 -0
- package/dist/puzzles/skewb/validation.js +69 -0
- package/dist-cjs/puzzles/clock/scrambler.js +2 -2
- package/dist-cjs/puzzles/index.js +4 -1
- package/dist-cjs/puzzles/megaminx/scrambler.js +2 -2
- package/dist-cjs/puzzles/pyraminx/scrambler.js +2 -2
- package/dist-cjs/puzzles/skewb/facelets.js +77 -0
- package/dist-cjs/puzzles/skewb/index.js +38 -0
- package/dist-cjs/puzzles/skewb/moves.js +95 -0
- package/dist-cjs/puzzles/skewb/random-state.js +30 -0
- package/dist-cjs/puzzles/skewb/scrambler.js +56 -0
- package/dist-cjs/puzzles/skewb/solver.js +160 -0
- package/dist-cjs/puzzles/skewb/state.js +37 -0
- package/dist-cjs/puzzles/skewb/types.js +16 -0
- package/dist-cjs/puzzles/skewb/validation.js +75 -0
- package/package.json +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSolvedSkewbState = createSolvedSkewbState;
|
|
4
|
+
exports.cloneSkewbState = cloneSkewbState;
|
|
5
|
+
exports.skewbStatesEqual = skewbStatesEqual;
|
|
6
|
+
exports.isSolvedSkewbState = isSolvedSkewbState;
|
|
7
|
+
function createSolvedSkewbState() {
|
|
8
|
+
return {
|
|
9
|
+
corners: {
|
|
10
|
+
permutation: [0, 1, 2, 3, 4, 5, 6, 7],
|
|
11
|
+
orientation: [0, 0, 0, 0, 0, 0, 0, 0],
|
|
12
|
+
},
|
|
13
|
+
centers: [0, 1, 2, 3, 4, 5],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function cloneSkewbState(state) {
|
|
17
|
+
return {
|
|
18
|
+
corners: {
|
|
19
|
+
permutation: [...state.corners.permutation],
|
|
20
|
+
orientation: [...state.corners.orientation],
|
|
21
|
+
},
|
|
22
|
+
centers: [...state.centers],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function skewbStatesEqual(left, right) {
|
|
26
|
+
return (arraysEqual(left.corners.permutation, right.corners.permutation) &&
|
|
27
|
+
arraysEqual(left.corners.orientation, right.corners.orientation) &&
|
|
28
|
+
arraysEqual(left.centers, right.centers));
|
|
29
|
+
}
|
|
30
|
+
function isSolvedSkewbState(state) {
|
|
31
|
+
return (state.corners.permutation.every((value, index) => value === index) &&
|
|
32
|
+
state.corners.orientation.every((value) => value === 0) &&
|
|
33
|
+
state.centers.every((value, index) => value === index));
|
|
34
|
+
}
|
|
35
|
+
function arraysEqual(left, right) {
|
|
36
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
37
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SKEWB_FACES = exports.SKEWB_MOVES = exports.CENTER_COUNT = exports.CORNER_COUNT = void 0;
|
|
4
|
+
exports.CORNER_COUNT = 8;
|
|
5
|
+
exports.CENTER_COUNT = 6;
|
|
6
|
+
exports.SKEWB_MOVES = [
|
|
7
|
+
"R",
|
|
8
|
+
"R'",
|
|
9
|
+
"U",
|
|
10
|
+
"U'",
|
|
11
|
+
"L",
|
|
12
|
+
"L'",
|
|
13
|
+
"B",
|
|
14
|
+
"B'",
|
|
15
|
+
];
|
|
16
|
+
exports.SKEWB_FACES = ["U", "R", "F", "D", "L", "B"];
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateSkewbState = validateSkewbState;
|
|
4
|
+
exports.isOneMoveFromSolvedSkewbState = isOneMoveFromSolvedSkewbState;
|
|
5
|
+
exports.isAllowedRandomSkewbState = isAllowedRandomSkewbState;
|
|
6
|
+
exports.permutationParity = permutationParity;
|
|
7
|
+
const types_js_1 = require("./types.js");
|
|
8
|
+
const moves_js_1 = require("./moves.js");
|
|
9
|
+
const state_js_1 = require("./state.js");
|
|
10
|
+
function validateSkewbState(state) {
|
|
11
|
+
const errors = [];
|
|
12
|
+
// corners permutation
|
|
13
|
+
errors.push(...validatePermutation("corner", state.corners.permutation, types_js_1.CORNER_COUNT));
|
|
14
|
+
// corners orientation
|
|
15
|
+
errors.push(...validateOrientations("corner", state.corners.orientation, types_js_1.CORNER_COUNT, 3));
|
|
16
|
+
// centers
|
|
17
|
+
errors.push(...validatePermutation("center", state.centers, types_js_1.CENTER_COUNT));
|
|
18
|
+
// parity checks - both perms must be even (as observed in BFS)
|
|
19
|
+
if (errors.length === 0) {
|
|
20
|
+
if (permutationParity(state.corners.permutation) !== 0) {
|
|
21
|
+
errors.push("Corner permutation parity must be even.");
|
|
22
|
+
}
|
|
23
|
+
if (permutationParity(state.centers) !== 0) {
|
|
24
|
+
errors.push("Center permutation parity must be even.");
|
|
25
|
+
}
|
|
26
|
+
// Check fixed corner invariant: corner 0 must be at position 0 with orientation 0 for WCA fixed model
|
|
27
|
+
// But we allow all states for validation; this is enforced by solver's reachable set, not validation.
|
|
28
|
+
// So we don't enforce fixed corner here; any even parity state is considered valid.
|
|
29
|
+
}
|
|
30
|
+
return { valid: errors.length === 0, errors };
|
|
31
|
+
}
|
|
32
|
+
function isOneMoveFromSolvedSkewbState(state) {
|
|
33
|
+
const solved = (0, state_js_1.createSolvedSkewbState)();
|
|
34
|
+
return types_js_1.SKEWB_MOVES.some((move) => (0, state_js_1.skewbStatesEqual)((0, moves_js_1.applySkewbMove)(solved, move), state));
|
|
35
|
+
}
|
|
36
|
+
function isAllowedRandomSkewbState(state) {
|
|
37
|
+
return validateSkewbState(state).valid && !(0, state_js_1.isSolvedSkewbState)(state) && !isOneMoveFromSolvedSkewbState(state);
|
|
38
|
+
}
|
|
39
|
+
function permutationParity(permutation) {
|
|
40
|
+
let inversions = 0;
|
|
41
|
+
for (let left = 0; left < permutation.length; left++) {
|
|
42
|
+
for (let right = left + 1; right < permutation.length; right++) {
|
|
43
|
+
if (permutation[left] > permutation[right])
|
|
44
|
+
inversions++;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return (inversions % 2);
|
|
48
|
+
}
|
|
49
|
+
function validatePermutation(label, permutation, length) {
|
|
50
|
+
const errors = [];
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
if (permutation.length !== length)
|
|
53
|
+
errors.push(`${label} permutation must contain ${length} values.`);
|
|
54
|
+
for (const value of permutation) {
|
|
55
|
+
if (!Number.isInteger(value) || value < 0 || value >= length) {
|
|
56
|
+
errors.push(`${label} permutation contains out-of-range value: ${value}.`);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (seen.has(value))
|
|
60
|
+
errors.push(`${label} permutation contains duplicate value: ${value}.`);
|
|
61
|
+
seen.add(value);
|
|
62
|
+
}
|
|
63
|
+
return errors;
|
|
64
|
+
}
|
|
65
|
+
function validateOrientations(label, orientations, length, modulo) {
|
|
66
|
+
const errors = [];
|
|
67
|
+
if (orientations.length !== length)
|
|
68
|
+
errors.push(`${label} orientation must contain ${length} values.`);
|
|
69
|
+
for (const value of orientations) {
|
|
70
|
+
if (!Number.isInteger(value) || value < 0 || value >= modulo) {
|
|
71
|
+
errors.push(`${label} orientation contains out-of-range value: ${value}.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return errors;
|
|
75
|
+
}
|