@vscubing/cubing
Version:
A collection of JavaScript cubing libraries.
266 lines (261 loc) • 7.53 kB
JavaScript
import {
experimental3x3x3KPuzzle,
normalize3x3x3Orientation,
puzzleOrientation3x3x3Cache,
puzzleOrientation3x3x3Idx
} from "./chunk-5EP7MK62.js";
import {
KPattern
} from "./chunk-S7T73XHS.js";
// src/cubing/protocol/binary/orbit-indexing.ts
function identityPermutation(numElems) {
const arr = new Array(numElems);
for (let i = 0; i < numElems; i++) {
arr[i] = i;
}
return arr;
}
function orientationsToMask(radix, orientations) {
let val = 0;
for (const orientation of orientations) {
val *= radix;
val += orientation;
}
return val;
}
function maskToOrientations(radix, numElems, mask) {
const arr = [];
while (mask > 0) {
arr.push(mask % radix);
mask = Math.floor(mask / radix);
}
return new Array(numElems - arr.length).fill(0).concat(arr.reverse());
}
function permutationToLex(permutation) {
const n = permutation.length;
let lexicographicIdx = 0;
for (let i = 0; i < n - 1; i++) {
lexicographicIdx = lexicographicIdx * (n - i);
for (let j = i + 1; j < n; j++) {
if (permutation[i] > permutation[j]) {
lexicographicIdx += 1;
}
}
}
return lexicographicIdx;
}
function lexToPermutation(numPieces, lexicographicIdx) {
const permutation = new Array(numPieces);
permutation[numPieces - 1] = 0;
for (let i = numPieces - 2; i >= 0; i--) {
permutation[i] = lexicographicIdx % (numPieces - i);
lexicographicIdx = Math.floor(lexicographicIdx / (numPieces - i));
for (let j = i + 1; j < numPieces; j++) {
if (permutation[j] >= permutation[i]) {
permutation[j] = permutation[j] + 1;
}
}
}
return permutation;
}
// src/cubing/protocol/binary/binary3x3x3.ts
function reorientPuzzle(pattern, idxU, idxL) {
return pattern.applyTransformation(
puzzleOrientation3x3x3Cache()[idxU][idxL].invert()
);
}
var BIT_LENGTHS = [29, 12, 16, 13, 3, 2, 1, 12];
function arraySum(arr) {
let total = 0;
for (const entry of arr) {
total += entry;
}
return total;
}
function splitBinary(bitLengths, buffy) {
const u8buffy = new Uint8Array(buffy);
let at = 0;
let bits = 0;
let accum = 0;
const values = [];
for (const bitLength of bitLengths) {
while (bits < bitLength) {
accum = accum << 8 | u8buffy[at++];
bits += 8;
}
values.push(accum >> bits - bitLength & (1 << bitLength) - 1);
bits -= bitLength;
}
return values;
}
function concatBinary(bitLengths, values) {
const buffy = new Uint8Array(Math.ceil(arraySum(bitLengths) / 8));
let at = 0;
let bits = 0;
let accum = 0;
for (let i = 0; i < bitLengths.length; i++) {
accum = accum << bitLengths[i] | values[i];
bits += bitLengths[i];
while (bits >= 8) {
buffy[at++] = accum >> bits - 8;
bits -= 8;
}
}
if (bits > 0) {
buffy[at++] = accum << 8 - bits;
}
return buffy;
}
function supportsPuzzleOrientation(components) {
return components.poIdxU !== 7;
}
function hasFullMOData(centerOrientationModData) {
if (!centerOrientationModData) {
return 1;
}
for (let i = 0; i < 6; i++) {
if (centerOrientationModData[i] !== 0) {
return 0;
}
}
return 1;
}
function reid3x3x3ToBinaryComponents(pattern) {
const normedPattern = normalize3x3x3Orientation(pattern);
const epLex = permutationToLex(normedPattern.patternData["EDGES"].pieces);
const eoMask = orientationsToMask(
2,
normedPattern.patternData["EDGES"].orientation
);
const cpLex = permutationToLex(normedPattern.patternData["CORNERS"].pieces);
const coMask = orientationsToMask(
3,
normedPattern.patternData["CORNERS"].orientation
);
const [poIdxU, poIdxL] = puzzleOrientation3x3x3Idx(pattern);
const moSupport = hasFullMOData(
pattern.patternData["CENTERS"].orientationMod
);
const moMask = moSupport ? orientationsToMask(4, normedPattern.patternData["CENTERS"].orientation) : 0;
return {
epLex,
eoMask,
cpLex,
coMask,
poIdxU,
poIdxL,
moSupport,
moMask
};
}
function binaryComponentsToTwizzleBinary(components) {
const { epLex, eoMask, cpLex, coMask, poIdxU, poIdxL, moSupport, moMask } = components;
return concatBinary(BIT_LENGTHS, [
epLex,
eoMask,
cpLex,
coMask,
poIdxU,
poIdxL,
moSupport,
moMask
]);
}
function reid3x3x3ToTwizzleBinary(pattern) {
const components = reid3x3x3ToBinaryComponents(pattern);
return binaryComponentsToTwizzleBinary(components);
}
function twizzleBinaryToBinaryComponents(buffer) {
const [epLex, eoMask, cpLex, coMask, poIdxU, poIdxL, moSupport, moMask] = splitBinary(BIT_LENGTHS, buffer);
return {
epLex,
eoMask,
cpLex,
coMask,
poIdxU,
poIdxL,
moSupport,
moMask
};
}
function binaryComponentsToReid3x3x3(components) {
const patternData = {
EDGES: {
pieces: lexToPermutation(12, components.epLex),
orientation: maskToOrientations(2, 12, components.eoMask)
},
CORNERS: {
pieces: lexToPermutation(8, components.cpLex),
orientation: maskToOrientations(3, 8, components.coMask)
},
CENTERS: {
pieces: identityPermutation(6),
orientation: maskToOrientations(4, 6, components.moMask)
}
};
if (!components.moSupport) {
patternData.CENTERS.orientationMod = new Array(6).fill(1);
}
const normedPattern = new KPattern(experimental3x3x3KPuzzle, patternData);
if (!supportsPuzzleOrientation(components)) {
return normedPattern;
}
return reorientPuzzle(normedPattern, components.poIdxU, components.poIdxL);
}
function validateComponents(components) {
const errors = [];
if (components.epLex < 0 || components.epLex >= 479001600) {
errors.push(`epLex (${components.epLex}) out of range`);
}
if (components.cpLex < 0 || components.cpLex >= 40320) {
errors.push(`cpLex (${components.cpLex}) out of range`);
}
if (components.coMask < 0 || components.coMask >= 6561) {
errors.push(`coMask (${components.coMask}) out of range`);
}
if (components.poIdxU < 0 || components.poIdxU >= 6) {
if (supportsPuzzleOrientation(components)) {
errors.push(`poIdxU (${components.poIdxU}) out of range`);
}
}
if (components.eoMask < 0 || components.eoMask >= 4096) {
errors.push(`eoMask (${components.eoMask}) out of range`);
}
if (components.moMask < 0 || components.moMask >= 4096) {
errors.push(`moMask (${components.moMask}) out of range`);
}
if (components.poIdxL < 0 || components.poIdxL >= 4) {
errors.push(`poIdxL (${components.poIdxL}) out of range`);
}
if (components.moSupport < 0 || components.moSupport >= 2) {
errors.push(`moSupport (${components.moSupport}) out of range`);
}
return errors;
}
function twizzleBinaryToReid3x3x3(buffy) {
const components = twizzleBinaryToBinaryComponents(buffy);
const errors = validateComponents(components);
if (errors.length !== 0) {
throw new Error(`Invalid binary pattern components: ${errors.join(", ")}`);
}
return binaryComponentsToReid3x3x3(components);
}
// src/cubing/protocol/binary/hex.ts
function bufferToSpacedHex(buffer) {
return Array.prototype.map.call(
new Uint8Array(buffer),
(x) => `00${x.toString(16)}`.slice(-2)
).join(" ");
}
function spacedHexToBuffer(hex) {
return new Uint8Array(hex.split(" ").map((c) => parseInt(c, 16)));
}
export {
reid3x3x3ToTwizzleBinary,
twizzleBinaryToBinaryComponents,
binaryComponentsToReid3x3x3,
twizzleBinaryToReid3x3x3,
bufferToSpacedHex,
spacedHexToBuffer
};
//# sourceMappingURL=chunk-NQT6LUO4.js.map