@cubingcenter/scrambler 0.1.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 +169 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +10 -0
- package/dist/cli/run.d.ts +9 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +139 -0
- package/dist/core/api.d.ts +19 -0
- package/dist/core/api.d.ts.map +1 -0
- package/dist/core/api.js +94 -0
- package/dist/core/errors.d.ts +21 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +34 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +3 -0
- package/dist/core/registry.d.ts +10 -0
- package/dist/core/registry.d.ts.map +1 -0
- package/dist/core/registry.js +35 -0
- package/dist/core/types.d.ts +34 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/puzzles/clock/index.d.ts +2 -0
- package/dist/puzzles/clock/index.d.ts.map +1 -0
- package/dist/puzzles/clock/index.js +1 -0
- package/dist/puzzles/clock/scrambler.d.ts +4 -0
- package/dist/puzzles/clock/scrambler.d.ts.map +1 -0
- package/dist/puzzles/clock/scrambler.js +50 -0
- package/dist/puzzles/cube2/facelets.d.ts +5 -0
- package/dist/puzzles/cube2/facelets.d.ts.map +1 -0
- package/dist/puzzles/cube2/facelets.js +53 -0
- package/dist/puzzles/cube2/index.d.ts +10 -0
- package/dist/puzzles/cube2/index.d.ts.map +1 -0
- package/dist/puzzles/cube2/index.js +8 -0
- package/dist/puzzles/cube2/moves.d.ts +9 -0
- package/dist/puzzles/cube2/moves.d.ts.map +1 -0
- package/dist/puzzles/cube2/moves.js +79 -0
- package/dist/puzzles/cube2/random-state.d.ts +3 -0
- package/dist/puzzles/cube2/random-state.d.ts.map +1 -0
- package/dist/puzzles/cube2/random-state.js +51 -0
- package/dist/puzzles/cube2/scrambler.d.ts +6 -0
- package/dist/puzzles/cube2/scrambler.d.ts.map +1 -0
- package/dist/puzzles/cube2/scrambler.js +54 -0
- package/dist/puzzles/cube2/solver/browser-loader.d.ts +12 -0
- package/dist/puzzles/cube2/solver/browser-loader.d.ts.map +1 -0
- package/dist/puzzles/cube2/solver/browser-loader.js +80 -0
- package/dist/puzzles/cube2/solver/generated/distances.bin +1 -0
- package/dist/puzzles/cube2/solver/generated/manifest.json +21 -0
- package/dist/puzzles/cube2/solver/generated/orientation-distances.bin +0 -0
- package/dist/puzzles/cube2/solver/generated/orientation-table.bin +0 -0
- package/dist/puzzles/cube2/solver/generated/permutation-distances.bin +0 -0
- package/dist/puzzles/cube2/solver/generated/permutation-table.bin +0 -0
- package/dist/puzzles/cube2/solver/generated-assets.d.ts +6 -0
- package/dist/puzzles/cube2/solver/generated-assets.d.ts.map +1 -0
- package/dist/puzzles/cube2/solver/generated-assets.js +25 -0
- package/dist/puzzles/cube2/solver/index.d.ts +3 -0
- package/dist/puzzles/cube2/solver/index.d.ts.map +1 -0
- package/dist/puzzles/cube2/solver/index.js +1 -0
- package/dist/puzzles/cube2/solver/node-loader.d.ts +6 -0
- package/dist/puzzles/cube2/solver/node-loader.d.ts.map +1 -0
- package/dist/puzzles/cube2/solver/node-loader.js +83 -0
- package/dist/puzzles/cube2/solver/search.d.ts +8 -0
- package/dist/puzzles/cube2/solver/search.d.ts.map +1 -0
- package/dist/puzzles/cube2/solver/search.js +50 -0
- package/dist/puzzles/cube2/solver/table-metadata.d.ts +16 -0
- package/dist/puzzles/cube2/solver/table-metadata.d.ts.map +1 -0
- package/dist/puzzles/cube2/solver/table-metadata.js +15 -0
- package/dist/puzzles/cube2/solver/tables.d.ts +14 -0
- package/dist/puzzles/cube2/solver/tables.d.ts.map +1 -0
- package/dist/puzzles/cube2/solver/tables.js +82 -0
- package/dist/puzzles/cube2/state.d.ts +6 -0
- package/dist/puzzles/cube2/state.d.ts.map +1 -0
- package/dist/puzzles/cube2/state.js +30 -0
- package/dist/puzzles/cube2/types.d.ts +23 -0
- package/dist/puzzles/cube2/types.d.ts.map +1 -0
- package/dist/puzzles/cube2/types.js +21 -0
- package/dist/puzzles/cube2/validation.d.ts +6 -0
- package/dist/puzzles/cube2/validation.d.ts.map +1 -0
- package/dist/puzzles/cube2/validation.js +72 -0
- package/dist/puzzles/cube3/facelets.d.ts +5 -0
- package/dist/puzzles/cube3/facelets.d.ts.map +1 -0
- package/dist/puzzles/cube3/facelets.js +89 -0
- package/dist/puzzles/cube3/index.d.ts +10 -0
- package/dist/puzzles/cube3/index.d.ts.map +1 -0
- package/dist/puzzles/cube3/index.js +8 -0
- package/dist/puzzles/cube3/moves.d.ts +9 -0
- package/dist/puzzles/cube3/moves.d.ts.map +1 -0
- package/dist/puzzles/cube3/moves.js +210 -0
- package/dist/puzzles/cube3/random-state.d.ts +3 -0
- package/dist/puzzles/cube3/random-state.d.ts.map +1 -0
- package/dist/puzzles/cube3/random-state.js +59 -0
- package/dist/puzzles/cube3/scrambler.d.ts +6 -0
- package/dist/puzzles/cube3/scrambler.d.ts.map +1 -0
- package/dist/puzzles/cube3/scrambler.js +59 -0
- package/dist/puzzles/cube3/solver/browser-loader.d.ts +5 -0
- package/dist/puzzles/cube3/solver/browser-loader.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/browser-loader.js +134 -0
- package/dist/puzzles/cube3/solver/browser-worker-pool.d.ts +31 -0
- package/dist/puzzles/cube3/solver/browser-worker-pool.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/browser-worker-pool.js +118 -0
- package/dist/puzzles/cube3/solver/browser-worker.d.ts +2 -0
- package/dist/puzzles/cube3/solver/browser-worker.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/browser-worker.js +71 -0
- package/dist/puzzles/cube3/solver/coordinates.d.ts +34 -0
- package/dist/puzzles/cube3/solver/coordinates.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/coordinates.js +266 -0
- package/dist/puzzles/cube3/solver/generated/manifest.json +404 -0
- package/dist/puzzles/cube3/solver/generated/move-cornerOrientation.bin +0 -0
- package/dist/puzzles/cube3/solver/generated/move-cornerPermutation.bin +0 -0
- package/dist/puzzles/cube3/solver/generated/move-edgeOrientation.bin +0 -0
- package/dist/puzzles/cube3/solver/generated/move-slicePermutation.bin +0 -0
- package/dist/puzzles/cube3/solver/generated/move-udEdgePermutation.bin +0 -0
- package/dist/puzzles/cube3/solver/generated/move-udSlice.bin +0 -0
- package/dist/puzzles/cube3/solver/generated/pruning-cornerOrientation.bin +1 -0
- package/dist/puzzles/cube3/solver/generated/pruning-cornerOrientationEdgeOrientation.bin +1 -0
- package/dist/puzzles/cube3/solver/generated/pruning-cornerPermutation.bin +1 -0
- package/dist/puzzles/cube3/solver/generated/pruning-cornerPermutationSlicePermutation.bin +1 -0
- package/dist/puzzles/cube3/solver/generated/pruning-edgeOrientation.bin +1 -0
- package/dist/puzzles/cube3/solver/generated/pruning-slicePermutation.bin +1 -0
- package/dist/puzzles/cube3/solver/generated/pruning-udEdgePermutation.bin +1 -0
- package/dist/puzzles/cube3/solver/generated/pruning-udEdgePermutationSlicePermutation.bin +1 -0
- package/dist/puzzles/cube3/solver/generated/pruning-udSlice.bin +0 -0
- package/dist/puzzles/cube3/solver/generated-assets.d.ts +5 -0
- package/dist/puzzles/cube3/solver/generated-assets.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/generated-assets.js +60 -0
- package/dist/puzzles/cube3/solver/index.d.ts +10 -0
- package/dist/puzzles/cube3/solver/index.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/index.js +5 -0
- package/dist/puzzles/cube3/solver/node-loader.d.ts +3 -0
- package/dist/puzzles/cube3/solver/node-loader.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/node-loader.js +120 -0
- package/dist/puzzles/cube3/solver/phase1.d.ts +28 -0
- package/dist/puzzles/cube3/solver/phase1.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/phase1.js +150 -0
- package/dist/puzzles/cube3/solver/phase2.d.ts +44 -0
- package/dist/puzzles/cube3/solver/phase2.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/phase2.js +270 -0
- package/dist/puzzles/cube3/solver/search-utils.d.ts +9 -0
- package/dist/puzzles/cube3/solver/search-utils.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/search-utils.js +41 -0
- package/dist/puzzles/cube3/solver/table-metadata.d.ts +97 -0
- package/dist/puzzles/cube3/solver/table-metadata.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/table-metadata.js +21 -0
- package/dist/puzzles/cube3/solver/tables.d.ts +72 -0
- package/dist/puzzles/cube3/solver/tables.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/tables.js +202 -0
- package/dist/puzzles/cube3/solver/worker-pool.d.ts +18 -0
- package/dist/puzzles/cube3/solver/worker-pool.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/worker-pool.js +116 -0
- package/dist/puzzles/cube3/solver/worker.d.ts +2 -0
- package/dist/puzzles/cube3/solver/worker.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/worker.js +73 -0
- package/dist/puzzles/cube3/state.d.ts +6 -0
- package/dist/puzzles/cube3/state.d.ts.map +1 -0
- package/dist/puzzles/cube3/state.js +40 -0
- package/dist/puzzles/cube3/subset-state.d.ts +4 -0
- package/dist/puzzles/cube3/subset-state.d.ts.map +1 -0
- package/dist/puzzles/cube3/subset-state.js +163 -0
- package/dist/puzzles/cube3/types.d.ts +29 -0
- package/dist/puzzles/cube3/types.d.ts.map +1 -0
- package/dist/puzzles/cube3/types.js +22 -0
- package/dist/puzzles/cube3/validation.d.ts +6 -0
- package/dist/puzzles/cube3/validation.d.ts.map +1 -0
- package/dist/puzzles/cube3/validation.js +83 -0
- package/dist/puzzles/cube4/facelets.d.ts +5 -0
- package/dist/puzzles/cube4/facelets.d.ts.map +1 -0
- package/dist/puzzles/cube4/facelets.js +135 -0
- package/dist/puzzles/cube4/index.d.ts +7 -0
- package/dist/puzzles/cube4/index.d.ts.map +1 -0
- package/dist/puzzles/cube4/index.js +8 -0
- package/dist/puzzles/cube4/moves.d.ts +37 -0
- package/dist/puzzles/cube4/moves.d.ts.map +1 -0
- package/dist/puzzles/cube4/moves.js +243 -0
- package/dist/puzzles/cube4/scrambler.d.ts +4 -0
- package/dist/puzzles/cube4/scrambler.d.ts.map +1 -0
- package/dist/puzzles/cube4/scrambler.js +98 -0
- package/dist/puzzles/cube4/state.d.ts +16 -0
- package/dist/puzzles/cube4/state.d.ts.map +1 -0
- package/dist/puzzles/cube4/state.js +84 -0
- package/dist/puzzles/cube4/types.d.ts +76 -0
- package/dist/puzzles/cube4/types.d.ts.map +1 -0
- package/dist/puzzles/cube4/types.js +62 -0
- package/dist/puzzles/cube5x5/index.d.ts +4 -0
- package/dist/puzzles/cube5x5/index.d.ts.map +1 -0
- package/dist/puzzles/cube5x5/index.js +2 -0
- package/dist/puzzles/cube5x5/scrambler.d.ts +4 -0
- package/dist/puzzles/cube5x5/scrambler.d.ts.map +1 -0
- package/dist/puzzles/cube5x5/scrambler.js +93 -0
- package/dist/puzzles/cube5x5/types.d.ts +4 -0
- package/dist/puzzles/cube5x5/types.d.ts.map +1 -0
- package/dist/puzzles/cube5x5/types.js +4 -0
- package/dist/puzzles/cube6x6/index.d.ts +4 -0
- package/dist/puzzles/cube6x6/index.d.ts.map +1 -0
- package/dist/puzzles/cube6x6/index.js +2 -0
- package/dist/puzzles/cube6x6/scrambler.d.ts +4 -0
- package/dist/puzzles/cube6x6/scrambler.d.ts.map +1 -0
- package/dist/puzzles/cube6x6/scrambler.js +105 -0
- package/dist/puzzles/cube6x6/types.d.ts +4 -0
- package/dist/puzzles/cube6x6/types.d.ts.map +1 -0
- package/dist/puzzles/cube6x6/types.js +8 -0
- package/dist/puzzles/cube7x7/index.d.ts +4 -0
- package/dist/puzzles/cube7x7/index.d.ts.map +1 -0
- package/dist/puzzles/cube7x7/index.js +2 -0
- package/dist/puzzles/cube7x7/scrambler.d.ts +4 -0
- package/dist/puzzles/cube7x7/scrambler.d.ts.map +1 -0
- package/dist/puzzles/cube7x7/scrambler.js +93 -0
- package/dist/puzzles/cube7x7/types.d.ts +4 -0
- package/dist/puzzles/cube7x7/types.d.ts.map +1 -0
- package/dist/puzzles/cube7x7/types.js +8 -0
- package/dist/puzzles/index.d.ts +10 -0
- package/dist/puzzles/index.d.ts.map +1 -0
- package/dist/puzzles/index.js +28 -0
- package/dist/puzzles/megaminx/index.d.ts +4 -0
- package/dist/puzzles/megaminx/index.d.ts.map +1 -0
- package/dist/puzzles/megaminx/index.js +2 -0
- package/dist/puzzles/megaminx/scrambler.d.ts +4 -0
- package/dist/puzzles/megaminx/scrambler.d.ts.map +1 -0
- package/dist/puzzles/megaminx/scrambler.js +56 -0
- package/dist/puzzles/megaminx/types.d.ts +6 -0
- package/dist/puzzles/megaminx/types.d.ts.map +1 -0
- package/dist/puzzles/megaminx/types.js +4 -0
- package/dist/puzzles/pyraminx/index.d.ts +9 -0
- package/dist/puzzles/pyraminx/index.d.ts.map +1 -0
- package/dist/puzzles/pyraminx/index.js +7 -0
- package/dist/puzzles/pyraminx/moves.d.ts +9 -0
- package/dist/puzzles/pyraminx/moves.d.ts.map +1 -0
- package/dist/puzzles/pyraminx/moves.js +117 -0
- package/dist/puzzles/pyraminx/random-state.d.ts +3 -0
- package/dist/puzzles/pyraminx/random-state.d.ts.map +1 -0
- package/dist/puzzles/pyraminx/random-state.js +53 -0
- package/dist/puzzles/pyraminx/scrambler.d.ts +6 -0
- package/dist/puzzles/pyraminx/scrambler.d.ts.map +1 -0
- package/dist/puzzles/pyraminx/scrambler.js +56 -0
- package/dist/puzzles/pyraminx/solver.d.ts +10 -0
- package/dist/puzzles/pyraminx/solver.d.ts.map +1 -0
- package/dist/puzzles/pyraminx/solver.js +160 -0
- package/dist/puzzles/pyraminx/state.d.ts +6 -0
- package/dist/puzzles/pyraminx/state.d.ts.map +1 -0
- package/dist/puzzles/pyraminx/state.js +32 -0
- package/dist/puzzles/pyraminx/types.d.ts +17 -0
- package/dist/puzzles/pyraminx/types.d.ts.map +1 -0
- package/dist/puzzles/pyraminx/types.js +7 -0
- package/dist/puzzles/pyraminx/validation.d.ts +8 -0
- package/dist/puzzles/pyraminx/validation.d.ts.map +1 -0
- package/dist/puzzles/pyraminx/validation.js +79 -0
- package/dist/random/index.d.ts +3 -0
- package/dist/random/index.d.ts.map +1 -0
- package/dist/random/index.js +1 -0
- package/dist/random/prng.d.ts +7 -0
- package/dist/random/prng.d.ts.map +1 -0
- package/dist/random/prng.js +60 -0
- package/dist-cjs/cli/index.js +12 -0
- package/dist-cjs/cli/run.js +142 -0
- package/dist-cjs/core/api.js +102 -0
- package/dist-cjs/core/errors.js +42 -0
- package/dist-cjs/core/index.js +19 -0
- package/dist-cjs/core/registry.js +39 -0
- package/dist-cjs/core/types.js +2 -0
- package/dist-cjs/index.js +19 -0
- package/dist-cjs/package.json +3 -0
- package/dist-cjs/puzzles/clock/index.js +6 -0
- package/dist-cjs/puzzles/clock/scrambler.js +54 -0
- package/dist-cjs/puzzles/cube2/facelets.js +58 -0
- package/dist-cjs/puzzles/cube2/index.js +67 -0
- package/dist-cjs/puzzles/cube2/moves.js +88 -0
- package/dist-cjs/puzzles/cube2/random-state.js +54 -0
- package/dist-cjs/puzzles/cube2/scrambler.js +58 -0
- package/dist-cjs/puzzles/cube2/solver/browser-loader.js +85 -0
- package/dist-cjs/puzzles/cube2/solver/generated/distances.bin +1 -0
- package/dist-cjs/puzzles/cube2/solver/generated/manifest.json +21 -0
- package/dist-cjs/puzzles/cube2/solver/generated/orientation-distances.bin +0 -0
- package/dist-cjs/puzzles/cube2/solver/generated/orientation-table.bin +0 -0
- package/dist-cjs/puzzles/cube2/solver/generated/permutation-distances.bin +0 -0
- package/dist-cjs/puzzles/cube2/solver/generated/permutation-table.bin +0 -0
- package/dist-cjs/puzzles/cube2/solver/generated-assets.js +61 -0
- package/dist-cjs/puzzles/cube2/solver/index.js +5 -0
- package/dist-cjs/puzzles/cube2/solver/node-loader.js +89 -0
- package/dist-cjs/puzzles/cube2/solver/search.js +53 -0
- package/dist-cjs/puzzles/cube2/solver/table-metadata.js +18 -0
- package/dist-cjs/puzzles/cube2/solver/tables.js +91 -0
- package/dist-cjs/puzzles/cube2/state.js +36 -0
- package/dist-cjs/puzzles/cube2/types.js +24 -0
- package/dist-cjs/puzzles/cube2/validation.js +78 -0
- package/dist-cjs/puzzles/cube3/facelets.js +94 -0
- package/dist-cjs/puzzles/cube3/index.js +68 -0
- package/dist-cjs/puzzles/cube3/moves.js +219 -0
- package/dist-cjs/puzzles/cube3/random-state.js +62 -0
- package/dist-cjs/puzzles/cube3/scrambler.js +63 -0
- package/dist-cjs/puzzles/cube3/solver/browser-loader.js +139 -0
- package/dist-cjs/puzzles/cube3/solver/coordinates.js +285 -0
- package/dist-cjs/puzzles/cube3/solver/generated/manifest.json +404 -0
- package/dist-cjs/puzzles/cube3/solver/generated/move-cornerOrientation.bin +0 -0
- package/dist-cjs/puzzles/cube3/solver/generated/move-cornerPermutation.bin +0 -0
- package/dist-cjs/puzzles/cube3/solver/generated/move-edgeOrientation.bin +0 -0
- package/dist-cjs/puzzles/cube3/solver/generated/move-slicePermutation.bin +0 -0
- package/dist-cjs/puzzles/cube3/solver/generated/move-udEdgePermutation.bin +0 -0
- package/dist-cjs/puzzles/cube3/solver/generated/move-udSlice.bin +0 -0
- package/dist-cjs/puzzles/cube3/solver/generated/pruning-cornerOrientation.bin +1 -0
- package/dist-cjs/puzzles/cube3/solver/generated/pruning-cornerOrientationEdgeOrientation.bin +1 -0
- package/dist-cjs/puzzles/cube3/solver/generated/pruning-cornerPermutation.bin +1 -0
- package/dist-cjs/puzzles/cube3/solver/generated/pruning-cornerPermutationSlicePermutation.bin +1 -0
- package/dist-cjs/puzzles/cube3/solver/generated/pruning-edgeOrientation.bin +1 -0
- package/dist-cjs/puzzles/cube3/solver/generated/pruning-slicePermutation.bin +1 -0
- package/dist-cjs/puzzles/cube3/solver/generated/pruning-udEdgePermutation.bin +1 -0
- package/dist-cjs/puzzles/cube3/solver/generated/pruning-udEdgePermutationSlicePermutation.bin +1 -0
- package/dist-cjs/puzzles/cube3/solver/generated/pruning-udSlice.bin +0 -0
- package/dist-cjs/puzzles/cube3/solver/generated-assets.js +98 -0
- package/dist-cjs/puzzles/cube3/solver/index.js +49 -0
- package/dist-cjs/puzzles/cube3/solver/node-loader.js +126 -0
- package/dist-cjs/puzzles/cube3/solver/phase1.js +158 -0
- package/dist-cjs/puzzles/cube3/solver/phase2.js +279 -0
- package/dist-cjs/puzzles/cube3/solver/search-utils.js +49 -0
- package/dist-cjs/puzzles/cube3/solver/table-metadata.js +24 -0
- package/dist-cjs/puzzles/cube3/solver/tables.js +216 -0
- package/dist-cjs/puzzles/cube3/state.js +46 -0
- package/dist-cjs/puzzles/cube3/subset-state.js +166 -0
- package/dist-cjs/puzzles/cube3/types.js +25 -0
- package/dist-cjs/puzzles/cube3/validation.js +89 -0
- package/dist-cjs/puzzles/cube4/facelets.js +140 -0
- package/dist-cjs/puzzles/cube4/index.js +45 -0
- package/dist-cjs/puzzles/cube4/moves.js +251 -0
- package/dist-cjs/puzzles/cube4/scrambler.js +135 -0
- package/dist-cjs/puzzles/cube4/state.js +92 -0
- package/dist-cjs/puzzles/cube4/types.js +65 -0
- package/dist-cjs/puzzles/cube5x5/index.js +9 -0
- package/dist-cjs/puzzles/cube5x5/scrambler.js +97 -0
- package/dist-cjs/puzzles/cube5x5/types.js +7 -0
- package/dist-cjs/puzzles/cube6x6/index.js +9 -0
- package/dist-cjs/puzzles/cube6x6/scrambler.js +109 -0
- package/dist-cjs/puzzles/cube6x6/types.js +11 -0
- package/dist-cjs/puzzles/cube7x7/index.js +9 -0
- package/dist-cjs/puzzles/cube7x7/scrambler.js +97 -0
- package/dist-cjs/puzzles/cube7x7/types.js +11 -0
- package/dist-cjs/puzzles/index.js +64 -0
- package/dist-cjs/puzzles/megaminx/index.js +11 -0
- package/dist-cjs/puzzles/megaminx/scrambler.js +60 -0
- package/dist-cjs/puzzles/megaminx/types.js +7 -0
- package/dist-cjs/puzzles/pyraminx/index.js +30 -0
- package/dist-cjs/puzzles/pyraminx/moves.js +126 -0
- package/dist-cjs/puzzles/pyraminx/random-state.js +56 -0
- package/dist-cjs/puzzles/pyraminx/scrambler.js +60 -0
- package/dist-cjs/puzzles/pyraminx/solver.js +170 -0
- package/dist-cjs/puzzles/pyraminx/state.js +38 -0
- package/dist-cjs/puzzles/pyraminx/types.js +10 -0
- package/dist-cjs/puzzles/pyraminx/validation.js +84 -0
- package/dist-cjs/random/index.js +5 -0
- package/dist-cjs/random/prng.js +63 -0
- package/docs/cubingcenter-integration.md +69 -0
- package/docs/development.md +44 -0
- package/docs/facelets.md +64 -0
- package/docs/getting-started.md +73 -0
- package/examples/cli-json.md +30 -0
- package/examples/commonjs.cjs +11 -0
- package/examples/esm.mjs +9 -0
- package/examples/timer-preview.mjs +29 -0
- package/package.json +53 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
function getHardwareConcurrency() {
|
|
2
|
+
if (typeof navigator !== "undefined" && navigator.hardwareConcurrency) {
|
|
3
|
+
return navigator.hardwareConcurrency;
|
|
4
|
+
}
|
|
5
|
+
return 4;
|
|
6
|
+
}
|
|
7
|
+
function resolveWorkerUrl() {
|
|
8
|
+
// Standard ESM pattern: bundlers (Vite, Webpack 5, Parcel) detect
|
|
9
|
+
// new Worker(new URL('./file.js', import.meta.url)) and handle the worker
|
|
10
|
+
// as a separate chunk automatically.
|
|
11
|
+
return new URL("./browser-worker.js", import.meta.url).href;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Web Worker pool for browser environments.
|
|
15
|
+
*
|
|
16
|
+
* Each worker loads solver tables independently (~10 MB per worker).
|
|
17
|
+
* Best suited for batch generation on client devices with 2+ cores.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```ts
|
|
21
|
+
* const pool = new Cube3BrowserWorkerPool();
|
|
22
|
+
* const results = await pool.generateBatch(50, (i) => `seed-${i}`);
|
|
23
|
+
* pool.terminate();
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export class Cube3BrowserWorkerPool {
|
|
27
|
+
workers = [];
|
|
28
|
+
available = [];
|
|
29
|
+
pending = new Map();
|
|
30
|
+
queue = [];
|
|
31
|
+
nextId = 0;
|
|
32
|
+
terminated = false;
|
|
33
|
+
constructor(size = Math.max(1, Math.min(8, getHardwareConcurrency()))) {
|
|
34
|
+
if (typeof Worker === "undefined") {
|
|
35
|
+
throw new Error("Web Workers are not available in this environment. " +
|
|
36
|
+
"Use generateScramble() directly for single-threaded generation.");
|
|
37
|
+
}
|
|
38
|
+
const workerUrl = resolveWorkerUrl();
|
|
39
|
+
for (let i = 0; i < size; i++) {
|
|
40
|
+
const worker = new Worker(workerUrl, { type: "module" });
|
|
41
|
+
worker.onmessage = (event) => {
|
|
42
|
+
this.handleResponse(worker, event.data);
|
|
43
|
+
};
|
|
44
|
+
worker.onerror = (error) => {
|
|
45
|
+
this.handleError(error);
|
|
46
|
+
};
|
|
47
|
+
this.workers.push(worker);
|
|
48
|
+
this.available.push(worker);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
generate(options = {}) {
|
|
52
|
+
if (this.terminated) {
|
|
53
|
+
return Promise.reject(new Error("Worker pool has been terminated."));
|
|
54
|
+
}
|
|
55
|
+
const id = this.nextId++;
|
|
56
|
+
const task = {
|
|
57
|
+
id,
|
|
58
|
+
...(options.seed !== undefined ? { seed: options.seed } : {}),
|
|
59
|
+
...(options.skipValidation !== undefined
|
|
60
|
+
? { skipValidation: options.skipValidation }
|
|
61
|
+
: {})
|
|
62
|
+
};
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
this.pending.set(id, { resolve, reject });
|
|
65
|
+
if (this.available.length > 0) {
|
|
66
|
+
const worker = this.available.pop();
|
|
67
|
+
worker.postMessage(task);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.queue.push(task);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
generateBatch(count, deriveSeed) {
|
|
75
|
+
const promises = Array.from({ length: count }, (_, index) => {
|
|
76
|
+
const seed = deriveSeed(index);
|
|
77
|
+
return this.generate(seed !== undefined ? { seed } : {});
|
|
78
|
+
});
|
|
79
|
+
return Promise.all(promises);
|
|
80
|
+
}
|
|
81
|
+
terminate() {
|
|
82
|
+
this.terminated = true;
|
|
83
|
+
this.queue = [];
|
|
84
|
+
this.pending.forEach(({ reject }) => {
|
|
85
|
+
reject(new Error("Worker pool terminated."));
|
|
86
|
+
});
|
|
87
|
+
this.pending.clear();
|
|
88
|
+
for (const worker of this.workers) {
|
|
89
|
+
worker.terminate();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
handleResponse(worker, response) {
|
|
93
|
+
const pending = this.pending.get(response.id);
|
|
94
|
+
if (!pending)
|
|
95
|
+
return;
|
|
96
|
+
this.pending.delete(response.id);
|
|
97
|
+
if (response.error) {
|
|
98
|
+
pending.reject(new Error(response.error));
|
|
99
|
+
}
|
|
100
|
+
else if (response.result) {
|
|
101
|
+
pending.resolve(response.result);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
pending.reject(new Error("Worker returned empty response."));
|
|
105
|
+
}
|
|
106
|
+
if (this.queue.length > 0) {
|
|
107
|
+
const nextTask = this.queue.shift();
|
|
108
|
+
worker.postMessage(nextTask);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
this.available.push(worker);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
handleError(error) {
|
|
115
|
+
this.pending.forEach(({ reject }) => reject(error.error));
|
|
116
|
+
this.pending.clear();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-worker.d.ts","sourceRoot":"","sources":["../../../../src/puzzles/cube3/solver/browser-worker.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/// <reference lib="webworker" />
|
|
2
|
+
import { generateRandomCube3State } from "../random-state.js";
|
|
3
|
+
import { createSolvedCube3State, cube3StatesEqual, isSolvedCube3State } from "../state.js";
|
|
4
|
+
import { applyCube3Algorithm, formatCube3Algorithm, invertCube3Algorithm } from "../moves.js";
|
|
5
|
+
import { formatCube3Facelets, toCube3Facelets } from "../facelets.js";
|
|
6
|
+
import { solveCube3State } from "./index.js";
|
|
7
|
+
import { loadBrowserTables } from "./browser-loader.js";
|
|
8
|
+
let tablesLoaded = false;
|
|
9
|
+
async function ensureTables() {
|
|
10
|
+
if (tablesLoaded)
|
|
11
|
+
return;
|
|
12
|
+
await loadBrowserTables();
|
|
13
|
+
tablesLoaded = true;
|
|
14
|
+
}
|
|
15
|
+
async function generate(task) {
|
|
16
|
+
await ensureTables();
|
|
17
|
+
const options = {
|
|
18
|
+
...(task.seed !== undefined ? { seed: task.seed } : {}),
|
|
19
|
+
...(task.skipValidation !== undefined ? { skipValidation: task.skipValidation } : {})
|
|
20
|
+
};
|
|
21
|
+
const state = generateRandomCube3State(options);
|
|
22
|
+
const solution = await solveCube3State(state);
|
|
23
|
+
const scrambleMoves = invertCube3Algorithm(solution.moves);
|
|
24
|
+
if (!options.skipValidation) {
|
|
25
|
+
const scrambledState = applyCube3Algorithm(createSolvedCube3State(), scrambleMoves);
|
|
26
|
+
if (!cube3StatesEqual(scrambledState, state)) {
|
|
27
|
+
throw new Error("Generated 3x3 scramble does not reproduce the target random state.");
|
|
28
|
+
}
|
|
29
|
+
if (!isSolvedCube3State(solution.state)) {
|
|
30
|
+
throw new Error("Generated 3x3 solution does not solve the target random state.");
|
|
31
|
+
}
|
|
32
|
+
if (scrambleMoves.length < 2) {
|
|
33
|
+
throw new Error("Generated 3x3 scramble is too short.");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const facelets = toCube3Facelets(state);
|
|
37
|
+
const result = {
|
|
38
|
+
eventId: "333",
|
|
39
|
+
scramble: formatCube3Algorithm(scrambleMoves),
|
|
40
|
+
moves: scrambleMoves,
|
|
41
|
+
quality: "random-state",
|
|
42
|
+
generator: "cube3-two-phase",
|
|
43
|
+
metadata: {
|
|
44
|
+
state,
|
|
45
|
+
facelets,
|
|
46
|
+
faceletString: formatCube3Facelets(facelets),
|
|
47
|
+
solutionMoves: solution.moves,
|
|
48
|
+
solutionDepth: solution.depth,
|
|
49
|
+
phase1Depth: solution.phase1.depth,
|
|
50
|
+
phase2Depth: solution.phase2.depth,
|
|
51
|
+
visitedNodes: solution.visitedNodes
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
if (options.seed !== undefined) {
|
|
55
|
+
result.seed = options.seed;
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
self.onmessage = async (event) => {
|
|
60
|
+
const task = event.data;
|
|
61
|
+
try {
|
|
62
|
+
const result = await generate(task);
|
|
63
|
+
const response = { id: task.id, result };
|
|
64
|
+
self.postMessage(response);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
68
|
+
const response = { id: task.id, error: message };
|
|
69
|
+
self.postMessage(response);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Cube3Move, Cube3State } from "../types.js";
|
|
2
|
+
export declare const CUBE3_COORDINATE_RANGES: {
|
|
3
|
+
readonly cornerOrientation: 2187;
|
|
4
|
+
readonly edgeOrientation: 2048;
|
|
5
|
+
readonly udSlice: 495;
|
|
6
|
+
readonly cornerPermutation: 40320;
|
|
7
|
+
readonly udEdgePermutation: 40320;
|
|
8
|
+
readonly slicePermutation: 24;
|
|
9
|
+
};
|
|
10
|
+
export interface Cube3CoordinateState {
|
|
11
|
+
cornerOrientation: number;
|
|
12
|
+
edgeOrientation: number;
|
|
13
|
+
udSlice: number;
|
|
14
|
+
cornerPermutation: number;
|
|
15
|
+
udEdgePermutation: number;
|
|
16
|
+
slicePermutation: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function encodeCube3Coordinates(state: Cube3State): Cube3CoordinateState;
|
|
19
|
+
export declare function encodeCube3Coordinate(coordinateName: keyof Cube3CoordinateState, state: Cube3State): number;
|
|
20
|
+
export declare function encodeCornerOrientation(state: Cube3State): number;
|
|
21
|
+
export declare function decodeCornerOrientation(coordinate: number): number[];
|
|
22
|
+
export declare function encodeEdgeOrientation(state: Cube3State): number;
|
|
23
|
+
export declare function decodeEdgeOrientation(coordinate: number): number[];
|
|
24
|
+
export declare function encodeUdSlice(state: Cube3State): number;
|
|
25
|
+
export declare function decodeUdSlice(coordinate: number): number[];
|
|
26
|
+
export declare function encodeUdEdgePermutation(state: Cube3State): number;
|
|
27
|
+
export declare function decodeUdEdgePermutation(coordinate: number): number[];
|
|
28
|
+
export declare function encodeSlicePermutation(state: Cube3State): number;
|
|
29
|
+
export declare function decodeSlicePermutation(coordinate: number): number[];
|
|
30
|
+
export declare function decodePermutation(coordinate: number, length: number): number[];
|
|
31
|
+
export declare function encodePermutation(permutation: readonly number[]): number;
|
|
32
|
+
export declare function createRepresentativeStateForCoordinate(coordinateName: keyof Cube3CoordinateState, coordinate: number): Cube3State;
|
|
33
|
+
export declare function moveCoordinate(coordinateName: keyof Cube3CoordinateState, coordinate: number, move: Cube3Move): number;
|
|
34
|
+
//# sourceMappingURL=coordinates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinates.d.ts","sourceRoot":"","sources":["../../../../src/puzzles/cube3/solver/coordinates.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,uBAAuB;;;;;;;CAO1B,CAAC;AAEX,MAAM,WAAW,oBAAoB;IACnC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAUD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,oBAAoB,CAS9E;AAED,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,MAAM,oBAAoB,EAC1C,KAAK,EAAE,UAAU,GAChB,MAAM,CAsBR;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAWjE;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBpE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAW/D;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBlE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAoBvD;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAG1D;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CASjE;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAWhE;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAEnE;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAe9E;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAcxE;AAED,wBAAgB,sCAAsC,CACpD,cAAc,EAAE,MAAM,oBAAoB,EAC1C,UAAU,EAAE,MAAM,GACjB,UAAU,CAiDZ;AAED,wBAAgB,cAAc,CAC5B,cAAc,EAAE,MAAM,oBAAoB,EAC1C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,SAAS,GACd,MAAM,CAIR"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { applyCube3Move } from "../moves.js";
|
|
2
|
+
import { createSolvedCube3State } from "../state.js";
|
|
3
|
+
import { CORNER_COUNT, EDGE_COUNT } from "../types.js";
|
|
4
|
+
export const CUBE3_COORDINATE_RANGES = {
|
|
5
|
+
cornerOrientation: 2187,
|
|
6
|
+
edgeOrientation: 2048,
|
|
7
|
+
udSlice: 495,
|
|
8
|
+
cornerPermutation: 40320,
|
|
9
|
+
udEdgePermutation: 40320,
|
|
10
|
+
slicePermutation: 24
|
|
11
|
+
};
|
|
12
|
+
const SLICE_EDGE_START = 8;
|
|
13
|
+
const UD_EDGE_COUNT = 8;
|
|
14
|
+
const SLICE_EDGE_COUNT = 4;
|
|
15
|
+
const UD_SLICE_COMBINATIONS = createCombinations(EDGE_COUNT, SLICE_EDGE_COUNT);
|
|
16
|
+
const UD_SLICE_INDEX_BY_KEY = new Map(UD_SLICE_COMBINATIONS.map((combination, index) => [combination.join(","), index]));
|
|
17
|
+
export function encodeCube3Coordinates(state) {
|
|
18
|
+
return {
|
|
19
|
+
cornerOrientation: encodeCornerOrientation(state),
|
|
20
|
+
edgeOrientation: encodeEdgeOrientation(state),
|
|
21
|
+
udSlice: encodeUdSlice(state),
|
|
22
|
+
cornerPermutation: encodePermutation(state.corners.permutation),
|
|
23
|
+
udEdgePermutation: encodeUdEdgePermutation(state),
|
|
24
|
+
slicePermutation: encodeSlicePermutation(state)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function encodeCube3Coordinate(coordinateName, state) {
|
|
28
|
+
if (coordinateName === "cornerOrientation") {
|
|
29
|
+
return encodeCornerOrientation(state);
|
|
30
|
+
}
|
|
31
|
+
if (coordinateName === "edgeOrientation") {
|
|
32
|
+
return encodeEdgeOrientation(state);
|
|
33
|
+
}
|
|
34
|
+
if (coordinateName === "udSlice") {
|
|
35
|
+
return encodeUdSlice(state);
|
|
36
|
+
}
|
|
37
|
+
if (coordinateName === "cornerPermutation") {
|
|
38
|
+
return encodePermutation(state.corners.permutation);
|
|
39
|
+
}
|
|
40
|
+
if (coordinateName === "udEdgePermutation") {
|
|
41
|
+
return encodeUdEdgePermutation(state);
|
|
42
|
+
}
|
|
43
|
+
return encodeSlicePermutation(state);
|
|
44
|
+
}
|
|
45
|
+
export function encodeCornerOrientation(state) {
|
|
46
|
+
assertLength(state.corners.orientation, CORNER_COUNT, "corner orientation");
|
|
47
|
+
let coordinate = 0;
|
|
48
|
+
for (let index = 0; index < CORNER_COUNT - 1; index += 1) {
|
|
49
|
+
const orientation = state.corners.orientation[index];
|
|
50
|
+
assertRange(orientation, 0, 2, "corner orientation");
|
|
51
|
+
coordinate = coordinate * 3 + orientation;
|
|
52
|
+
}
|
|
53
|
+
return coordinate;
|
|
54
|
+
}
|
|
55
|
+
export function decodeCornerOrientation(coordinate) {
|
|
56
|
+
assertCoordinate(coordinate, CUBE3_COORDINATE_RANGES.cornerOrientation, "corner orientation");
|
|
57
|
+
const orientations = Array(CORNER_COUNT).fill(0);
|
|
58
|
+
let remaining = coordinate;
|
|
59
|
+
let total = 0;
|
|
60
|
+
for (let index = CORNER_COUNT - 2; index >= 0; index -= 1) {
|
|
61
|
+
const orientation = remaining % 3;
|
|
62
|
+
orientations[index] = orientation;
|
|
63
|
+
total += orientation;
|
|
64
|
+
remaining = Math.floor(remaining / 3);
|
|
65
|
+
}
|
|
66
|
+
orientations[CORNER_COUNT - 1] = (3 - (total % 3)) % 3;
|
|
67
|
+
return orientations;
|
|
68
|
+
}
|
|
69
|
+
export function encodeEdgeOrientation(state) {
|
|
70
|
+
assertLength(state.edges.orientation, EDGE_COUNT, "edge orientation");
|
|
71
|
+
let coordinate = 0;
|
|
72
|
+
for (let index = 0; index < EDGE_COUNT - 1; index += 1) {
|
|
73
|
+
const orientation = state.edges.orientation[index];
|
|
74
|
+
assertRange(orientation, 0, 1, "edge orientation");
|
|
75
|
+
coordinate = coordinate * 2 + orientation;
|
|
76
|
+
}
|
|
77
|
+
return coordinate;
|
|
78
|
+
}
|
|
79
|
+
export function decodeEdgeOrientation(coordinate) {
|
|
80
|
+
assertCoordinate(coordinate, CUBE3_COORDINATE_RANGES.edgeOrientation, "edge orientation");
|
|
81
|
+
const orientations = Array(EDGE_COUNT).fill(0);
|
|
82
|
+
let remaining = coordinate;
|
|
83
|
+
let total = 0;
|
|
84
|
+
for (let index = EDGE_COUNT - 2; index >= 0; index -= 1) {
|
|
85
|
+
const orientation = remaining % 2;
|
|
86
|
+
orientations[index] = orientation;
|
|
87
|
+
total += orientation;
|
|
88
|
+
remaining = Math.floor(remaining / 2);
|
|
89
|
+
}
|
|
90
|
+
orientations[EDGE_COUNT - 1] = total % 2;
|
|
91
|
+
return orientations;
|
|
92
|
+
}
|
|
93
|
+
export function encodeUdSlice(state) {
|
|
94
|
+
assertLength(state.edges.permutation, EDGE_COUNT, "edge permutation");
|
|
95
|
+
const positions = state.edges.permutation
|
|
96
|
+
.map((piece, position) => ({ piece, position }))
|
|
97
|
+
.filter(({ piece }) => piece >= SLICE_EDGE_START)
|
|
98
|
+
.map(({ position }) => position);
|
|
99
|
+
if (positions.length !== SLICE_EDGE_COUNT) {
|
|
100
|
+
throw new RangeError("UD slice coordinate requires exactly four slice edges.");
|
|
101
|
+
}
|
|
102
|
+
const key = positions.join(",");
|
|
103
|
+
const coordinate = UD_SLICE_INDEX_BY_KEY.get(key);
|
|
104
|
+
if (coordinate === undefined) {
|
|
105
|
+
throw new RangeError(`Invalid UD slice positions: ${key}`);
|
|
106
|
+
}
|
|
107
|
+
return coordinate;
|
|
108
|
+
}
|
|
109
|
+
export function decodeUdSlice(coordinate) {
|
|
110
|
+
assertCoordinate(coordinate, CUBE3_COORDINATE_RANGES.udSlice, "UD slice");
|
|
111
|
+
return [...UD_SLICE_COMBINATIONS[coordinate]];
|
|
112
|
+
}
|
|
113
|
+
export function encodeUdEdgePermutation(state) {
|
|
114
|
+
assertLength(state.edges.permutation, EDGE_COUNT, "edge permutation");
|
|
115
|
+
const permutation = state.edges.permutation.slice(0, UD_EDGE_COUNT);
|
|
116
|
+
if (permutation.some((piece) => piece < 0 || piece >= UD_EDGE_COUNT)) {
|
|
117
|
+
throw new RangeError("UD edge permutation requires UD edges in UD edge positions.");
|
|
118
|
+
}
|
|
119
|
+
return encodePermutation(permutation);
|
|
120
|
+
}
|
|
121
|
+
export function decodeUdEdgePermutation(coordinate) {
|
|
122
|
+
return decodePermutation(coordinate, UD_EDGE_COUNT);
|
|
123
|
+
}
|
|
124
|
+
export function encodeSlicePermutation(state) {
|
|
125
|
+
assertLength(state.edges.permutation, EDGE_COUNT, "edge permutation");
|
|
126
|
+
const permutation = state.edges.permutation
|
|
127
|
+
.slice(SLICE_EDGE_START)
|
|
128
|
+
.map((piece) => piece - SLICE_EDGE_START);
|
|
129
|
+
if (permutation.some((piece) => piece < 0 || piece >= SLICE_EDGE_COUNT)) {
|
|
130
|
+
throw new RangeError("Slice permutation requires slice edges in slice positions.");
|
|
131
|
+
}
|
|
132
|
+
return encodePermutation(permutation);
|
|
133
|
+
}
|
|
134
|
+
export function decodeSlicePermutation(coordinate) {
|
|
135
|
+
return decodePermutation(coordinate, SLICE_EDGE_COUNT).map((piece) => piece + SLICE_EDGE_START);
|
|
136
|
+
}
|
|
137
|
+
export function decodePermutation(coordinate, length) {
|
|
138
|
+
assertCoordinate(coordinate, factorial(length), `permutation length ${length}`);
|
|
139
|
+
const available = Array.from({ length }, (_, index) => index);
|
|
140
|
+
const permutation = [];
|
|
141
|
+
let remaining = coordinate;
|
|
142
|
+
for (let index = length; index > 0; index -= 1) {
|
|
143
|
+
const placeValue = factorial(index - 1);
|
|
144
|
+
const selected = Math.floor(remaining / placeValue);
|
|
145
|
+
permutation.push(available.splice(selected, 1)[0]);
|
|
146
|
+
remaining %= placeValue;
|
|
147
|
+
}
|
|
148
|
+
return permutation;
|
|
149
|
+
}
|
|
150
|
+
export function encodePermutation(permutation) {
|
|
151
|
+
validatePermutation(permutation);
|
|
152
|
+
const available = Array.from({ length: permutation.length }, (_, index) => index);
|
|
153
|
+
let coordinate = 0;
|
|
154
|
+
for (let index = 0; index < permutation.length; index += 1) {
|
|
155
|
+
const value = permutation[index];
|
|
156
|
+
const selected = available.indexOf(value);
|
|
157
|
+
coordinate += selected * factorial(permutation.length - index - 1);
|
|
158
|
+
available.splice(selected, 1);
|
|
159
|
+
}
|
|
160
|
+
return coordinate;
|
|
161
|
+
}
|
|
162
|
+
export function createRepresentativeStateForCoordinate(coordinateName, coordinate) {
|
|
163
|
+
const state = createSolvedCube3State();
|
|
164
|
+
if (coordinateName === "cornerOrientation") {
|
|
165
|
+
state.corners.orientation = decodeCornerOrientation(coordinate);
|
|
166
|
+
}
|
|
167
|
+
else if (coordinateName === "edgeOrientation") {
|
|
168
|
+
state.edges.orientation = decodeEdgeOrientation(coordinate);
|
|
169
|
+
}
|
|
170
|
+
else if (coordinateName === "udSlice") {
|
|
171
|
+
const slicePositions = new Set(decodeUdSlice(coordinate));
|
|
172
|
+
const edgePermutation = Array(EDGE_COUNT).fill(-1);
|
|
173
|
+
let udEdge = 0;
|
|
174
|
+
let sliceEdge = SLICE_EDGE_START;
|
|
175
|
+
for (let position = 0; position < EDGE_COUNT; position += 1) {
|
|
176
|
+
if (slicePositions.has(position)) {
|
|
177
|
+
edgePermutation[position] = sliceEdge;
|
|
178
|
+
sliceEdge += 1;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
edgePermutation[position] = udEdge;
|
|
182
|
+
udEdge += 1;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
state.edges.permutation = edgePermutation;
|
|
186
|
+
}
|
|
187
|
+
else if (coordinateName === "cornerPermutation") {
|
|
188
|
+
state.corners.permutation = decodePermutation(coordinate, CORNER_COUNT);
|
|
189
|
+
}
|
|
190
|
+
else if (coordinateName === "udEdgePermutation") {
|
|
191
|
+
state.edges.permutation = [
|
|
192
|
+
...decodeUdEdgePermutation(coordinate),
|
|
193
|
+
8,
|
|
194
|
+
9,
|
|
195
|
+
10,
|
|
196
|
+
11
|
|
197
|
+
];
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
state.edges.permutation = [
|
|
201
|
+
0,
|
|
202
|
+
1,
|
|
203
|
+
2,
|
|
204
|
+
3,
|
|
205
|
+
4,
|
|
206
|
+
5,
|
|
207
|
+
6,
|
|
208
|
+
7,
|
|
209
|
+
...decodeSlicePermutation(coordinate)
|
|
210
|
+
];
|
|
211
|
+
}
|
|
212
|
+
return state;
|
|
213
|
+
}
|
|
214
|
+
export function moveCoordinate(coordinateName, coordinate, move) {
|
|
215
|
+
const state = createRepresentativeStateForCoordinate(coordinateName, coordinate);
|
|
216
|
+
const moved = applyCube3Move(state, move);
|
|
217
|
+
return encodeCube3Coordinate(coordinateName, moved);
|
|
218
|
+
}
|
|
219
|
+
function createCombinations(size, selected) {
|
|
220
|
+
const combinations = [];
|
|
221
|
+
function visit(start, current) {
|
|
222
|
+
if (current.length === selected) {
|
|
223
|
+
combinations.push([...current]);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
for (let value = start; value <= size - (selected - current.length); value += 1) {
|
|
227
|
+
current.push(value);
|
|
228
|
+
visit(value + 1, current);
|
|
229
|
+
current.pop();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
visit(0, []);
|
|
233
|
+
return combinations;
|
|
234
|
+
}
|
|
235
|
+
function validatePermutation(permutation) {
|
|
236
|
+
const seen = new Set();
|
|
237
|
+
for (const value of permutation) {
|
|
238
|
+
assertRange(value, 0, permutation.length - 1, "permutation value");
|
|
239
|
+
if (seen.has(value)) {
|
|
240
|
+
throw new RangeError(`Permutation contains duplicate value: ${value}`);
|
|
241
|
+
}
|
|
242
|
+
seen.add(value);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function assertLength(values, expected, label) {
|
|
246
|
+
if (values.length !== expected) {
|
|
247
|
+
throw new RangeError(`${label} must contain ${expected} values.`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function assertRange(value, min, max, label) {
|
|
251
|
+
if (!Number.isInteger(value) || value < min || value > max) {
|
|
252
|
+
throw new RangeError(`${label} must be an integer between ${min} and ${max}. Received: ${value}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function assertCoordinate(value, range, label) {
|
|
256
|
+
if (!Number.isInteger(value) || value < 0 || value >= range) {
|
|
257
|
+
throw new RangeError(`${label} coordinate must be between 0 and ${range - 1}. Received: ${value}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function factorial(value) {
|
|
261
|
+
let result = 1;
|
|
262
|
+
for (let factor = 2; factor <= value; factor += 1) {
|
|
263
|
+
result *= factor;
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
}
|