@cubingcenter/scrambler 0.6.3 → 0.8.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/README.md +17 -4
- package/dist/core/api.d.ts.map +1 -1
- package/dist/core/api.js +10 -2
- package/dist/puzzles/cube2/solver/browser-loader.d.ts +4 -7
- package/dist/puzzles/cube2/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/cube2/solver/browser-loader.js +42 -14
- package/dist/puzzles/cube2/solver/generated-assets.d.ts.map +1 -1
- package/dist/puzzles/cube2/solver/generated-assets.js +8 -3
- package/dist/puzzles/cube2/solver/search.d.ts.map +1 -1
- package/dist/puzzles/cube2/solver/search.js +3 -3
- package/dist/puzzles/cube2/solver/tables.d.ts +6 -0
- package/dist/puzzles/cube2/solver/tables.d.ts.map +1 -1
- package/dist/puzzles/cube2/solver/tables.js +16 -2
- package/dist/puzzles/cube3/index.d.ts +1 -0
- package/dist/puzzles/cube3/index.d.ts.map +1 -1
- package/dist/puzzles/cube3/moves.d.ts.map +1 -1
- package/dist/puzzles/cube3/moves.js +104 -18
- package/dist/puzzles/cube3/scrambler.d.ts +16 -1
- package/dist/puzzles/cube3/scrambler.d.ts.map +1 -1
- package/dist/puzzles/cube3/scrambler.js +1 -1
- package/dist/puzzles/cube3/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/browser-loader.js +48 -22
- package/dist/puzzles/cube3/solver/generated-assets.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/generated-assets.js +9 -3
- package/dist/puzzles/cube3/solver/index.d.ts +5 -3
- package/dist/puzzles/cube3/solver/index.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/index.js +2 -1
- package/dist/puzzles/cube3/solver/node-loader.js +9 -2
- package/dist/puzzles/cube3/solver/phase1.d.ts +37 -0
- package/dist/puzzles/cube3/solver/phase1.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/phase1.js +156 -15
- package/dist/puzzles/cube3/solver/phase2.d.ts +75 -0
- package/dist/puzzles/cube3/solver/phase2.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/phase2.js +279 -68
- package/dist/puzzles/cube3/solver/search-utils.d.ts +1 -1
- package/dist/puzzles/cube3/solver/search-utils.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/symmetry.d.ts +24 -0
- package/dist/puzzles/cube3/solver/symmetry.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/symmetry.js +74 -0
- package/dist/puzzles/cube3/solver/tables.d.ts +6 -1
- package/dist/puzzles/cube3/solver/tables.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/tables.js +14 -12
- package/dist/puzzles/cube3/validation.d.ts.map +1 -1
- package/dist/puzzles/cube3/validation.js +15 -7
- package/dist/puzzles/cube4/browser-worker-pool.d.ts +82 -0
- package/dist/puzzles/cube4/browser-worker-pool.d.ts.map +1 -0
- package/dist/puzzles/cube4/browser-worker-pool.js +205 -0
- package/dist/puzzles/cube4/browser-worker.d.ts +2 -0
- package/dist/puzzles/cube4/browser-worker.d.ts.map +1 -0
- package/dist/puzzles/cube4/browser-worker.js +31 -0
- package/dist/puzzles/cube4/index.d.ts +10 -2
- package/dist/puzzles/cube4/index.d.ts.map +1 -1
- package/dist/puzzles/cube4/index.js +6 -2
- package/dist/puzzles/cube4/moves.d.ts +5 -0
- package/dist/puzzles/cube4/moves.d.ts.map +1 -1
- package/dist/puzzles/cube4/moves.js +212 -11
- package/dist/puzzles/cube4/reduction/browser-loader.d.ts +29 -1
- package/dist/puzzles/cube4/reduction/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/browser-loader.js +227 -32
- package/dist/puzzles/cube4/reduction/center2.d.ts +44 -3
- package/dist/puzzles/cube4/reduction/center2.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/center2.js +152 -10
- package/dist/puzzles/cube4/reduction/edge3.d.ts +4 -0
- package/dist/puzzles/cube4/reduction/edge3.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/edge3.js +23 -3
- package/dist/puzzles/cube4/reduction/finish3.d.ts +53 -0
- package/dist/puzzles/cube4/reduction/finish3.d.ts.map +1 -0
- package/dist/puzzles/cube4/reduction/finish3.js +393 -0
- package/dist/puzzles/cube4/reduction/generated/c3_pair_dist.bin +1 -0
- package/dist/puzzles/cube4/reduction/generated/center2-manifest.json +36 -0
- package/dist/puzzles/cube4/reduction/generated/center2-pruning-wide.bin +1 -0
- package/dist/puzzles/cube4/reduction/generated/hc-distances.bin +1 -0
- package/dist/puzzles/cube4/reduction/generated/hc-manifest.json +44 -0
- package/dist/puzzles/cube4/reduction/generated/hc-move.bin +0 -0
- package/dist/puzzles/cube4/reduction/hc-pdb.d.ts +52 -0
- package/dist/puzzles/cube4/reduction/hc-pdb.d.ts.map +1 -0
- package/dist/puzzles/cube4/reduction/hc-pdb.js +220 -0
- package/dist/puzzles/cube4/reduction/node-loader.d.ts +15 -1
- package/dist/puzzles/cube4/reduction/node-loader.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/node-loader.js +199 -25
- package/dist/puzzles/cube4/reduction/pair-transversal.d.ts +28 -0
- package/dist/puzzles/cube4/reduction/pair-transversal.d.ts.map +1 -0
- package/dist/puzzles/cube4/reduction/pair-transversal.js +107 -0
- package/dist/puzzles/cube4/reduction/pairing-coordinate.js +5 -5
- package/dist/puzzles/cube4/reduction/phase3-search.d.ts +116 -7
- package/dist/puzzles/cube4/reduction/phase3-search.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/phase3-search.js +458 -32
- package/dist/puzzles/cube4/reduction/rotation-fix.d.ts +28 -0
- package/dist/puzzles/cube4/reduction/rotation-fix.d.ts.map +1 -0
- package/dist/puzzles/cube4/reduction/rotation-fix.js +212 -0
- package/dist/puzzles/cube4/reduction/solve.d.ts +172 -2
- package/dist/puzzles/cube4/reduction/solve.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/solve.js +1201 -180
- package/dist/puzzles/cube4/scramble-cache.d.ts +93 -0
- package/dist/puzzles/cube4/scramble-cache.d.ts.map +1 -0
- package/dist/puzzles/cube4/scramble-cache.js +150 -0
- package/dist/puzzles/cube4/scrambler.d.ts +201 -6
- package/dist/puzzles/cube4/scrambler.d.ts.map +1 -1
- package/dist/puzzles/cube4/scrambler.js +414 -176
- package/dist/puzzles/cube4/state.d.ts.map +1 -1
- package/dist/puzzles/cube4/state.js +4 -1
- package/dist/puzzles/cube4/worker-pool.d.ts +139 -0
- package/dist/puzzles/cube4/worker-pool.d.ts.map +1 -0
- package/dist/puzzles/cube4/worker-pool.js +405 -0
- package/dist/puzzles/cube4/worker-protocol.d.ts +58 -0
- package/dist/puzzles/cube4/worker-protocol.d.ts.map +1 -0
- package/dist/puzzles/cube4/worker-protocol.js +58 -0
- package/dist/puzzles/cube4/worker.d.ts +26 -0
- package/dist/puzzles/cube4/worker.d.ts.map +1 -0
- package/dist/puzzles/cube4/worker.js +49 -0
- package/dist/puzzles/pyraminx/solver/browser-loader.d.ts +4 -8
- package/dist/puzzles/pyraminx/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/pyraminx/solver/browser-loader.js +44 -15
- package/dist/puzzles/pyraminx/solver/generated-assets.d.ts.map +1 -1
- package/dist/puzzles/pyraminx/solver/generated-assets.js +8 -3
- package/dist/puzzles/pyraminx/solver/search.d.ts.map +1 -1
- package/dist/puzzles/pyraminx/solver/search.js +3 -6
- package/dist/puzzles/pyraminx/solver/tables.d.ts +6 -0
- package/dist/puzzles/pyraminx/solver/tables.d.ts.map +1 -1
- package/dist/puzzles/pyraminx/solver/tables.js +17 -0
- package/dist/puzzles/shared/compressed-fetch.d.ts +37 -1
- package/dist/puzzles/shared/compressed-fetch.d.ts.map +1 -1
- package/dist/puzzles/shared/compressed-fetch.js +226 -31
- package/dist/puzzles/shared/load-once.d.ts +16 -0
- package/dist/puzzles/shared/load-once.d.ts.map +1 -0
- package/dist/puzzles/shared/load-once.js +11 -0
- package/dist/puzzles/skewb/solver/browser-loader.d.ts +4 -11
- package/dist/puzzles/skewb/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/skewb/solver/browser-loader.js +44 -16
- package/dist/puzzles/skewb/solver/generated-assets.d.ts.map +1 -1
- package/dist/puzzles/skewb/solver/generated-assets.js +8 -3
- package/dist/puzzles/skewb/solver/search.js +3 -3
- package/dist/puzzles/skewb/solver/tables.d.ts +6 -0
- package/dist/puzzles/skewb/solver/tables.d.ts.map +1 -1
- package/dist/puzzles/skewb/solver/tables.js +17 -0
- package/dist/puzzles/sq1/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/sq1/solver/browser-loader.js +58 -26
- package/dist-cjs/core/api.js +10 -2
- package/dist-cjs/puzzles/cube2/solver/browser-loader.js +42 -14
- package/dist-cjs/puzzles/cube2/solver/generated-assets.js +8 -3
- package/dist-cjs/puzzles/cube2/solver/search.js +2 -2
- package/dist-cjs/puzzles/cube2/solver/tables.js +17 -3
- package/dist-cjs/puzzles/cube3/moves.js +104 -18
- package/dist-cjs/puzzles/cube3/scrambler.js +1 -1
- package/dist-cjs/puzzles/cube3/solver/browser-loader.js +48 -22
- package/dist-cjs/puzzles/cube3/solver/generated-assets.js +9 -3
- package/dist-cjs/puzzles/cube3/solver/index.js +8 -1
- package/dist-cjs/puzzles/cube3/solver/node-loader.js +9 -2
- package/dist-cjs/puzzles/cube3/solver/phase1.js +157 -15
- package/dist-cjs/puzzles/cube3/solver/phase2.js +276 -65
- package/dist-cjs/puzzles/cube3/solver/symmetry.js +80 -0
- package/dist-cjs/puzzles/cube3/solver/tables.js +14 -12
- package/dist-cjs/puzzles/cube3/validation.js +15 -7
- package/dist-cjs/puzzles/cube4/browser-worker-pool.js +211 -0
- package/dist-cjs/puzzles/cube4/index.js +23 -1
- package/dist-cjs/puzzles/cube4/moves.js +213 -11
- package/dist-cjs/puzzles/cube4/reduction/browser-loader.js +227 -32
- package/dist-cjs/puzzles/cube4/reduction/center2.js +155 -10
- package/dist-cjs/puzzles/cube4/reduction/edge3.js +24 -3
- package/dist-cjs/puzzles/cube4/reduction/finish3.js +398 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/c3_pair_dist.bin +1 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/center2-manifest.json +36 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/center2-pruning-wide.bin +1 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/hc-distances.bin +1 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/hc-manifest.json +44 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/hc-move.bin +0 -0
- package/dist-cjs/puzzles/cube4/reduction/hc-pdb.js +232 -0
- package/dist-cjs/puzzles/cube4/reduction/node-loader.js +200 -25
- package/dist-cjs/puzzles/cube4/reduction/pair-transversal.js +112 -0
- package/dist-cjs/puzzles/cube4/reduction/pairing-coordinate.js +5 -5
- package/dist-cjs/puzzles/cube4/reduction/phase3-search.js +460 -33
- package/dist-cjs/puzzles/cube4/reduction/rotation-fix.js +216 -0
- package/dist-cjs/puzzles/cube4/reduction/solve.js +1203 -172
- package/dist-cjs/puzzles/cube4/scramble-cache.js +156 -0
- package/dist-cjs/puzzles/cube4/scrambler.js +416 -174
- package/dist-cjs/puzzles/cube4/state.js +4 -1
- package/dist-cjs/puzzles/cube4/worker-pool.js +447 -0
- package/dist-cjs/puzzles/cube4/worker-protocol.js +62 -0
- package/dist-cjs/puzzles/pyraminx/solver/browser-loader.js +44 -15
- package/dist-cjs/puzzles/pyraminx/solver/generated-assets.js +8 -3
- package/dist-cjs/puzzles/pyraminx/solver/search.js +2 -5
- package/dist-cjs/puzzles/pyraminx/solver/tables.js +18 -1
- package/dist-cjs/puzzles/shared/compressed-fetch.js +229 -31
- package/dist-cjs/puzzles/shared/load-once.js +14 -0
- package/dist-cjs/puzzles/skewb/solver/browser-loader.js +44 -16
- package/dist-cjs/puzzles/skewb/solver/generated-assets.js +8 -3
- package/dist-cjs/puzzles/skewb/solver/search.js +2 -2
- package/dist-cjs/puzzles/skewb/solver/tables.js +18 -1
- package/dist-cjs/puzzles/sq1/solver/browser-loader.js +58 -26
- package/docs/development.md +19 -7
- package/package.json +17 -7
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* - goal: ct == 0 and rl in the 6 reference goal patterns (even parity);
|
|
13
13
|
* - the 28-move set keeps the ct and rl position sets separate, so the move
|
|
14
14
|
* tables factor: ctmv (6,435×28) and rlmv (70×28);
|
|
15
|
-
* - the search explores the first 23 moves (face moves + Uw2/Rw/Rw2/Rw')
|
|
15
|
+
* - the search explores the first 23 moves (face moves + Uw2/Rw/Rw2/Rw')
|
|
16
|
+
* by default; the wide set (`CENTER2_SEARCH_MOVES_WIDE`, all 28, with
|
|
17
|
+
* the `pruningWide` table) additionally tries Dw2/Lw/Lw2/Lw'/Bw2.
|
|
16
18
|
*
|
|
17
19
|
* The phase-1 → phase-2 bridge (alignment + encode) is in `reduction.ts`.
|
|
18
20
|
*/
|
|
@@ -21,6 +23,12 @@ import type { Cube4State, Cube4Move } from "../types.js";
|
|
|
21
23
|
export declare const CENTER2_MOVES: readonly Cube4Move[];
|
|
22
24
|
/** The search's exploration set (the first 23 of CENTER2_MOVES). */
|
|
23
25
|
export declare const CENTER2_SEARCH_MOVES: readonly Cube4Move[];
|
|
26
|
+
/**
|
|
27
|
+
* The wide exploration set: all 28 moves (adds Dw2/Lw/Lw2/Lw'/Bw2).
|
|
28
|
+
* Searches over this set must use the `pruningWide` table — the
|
|
29
|
+
* 23-move pruning distances are inadmissible here (they overestimate).
|
|
30
|
+
*/
|
|
31
|
+
export declare const CENTER2_SEARCH_MOVES_WIDE: readonly Cube4Move[];
|
|
24
32
|
/** The 6 reference goal rl patterns (full 70-space values, even parity). */
|
|
25
33
|
export declare const CENTER2_GOAL_RL: readonly number[];
|
|
26
34
|
export declare const CENTER2_CT_STATES = 6435;
|
|
@@ -34,9 +42,12 @@ export declare function wingPermutationParity(wp: Uint8Array): 0 | 1;
|
|
|
34
42
|
/** Encode a full 4x4 state to the (ct, rl) coordinate (0..450,449). */
|
|
35
43
|
export declare function encodeCenter2(state: Cube4State): Center2Encoded;
|
|
36
44
|
export declare function isCenter2Goal(ct: number, rl: number): boolean;
|
|
45
|
+
export declare const ALIGNMENT_ROTATIONS: readonly (readonly string[])[];
|
|
37
46
|
export interface Center2BridgeResult {
|
|
38
47
|
/** Alignment moves (0-2). */
|
|
39
48
|
alignment: Cube4Move[];
|
|
49
|
+
/** Alignment rotation sequence (0-1 rotations: [], ["z"], or ["y"]). */
|
|
50
|
+
rotation: string[];
|
|
40
51
|
/** The aligned state (invariant). */
|
|
41
52
|
state: Cube4State;
|
|
42
53
|
/** The (ct, rl) coordinate of the aligned state. */
|
|
@@ -57,10 +68,39 @@ export interface Center2Tables {
|
|
|
57
68
|
ctMove: Int32Array;
|
|
58
69
|
/** 70 × 28 — rl rank (parity included) after each move. */
|
|
59
70
|
rlMove: Int32Array;
|
|
60
|
-
/** 450,450 exact BFS distances from the goal. */
|
|
71
|
+
/** 450,450 exact BFS distances from the goal (23-move set). */
|
|
61
72
|
pruning: Uint8Array;
|
|
73
|
+
/**
|
|
74
|
+
* 450,450 exact BFS distances from the goal (wide 28-move set).
|
|
75
|
+
* Optional in memory (older assets); required for wide searches.
|
|
76
|
+
*/
|
|
77
|
+
pruningWide?: Uint8Array | undefined;
|
|
62
78
|
}
|
|
63
79
|
export declare function generateCenter2Tables(): Center2Tables;
|
|
80
|
+
/**
|
|
81
|
+
* The ct rank above is RELATIVE to ct[15], so `ct == 0` accepts both
|
|
82
|
+
* assignments of the two non-R/L axes to the U/D and F/B face-pairs. Only
|
|
83
|
+
* one of them survives the downstream chirality gate (`axisDet`: the U, R, F
|
|
84
|
+
* axes must form a right-handed frame, i.e. U/D must hold axis (a + 2) % 3
|
|
85
|
+
* when R/L holds axis a). The chiral coordinate ranks the ABSOLUTE pattern
|
|
86
|
+
* "which of the 16 U/D/F/B positions hold the U/D-bound axis" (C(16,8) =
|
|
87
|
+
* 12,870) and its pruning measures the distance to the chirality-correct
|
|
88
|
+
* goals only, so the phase-2 search never walks wrong-chirality goal paths.
|
|
89
|
+
* Same goal set as `ct == 0 && axisDet == 1`; generated at runtime (~1.6 MB).
|
|
90
|
+
*/
|
|
91
|
+
export declare const CENTER2_CHIRAL_CT_STATES = 12870;
|
|
92
|
+
export declare const CENTER2_CHIRAL_STATES: number;
|
|
93
|
+
export interface Center2ChiralTables {
|
|
94
|
+
/** 12,870 × 28 — chiral ct rank after each move. */
|
|
95
|
+
ctMove: Uint16Array;
|
|
96
|
+
/** 900,900 exact BFS distances to the chiral goals (23-move set). */
|
|
97
|
+
pruning: Uint8Array;
|
|
98
|
+
/** Chiral ct rank of the goal pattern (U/D positions all U/D-bound). */
|
|
99
|
+
goalCt: number;
|
|
100
|
+
}
|
|
101
|
+
/** Chiral ct rank of a coordinate-invariant (bridged) phase-2 state. */
|
|
102
|
+
export declare function encodeCenter2ChiralCt(state: Cube4State): number;
|
|
103
|
+
export declare function generateCenter2ChiralTables(rlMove: Int32Array): Center2ChiralTables;
|
|
64
104
|
export interface Center2Phase2Result {
|
|
65
105
|
/** Phase-2 solution moves (standard 4x4 moves). */
|
|
66
106
|
moves: Cube4Move[];
|
|
@@ -77,6 +117,7 @@ export declare function solveCenter2(startCt: number, startRl: number, tables: C
|
|
|
77
117
|
* (transversal + even wing permutation), which most states fail.
|
|
78
118
|
*/
|
|
79
119
|
export declare function solveCenter2All(startCt: number, startRl: number, tables: Center2Tables, maxLength?: number, cap?: number): Center2Phase2Result[];
|
|
120
|
+
export declare function getWingMoveMaps(): Int32Array;
|
|
80
121
|
/**
|
|
81
122
|
* Solve Center 2 gated for an exact target length.
|
|
82
123
|
*/
|
|
@@ -87,5 +128,5 @@ export declare function solveCenter2GatedLength(startCt: number, startRl: number
|
|
|
87
128
|
* transversal (the phase-3 entry gate).
|
|
88
129
|
*/
|
|
89
130
|
export declare function solveCenter2Gated(startCt: number, startRl: number, startWp: Uint8Array, tables: Center2Tables, isGateEligible: (wp: Uint8Array) => boolean, maxLength?: number): Center2Phase2Result | null;
|
|
90
|
-
export declare function verifyCenter2(tables: Center2Tables): string[];
|
|
131
|
+
export declare function verifyCenter2(tables: Center2Tables, pruning?: Uint8Array, moves?: readonly Cube4Move[]): string[];
|
|
91
132
|
//# sourceMappingURL=center2.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"center2.d.ts","sourceRoot":"","sources":["../../../../src/puzzles/cube4/reduction/center2.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"center2.d.ts","sourceRoot":"","sources":["../../../../src/puzzles/cube4/reduction/center2.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
* - goal: ct == 0 and rl in the 6 reference goal patterns (even parity);
|
|
13
13
|
* - the 28-move set keeps the ct and rl position sets separate, so the move
|
|
14
14
|
* tables factor: ctmv (6,435×28) and rlmv (70×28);
|
|
15
|
-
* - the search explores the first 23 moves (face moves + Uw2/Rw/Rw2/Rw')
|
|
15
|
+
* - the search explores the first 23 moves (face moves + Uw2/Rw/Rw2/Rw')
|
|
16
|
+
* by default; the wide set (`CENTER2_SEARCH_MOVES_WIDE`, all 28, with
|
|
17
|
+
* the `pruningWide` table) additionally tries Dw2/Lw/Lw2/Lw'/Bw2.
|
|
16
18
|
*
|
|
17
19
|
* The phase-1 → phase-2 bridge (alignment + encode) is in `reduction.ts`.
|
|
18
20
|
*/
|
|
@@ -28,11 +30,23 @@ export const CENTER2_MOVES = [
|
|
|
28
30
|
];
|
|
29
31
|
/** The search's exploration set (the first 23 of CENTER2_MOVES). */
|
|
30
32
|
export const CENTER2_SEARCH_MOVES = CENTER2_MOVES.slice(0, 23);
|
|
33
|
+
/**
|
|
34
|
+
* The wide exploration set: all 28 moves (adds Dw2/Lw/Lw2/Lw'/Bw2).
|
|
35
|
+
* Searches over this set must use the `pruningWide` table — the
|
|
36
|
+
* 23-move pruning distances are inadmissible here (they overestimate).
|
|
37
|
+
*/
|
|
38
|
+
export const CENTER2_SEARCH_MOVES_WIDE = CENTER2_MOVES;
|
|
31
39
|
/** The 6 reference goal rl patterns (full 70-space values, even parity). */
|
|
32
40
|
export const CENTER2_GOAL_RL = [0, 18, 28, 46, 54, 56];
|
|
33
41
|
export const CENTER2_CT_STATES = 6435;
|
|
34
42
|
export const CENTER2_RL_STATES = 70;
|
|
35
43
|
export const CENTER2_STATES = CENTER2_CT_STATES * CENTER2_RL_STATES;
|
|
44
|
+
const CENTER2_GOAL_FLAGS = (() => {
|
|
45
|
+
const flags = new Uint8Array(CENTER2_RL_STATES);
|
|
46
|
+
for (const rl of CENTER2_GOAL_RL)
|
|
47
|
+
flags[rl] = 1;
|
|
48
|
+
return flags;
|
|
49
|
+
})();
|
|
36
50
|
// ct positions: U(0-3), D(12-15), F(8-11), B(20-23) — the reference's face
|
|
37
51
|
// order {U, D, F, B}, in this repo's face-major numbering.
|
|
38
52
|
const CT_POS = [0, 1, 2, 3, 12, 13, 14, 15, 8, 9, 10, 11, 20, 21, 22, 23];
|
|
@@ -96,7 +110,7 @@ export function encodeCenter2(state) {
|
|
|
96
110
|
return { ct: ctRank, rl: rlRank };
|
|
97
111
|
}
|
|
98
112
|
export function isCenter2Goal(ct, rl) {
|
|
99
|
-
return ct === 0 &&
|
|
113
|
+
return ct === 0 && CENTER2_GOAL_FLAGS[rl] === 1;
|
|
100
114
|
}
|
|
101
115
|
/**
|
|
102
116
|
* The phase-2 coordinate is only valid for states where exactly 8 of the
|
|
@@ -112,6 +126,11 @@ const ALIGNMENT_CANDIDATES = [
|
|
|
112
126
|
["Uw", "Dw'"]
|
|
113
127
|
];
|
|
114
128
|
function center2InvariantDiffs(centers) {
|
|
129
|
+
const rlAxis = centers[RL_POS[7]] % 3;
|
|
130
|
+
for (let i = 0; i < 7; i++) {
|
|
131
|
+
if (centers[RL_POS[i]] % 3 !== rlAxis)
|
|
132
|
+
return { ctDiff: -1, rlDiff: -1 };
|
|
133
|
+
}
|
|
115
134
|
let ctDiff = 0;
|
|
116
135
|
let rlDiff = 0;
|
|
117
136
|
for (let i = 0; i < 15; i++) {
|
|
@@ -124,12 +143,18 @@ function center2InvariantDiffs(centers) {
|
|
|
124
143
|
}
|
|
125
144
|
return { ctDiff, rlDiff };
|
|
126
145
|
}
|
|
146
|
+
export const ALIGNMENT_ROTATIONS = [
|
|
147
|
+
[],
|
|
148
|
+
["z"],
|
|
149
|
+
["y"]
|
|
150
|
+
];
|
|
127
151
|
/**
|
|
128
152
|
* Phase-1 → phase-2 bridge: apply the shortest alignment candidate that
|
|
129
153
|
* makes the state coordinate-invariant, then encode.
|
|
130
154
|
*/
|
|
131
155
|
export function center2Bridge(state) {
|
|
132
|
-
for (
|
|
156
|
+
for (let idx = 0; idx < ALIGNMENT_CANDIDATES.length; idx++) {
|
|
157
|
+
const alignment = ALIGNMENT_CANDIDATES[idx];
|
|
133
158
|
const aligned = alignment.length === 0
|
|
134
159
|
? state
|
|
135
160
|
: applyCube4Algorithm(state, alignment);
|
|
@@ -137,6 +162,7 @@ export function center2Bridge(state) {
|
|
|
137
162
|
if (ctDiff === 8 && rlDiff === 4) {
|
|
138
163
|
return {
|
|
139
164
|
alignment: [...alignment],
|
|
165
|
+
rotation: [...ALIGNMENT_ROTATIONS[idx]],
|
|
140
166
|
state: aligned,
|
|
141
167
|
encoded: encodeCenter2(aligned)
|
|
142
168
|
};
|
|
@@ -246,7 +272,123 @@ export function generateCenter2Tables() {
|
|
|
246
272
|
}
|
|
247
273
|
}
|
|
248
274
|
}
|
|
249
|
-
|
|
275
|
+
// Wide pruning BFS: same goals, all 28 moves (exact distances for the
|
|
276
|
+
// wide search; the 23-move table overestimates there).
|
|
277
|
+
const pruningWide = new Uint8Array(CENTER2_STATES).fill(0xff);
|
|
278
|
+
const wideQueue = [];
|
|
279
|
+
for (const rl of CENTER2_GOAL_RL) {
|
|
280
|
+
pruningWide[rl] = 0;
|
|
281
|
+
wideQueue.push(rl);
|
|
282
|
+
}
|
|
283
|
+
let wideHead = 0;
|
|
284
|
+
while (wideHead < wideQueue.length) {
|
|
285
|
+
const idx = wideQueue[wideHead++];
|
|
286
|
+
const ct = Math.floor(idx / CENTER2_RL_STATES);
|
|
287
|
+
const rl = idx % CENTER2_RL_STATES;
|
|
288
|
+
const d = pruningWide[idx];
|
|
289
|
+
for (let m = 0; m < CENTER2_SEARCH_MOVES_WIDE.length; m++) {
|
|
290
|
+
const nextCt = ctMove[ct * CENTER2_MOVES.length + m];
|
|
291
|
+
const nextRl = rlMove[rl * CENTER2_MOVES.length + m];
|
|
292
|
+
const next = nextCt * CENTER2_RL_STATES + nextRl;
|
|
293
|
+
if (pruningWide[next] === 0xff) {
|
|
294
|
+
pruningWide[next] = d + 1;
|
|
295
|
+
wideQueue.push(next);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return { ctMove, rlMove, pruning, pruningWide };
|
|
300
|
+
}
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
// Chiral (absolute-ct) phase-2 tables
|
|
303
|
+
// ---------------------------------------------------------------------------
|
|
304
|
+
/**
|
|
305
|
+
* The ct rank above is RELATIVE to ct[15], so `ct == 0` accepts both
|
|
306
|
+
* assignments of the two non-R/L axes to the U/D and F/B face-pairs. Only
|
|
307
|
+
* one of them survives the downstream chirality gate (`axisDet`: the U, R, F
|
|
308
|
+
* axes must form a right-handed frame, i.e. U/D must hold axis (a + 2) % 3
|
|
309
|
+
* when R/L holds axis a). The chiral coordinate ranks the ABSOLUTE pattern
|
|
310
|
+
* "which of the 16 U/D/F/B positions hold the U/D-bound axis" (C(16,8) =
|
|
311
|
+
* 12,870) and its pruning measures the distance to the chirality-correct
|
|
312
|
+
* goals only, so the phase-2 search never walks wrong-chirality goal paths.
|
|
313
|
+
* Same goal set as `ct == 0 && axisDet == 1`; generated at runtime (~1.6 MB).
|
|
314
|
+
*/
|
|
315
|
+
export const CENTER2_CHIRAL_CT_STATES = 12870;
|
|
316
|
+
export const CENTER2_CHIRAL_STATES = CENTER2_CHIRAL_CT_STATES * CENTER2_RL_STATES;
|
|
317
|
+
function rankSubset16(bits) {
|
|
318
|
+
let idx = 0;
|
|
319
|
+
let r = 8;
|
|
320
|
+
for (let i = 15; i >= 0 && r > 0; i--) {
|
|
321
|
+
if (bits[i] === 1) {
|
|
322
|
+
idx += CNK[i][r];
|
|
323
|
+
r--;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return idx;
|
|
327
|
+
}
|
|
328
|
+
function unrankSubset16(idx) {
|
|
329
|
+
const bits = new Uint8Array(16);
|
|
330
|
+
let r = 8;
|
|
331
|
+
for (let i = 15; i >= 0 && r > 0; i--) {
|
|
332
|
+
if (idx >= CNK[i][r]) {
|
|
333
|
+
idx -= CNK[i][r];
|
|
334
|
+
bits[i] = 1;
|
|
335
|
+
r--;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return bits;
|
|
339
|
+
}
|
|
340
|
+
/** Chiral ct rank of a coordinate-invariant (bridged) phase-2 state. */
|
|
341
|
+
export function encodeCenter2ChiralCt(state) {
|
|
342
|
+
const rlAxis = state.centers[RL_POS[0]] % 3;
|
|
343
|
+
const udAxis = (rlAxis + 2) % 3;
|
|
344
|
+
const bits = new Uint8Array(16);
|
|
345
|
+
for (let i = 0; i < 16; i++)
|
|
346
|
+
bits[i] = state.centers[CT_POS[i]] % 3 === udAxis ? 1 : 0;
|
|
347
|
+
return rankSubset16(bits);
|
|
348
|
+
}
|
|
349
|
+
export function generateCenter2ChiralTables(rlMove) {
|
|
350
|
+
const moveMaps = buildMovePositionMaps();
|
|
351
|
+
const nMoves = CENTER2_MOVES.length;
|
|
352
|
+
const ctMove = new Uint16Array(CENTER2_CHIRAL_CT_STATES * nMoves);
|
|
353
|
+
const full = new Uint8Array(24);
|
|
354
|
+
const bits = new Uint8Array(16);
|
|
355
|
+
for (let ct = 0; ct < CENTER2_CHIRAL_CT_STATES; ct++) {
|
|
356
|
+
const pattern = unrankSubset16(ct);
|
|
357
|
+
full.fill(0);
|
|
358
|
+
for (let i = 0; i < 16; i++)
|
|
359
|
+
full[CT_POS[i]] = pattern[i];
|
|
360
|
+
for (let m = 0; m < nMoves; m++) {
|
|
361
|
+
for (let i = 0; i < 16; i++)
|
|
362
|
+
bits[i] = full[moveMaps[m * 24 + CT_POS[i]]];
|
|
363
|
+
ctMove[ct * nMoves + m] = rankSubset16(bits);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const goalBits = new Uint8Array(16);
|
|
367
|
+
for (let i = 0; i < 8; i++)
|
|
368
|
+
goalBits[i] = 1; // CT_POS[0..7] = U and D faces
|
|
369
|
+
const goalCt = rankSubset16(goalBits);
|
|
370
|
+
const pruning = new Uint8Array(CENTER2_CHIRAL_STATES).fill(0xff);
|
|
371
|
+
const queue = new Int32Array(CENTER2_CHIRAL_STATES);
|
|
372
|
+
let tail = 0;
|
|
373
|
+
for (const rl of CENTER2_GOAL_RL) {
|
|
374
|
+
const idx = goalCt * CENTER2_RL_STATES + rl;
|
|
375
|
+
pruning[idx] = 0;
|
|
376
|
+
queue[tail++] = idx;
|
|
377
|
+
}
|
|
378
|
+
for (let head = 0; head < tail; head++) {
|
|
379
|
+
const idx = queue[head];
|
|
380
|
+
const ct = (idx / CENTER2_RL_STATES) | 0;
|
|
381
|
+
const rl = idx - ct * CENTER2_RL_STATES;
|
|
382
|
+
const d = pruning[idx] + 1;
|
|
383
|
+
for (let m = 0; m < CENTER2_SEARCH_MOVES.length; m++) {
|
|
384
|
+
const next = ctMove[ct * nMoves + m] * CENTER2_RL_STATES + rlMove[rl * nMoves + m];
|
|
385
|
+
if (pruning[next] === 0xff) {
|
|
386
|
+
pruning[next] = d;
|
|
387
|
+
queue[tail++] = next;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return { ctMove, pruning, goalCt };
|
|
250
392
|
}
|
|
251
393
|
// The reference's cancellation rule (ckmv over move2std): skip the same base
|
|
252
394
|
// move, or the same axis-class when the previous move's standard index is
|
|
@@ -320,7 +462,7 @@ export function solveCenter2All(startCt, startRl, tables, maxLength = 40, cap =
|
|
|
320
462
|
}
|
|
321
463
|
}
|
|
322
464
|
let cachedWingMaps = null;
|
|
323
|
-
function getWingMoveMaps() {
|
|
465
|
+
export function getWingMoveMaps() {
|
|
324
466
|
if (!cachedWingMaps) {
|
|
325
467
|
cachedWingMaps = buildWingMoveMaps();
|
|
326
468
|
}
|
|
@@ -421,24 +563,24 @@ function buildWingMoveMaps() {
|
|
|
421
563
|
// ---------------------------------------------------------------------------
|
|
422
564
|
// Verification gates
|
|
423
565
|
// ---------------------------------------------------------------------------
|
|
424
|
-
export function verifyCenter2(tables) {
|
|
566
|
+
export function verifyCenter2(tables, pruning = tables.pruning, moves = CENTER2_SEARCH_MOVES) {
|
|
425
567
|
const errors = [];
|
|
426
568
|
for (const rl of CENTER2_GOAL_RL) {
|
|
427
|
-
if (
|
|
569
|
+
if (pruning[rl] !== 0) {
|
|
428
570
|
errors.push(`Goal rl ${rl} must have pruning 0.`);
|
|
429
571
|
}
|
|
430
572
|
}
|
|
431
573
|
let maxDepth = 0;
|
|
432
574
|
for (let idx = 0; idx < CENTER2_STATES; idx++) {
|
|
433
|
-
const d =
|
|
575
|
+
const d = pruning[idx];
|
|
434
576
|
if (d > maxDepth)
|
|
435
577
|
maxDepth = d;
|
|
436
578
|
const ct = Math.floor(idx / CENTER2_RL_STATES);
|
|
437
579
|
const rl = idx % CENTER2_RL_STATES;
|
|
438
|
-
for (let m = 0; m <
|
|
580
|
+
for (let m = 0; m < moves.length; m++) {
|
|
439
581
|
const nc = tables.ctMove[ct * CENTER2_MOVES.length + m];
|
|
440
582
|
const nr = tables.rlMove[rl * CENTER2_MOVES.length + m];
|
|
441
|
-
const nd =
|
|
583
|
+
const nd = pruning[nc * CENTER2_RL_STATES + nr];
|
|
442
584
|
if (nd < d - 1 || nd > d + 1) {
|
|
443
585
|
errors.push(`Pruning inconsistency at ${idx} move ${CENTER2_MOVES[m]}: ${d} -> ${nd}.`);
|
|
444
586
|
break;
|
|
@@ -80,6 +80,10 @@ export interface Edge3Tables {
|
|
|
80
80
|
* `maxDepthCap` stops the BFS early (validation only).
|
|
81
81
|
*/
|
|
82
82
|
export declare function generateEdge3Tables(maxDepthCap?: number): Edge3Tables;
|
|
83
|
+
/**
|
|
84
|
+
* Unpack 4-bit nibble-packed distances into a byte-expanded Uint8Array (1 byte per state).
|
|
85
|
+
*/
|
|
86
|
+
export declare function unpackEdge3Distances(packed: Uint8Array): Uint8Array;
|
|
83
87
|
/**
|
|
84
88
|
* The distance lookup over a loaded distances buffer: builds the sym
|
|
85
89
|
* machinery once (cached) and returns a closure from the std-form edge
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edge3.d.ts","sourceRoot":"","sources":["../../../../src/puzzles/cube4/reduction/edge3.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAWH,mEAAmE;AACnE,eAAO,MAAM,WAAW,WAAa,CAAC;AACtC,eAAO,MAAM,aAAa,OAAO,CAAC;AAClC,eAAO,MAAM,WAAW,QAAS,CAAC;AAGlC,qEAAqE;AACrE,eAAO,MAAM,eAAe,KAAK,CAAC;AAUlC,+EAA+E;AAC/E,eAAO,MAAM,SAAS,EAAE,SAAS,MAAM,EAEtC,CAAC;AAaF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C;AAkCD;;;;;GAKG;AACH,iBAAS,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CA2G3E;AAkCD,iFAAiF;AACjF,iBAAS,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAO3E;AAMD;;;;GAIG;AACH,iBAAS,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,MAAM,CAS3E;AAED;;;GAGG;AACH,iBAAS,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAmBhD;AAOD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,oEAAoE;IACpE,QAAQ,EAAE,WAAW,CAAC;IACtB,gDAAgD;IAChD,OAAO,EAAE,WAAW,CAAC;IACrB,iFAAiF;IACjF,QAAQ,EAAE,WAAW,CAAC;IACtB,qFAAqF;IACrF,OAAO,EAAE,WAAW,CAAC;CACtB;AAID,wBAAgB,YAAY,IAAI,SAAS,CAKxC;AAED,wBAAgB,cAAc,IAAI,SAAS,CAoE1C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,UAAU,EAClB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,UAAU,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CA6BR;AAMD,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,SAAS,EAAE,UAAU,CAAC;IACtB,0DAA0D;IAC1D,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,SAAK,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"edge3.d.ts","sourceRoot":"","sources":["../../../../src/puzzles/cube4/reduction/edge3.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAWH,mEAAmE;AACnE,eAAO,MAAM,WAAW,WAAa,CAAC;AACtC,eAAO,MAAM,aAAa,OAAO,CAAC;AAClC,eAAO,MAAM,WAAW,QAAS,CAAC;AAGlC,qEAAqE;AACrE,eAAO,MAAM,eAAe,KAAK,CAAC;AAUlC,+EAA+E;AAC/E,eAAO,MAAM,SAAS,EAAE,SAAS,MAAM,EAEtC,CAAC;AAaF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C;AAkCD;;;;;GAKG;AACH,iBAAS,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CA2G3E;AAkCD,iFAAiF;AACjF,iBAAS,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAO3E;AAMD;;;;GAIG;AACH,iBAAS,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,UAAQ,GAAG,MAAM,CAS3E;AAED;;;GAGG;AACH,iBAAS,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAmBhD;AAOD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,oEAAoE;IACpE,QAAQ,EAAE,WAAW,CAAC;IACtB,gDAAgD;IAChD,OAAO,EAAE,WAAW,CAAC;IACrB,iFAAiF;IACjF,QAAQ,EAAE,WAAW,CAAC;IACtB,qFAAqF;IACrF,OAAO,EAAE,WAAW,CAAC;CACtB;AAID,wBAAgB,YAAY,IAAI,SAAS,CAKxC;AAED,wBAAgB,cAAc,IAAI,SAAS,CAoE1C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,UAAU,EAClB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,WAAW,EACpB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,UAAU,EAClB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CA6BR;AAMD,MAAM,WAAW,WAAW;IAC1B,uDAAuD;IACvD,SAAS,EAAE,UAAU,CAAC;IACtB,0DAA0D;IAC1D,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,SAAK,GAAG,WAAW,CAmEjE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CASnE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,UAAU,GAAG,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,CAWvF;AAMD,uBAAuB;AACvB,wBAAgB,gBAAgB;;;;;;;EAE/B;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAkBzD"}
|
|
@@ -468,8 +468,23 @@ export function generateEdge3Tables(maxDepthCap = -1) {
|
|
|
468
468
|
frontier = next;
|
|
469
469
|
depth++;
|
|
470
470
|
}
|
|
471
|
-
const
|
|
472
|
-
|
|
471
|
+
const unpacked = unpackEdge3Distances(distances);
|
|
472
|
+
const distanceOfEdge = edge3DistanceLookup(unpacked);
|
|
473
|
+
return { distances: unpacked, distanceOfEdge };
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Unpack 4-bit nibble-packed distances into a byte-expanded Uint8Array (1 byte per state).
|
|
477
|
+
*/
|
|
478
|
+
export function unpackEdge3Distances(packed) {
|
|
479
|
+
if (packed.length >= EDGE3_TOTAL)
|
|
480
|
+
return packed;
|
|
481
|
+
const unpacked = new Uint8Array(EDGE3_TOTAL);
|
|
482
|
+
for (let i = 0; i < packed.length; i++) {
|
|
483
|
+
const b = packed[i];
|
|
484
|
+
unpacked[i << 1] = b & 0x0f;
|
|
485
|
+
unpacked[(i << 1) | 1] = b >> 4;
|
|
486
|
+
}
|
|
487
|
+
return unpacked;
|
|
473
488
|
}
|
|
474
489
|
/**
|
|
475
490
|
* The distance lookup over a loaded distances buffer: builds the sym
|
|
@@ -480,9 +495,12 @@ export function edge3DistanceLookup(distances) {
|
|
|
480
495
|
const t = symTables ?? buildSymTables();
|
|
481
496
|
const { sym2Raw, sym2Mask, raw2Sym, mvrot, mvroto } = t;
|
|
482
497
|
const identity = Uint8Array.from({ length: 12 }, (_, i) => i);
|
|
498
|
+
const isUnpacked = distances.length >= EDGE3_TOTAL;
|
|
483
499
|
return (e) => {
|
|
484
500
|
const std = normalizePairingState(e, identity).edge;
|
|
485
501
|
const idx = getMvSymFrom(std, identity, 20, sym2Raw, sym2Mask, raw2Sym, mvrot, mvroto) >> 3;
|
|
502
|
+
if (isUnpacked)
|
|
503
|
+
return distances[idx];
|
|
486
504
|
return (distances[idx >> 1] >> ((idx & 1) * 4)) & 0x0f;
|
|
487
505
|
};
|
|
488
506
|
}
|
|
@@ -500,8 +518,10 @@ export function verifyEdge3(tables) {
|
|
|
500
518
|
errors.push("Solved state must have distance 0.");
|
|
501
519
|
}
|
|
502
520
|
let seen = 0;
|
|
521
|
+
const isUnpacked = tables.distances.length >= EDGE3_TOTAL;
|
|
503
522
|
for (let i = 0; i < EDGE3_TOTAL; i++) {
|
|
504
|
-
|
|
523
|
+
const d = isUnpacked ? tables.distances[i] : ((tables.distances[i >> 1] >> ((i & 1) * 4)) & 0x0f);
|
|
524
|
+
if (d !== 0x0f)
|
|
505
525
|
seen++;
|
|
506
526
|
}
|
|
507
527
|
if (seen !== EDGE3_TOTAL) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continuous two-phase 3x3 solver for the 4x4 finish (Kociemba-style).
|
|
3
|
+
*
|
|
4
|
+
* Unlike the batch solver in `cube3/solver` (collect phase-1 solutions,
|
|
5
|
+
* then solve phase 2 for each), this is the classic continuous search: an
|
|
6
|
+
* iterative-deepening phase 1 where EVERY phase-1 solution immediately runs
|
|
7
|
+
* phase 2 under the remaining length budget, and every solution found
|
|
8
|
+
* tightens the bound for the rest of the search. Optional legal views are
|
|
9
|
+
* searched interleaved by phase-1 depth — up to 3 relabelled axes
|
|
10
|
+
* (identity, x, z) × {state, inverse} — which is what makes short solutions
|
|
11
|
+
* cheap to find (the existing cube3 solver's rotation/inverse trick).
|
|
12
|
+
*
|
|
13
|
+
* Tables: the already-loaded cube3 tables (phase-1: twist/flip/slice move
|
|
14
|
+
* tables + twist×flip, slice×twist, slice×flip pruning; phase-2: cp/ep/sp
|
|
15
|
+
* move tables + cp×sp, ep×sp pruning). Nothing is generated here.
|
|
16
|
+
*
|
|
17
|
+
* Deterministic: the only stopping rules are node counts and lengths, so
|
|
18
|
+
* the result is a pure function of (state, options).
|
|
19
|
+
*/
|
|
20
|
+
import type { Cube3Move, Cube3State } from "../../cube3/types.js";
|
|
21
|
+
import { type Cube3Phase1Tables, type Cube3Phase2Tables } from "../../cube3/solver/tables.js";
|
|
22
|
+
export interface Finish3Tables {
|
|
23
|
+
phase1: Cube3Phase1Tables;
|
|
24
|
+
phase2: Cube3Phase2Tables;
|
|
25
|
+
}
|
|
26
|
+
export interface Finish3Options {
|
|
27
|
+
/** Stop as soon as a solution of at most this length is found (default 0 = never). */
|
|
28
|
+
targetLength?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Node budget (phase-1 + phase-2 nodes) after which the best solution so
|
|
31
|
+
* far is returned (default 200_000). The search always runs until a first
|
|
32
|
+
* solution exists, bounded by `hardMaxNodes`.
|
|
33
|
+
*/
|
|
34
|
+
maxNodes?: number;
|
|
35
|
+
/** Absolute node cap; exceeding it without any solution throws (default 20M). */
|
|
36
|
+
hardMaxNodes?: number;
|
|
37
|
+
/** Views searched: 1 (as is), 2 (+inverse), 6 (3 axes × inverse). */
|
|
38
|
+
views?: 1 | 2 | 6;
|
|
39
|
+
/** @deprecated Ignored: views are built by cubie conjugation. */
|
|
40
|
+
viewScramble?: readonly Cube3Move[];
|
|
41
|
+
/** Longest phase-2 segment considered (default 12). */
|
|
42
|
+
maxPhase2Length?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface Finish3Result {
|
|
45
|
+
moves: Cube3Move[];
|
|
46
|
+
nodes: number;
|
|
47
|
+
}
|
|
48
|
+
export declare class Finish3SearchError extends Error {
|
|
49
|
+
readonly code: "cube4-finish3-cap";
|
|
50
|
+
constructor(message: string);
|
|
51
|
+
}
|
|
52
|
+
export declare function solveFinish3(state: Cube3State, tables: Finish3Tables, options?: Finish3Options): Finish3Result;
|
|
53
|
+
//# sourceMappingURL=finish3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finish3.d.ts","sourceRoot":"","sources":["../../../../src/puzzles/cube4/reduction/finish3.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAalE,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACvB,MAAM,8BAA8B,CAAC;AAMtC,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,sFAAsF;IACtF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClB,iEAAiE;IACjE,YAAY,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACpC,uDAAuD;IACvD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAG,mBAAmB,CAAU;gBAEjC,OAAO,EAAE,MAAM;CAI5B;AAsKD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAuMf"}
|