scramby
Version:
Generates scrambles for twisty puzzles.
1,707 lines (1,595 loc) • 45.2 kB
JavaScript
/*
scramble_333.js
3x3x3 Solver / Scramble Generator in Javascript.
The core 3x3x3 code is from a min2phase solver by Shuang Chen.
Compiled to Javascript using GWT.
(There may be a lot of redundant code right now, but it's still really fast.)
*/
'use strict';
var Raphael;
if (typeof window !== 'undefined') {
Raphael = require('raphael');
}
function randInt(min, max) {
if (max === undefined) {
max = min;
min = 0;
}
if (typeof min !== 'number' || typeof max !== 'number') {
throw new TypeError('Expected all arguments to be numbers');
}
return Math.floor(Math.random() * (max - min) + min);
}
var _;
function noop() {}
function createArray(length1, length2) {
var result, i;
result = Array(length1);
for (i = 0; i < length1; result[i++] = Array(length2)) {}
return result;
}
function $clinit_CoordCube() {
$clinit_CoordCube = noop;
UDSliceMove = createArray(495, 18);
TwistMove = createArray(324, 18);
FlipMove = createArray(336, 18);
UDSliceConj = createArray(495, 8);
UDSliceTwistPrun = Array(160380);
UDSliceFlipPrun = Array(166320);
TwistFlipPrun = Array(870912);
Mid3Move = createArray(1320, 18);
Mid32MPerm = Array(24);
CParity = Array(346);
CPermMove = createArray(2768, 18);
EPermMove = createArray(2768, 10);
MPermMove = createArray(24, 10);
MPermConj = createArray(24, 16);
MCPermPrun = Array(66432);
MEPermPrun = Array(66432);
}
function initCParity() {
var i;
for (i = 0; i < 346; ++i) {
CParity[i] = 0;
}
for (i = 0; i < 2768; ++i) {
CParity[i >>> 3] = CParity[i >>> 3] | get8Parity(CPermS2R[i]) << (i & 7);
}
}
function initCPermMove() {
var c, d, i, j;
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 2768; ++i) {
set8Perm(c.cp, CPermS2R[i]);
for (j = 0; j < 18; ++j) {
CornMult(c, moveCube[j], d);
CPermMove[i][j] = $getCPermSym(d);
}
}
}
function initEPermMove() {
var c, d, i, j;
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 2768; ++i) {
set8Perm(c.ep, EPermS2R[i]);
for (j = 0; j < 10; ++j) {
EdgeMult(c, moveCube[ud2std[j]], d);
EPermMove[i][j] = $getEPermSym(d);
}
}
}
function initFlipMove() {
var c, d, i, j;
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 336; ++i) {
$setFlip(c, FlipS2R[i]);
for (j = 0; j < 18; ++j) {
EdgeMult(c, moveCube[j], d);
FlipMove[i][j] = $getFlipSym(d);
}
}
}
function initMCEPermPrun(callback) {
var SymState, c, check, corn, cornx, d, depth, done, edge, edgex, i, idx, idxx, inv, j, m_0, mid, midx, select, sym, symx;
c = new CubieCube_0();
d = new CubieCube_0();
depth = 0;
done = 1;
SymState = Array(2768);
for (i = 0; i < 2768; ++i) {
SymState[i] = 0;
set8Perm(c.ep, EPermS2R[i]);
for (j = 1; j < 16; ++j) {
EdgeMult(CubeSym[SymInv[j]], c, temp_0);
EdgeMult(temp_0, CubeSym[j], d);
binarySearch(EPermS2R, get8Perm(d.ep)) != 65535 && (SymState[i] = SymState[i] | 1 << j);
}
}
for (i = 0; i < 66432; ++i) {
MEPermPrun[i] = -1;
}
MEPermPrun[0] = 0;
while (done < 66432) {
inv = depth > 7;
select = inv ? -1 : depth;
check = inv ? depth : -1;
++depth;
for (i = 0; i < 66432; ++i) {
if (MEPermPrun[i] === select) {
mid = i % 24;
edge = ~~(i / 24);
for (m_0 = 0; m_0 < 10; ++m_0) {
edgex = EPermMove[edge][m_0];
symx = edgex & 15;
midx = MPermConj[MPermMove[mid][m_0]][symx];
edgex >>>= 4;
idx = edgex * 24 + midx;
if (MEPermPrun[idx] === check) {
++done;
if (inv) {
MEPermPrun[i] = depth;
break;
} else {
MEPermPrun[idx] = depth;
sym = SymState[edgex];
if (sym != 0) {
for (j = 1; j < 16; ++j) {
sym = sym >> 1;
if ((sym & 1) === 1) {
idxx = edgex * 24 + MPermConj[midx][j];
if (MEPermPrun[idxx] === -1) {
MEPermPrun[idxx] = depth;
++done;
}
}
}
}
}
}
}
}
}
if (done / 66432 > 0.01) {
callback('MEPermPrun: ' + Math.floor(done * 100 / 66432) + '% (' + done + '/66432)');
}
}
for (i = 0; i < 66432; ++i) {
MCPermPrun[i] = -1;
}
MCPermPrun[0] = 0;
depth = 0;
done = 1;
while (done < 66432) {
inv = depth > 7;
select = inv ? -1 : depth;
check = inv ? depth : -1;
++depth;
for (i = 0; i < 66432; ++i) {
if (MCPermPrun[i] === select) {
mid = i % 24;
corn = ~~(i / 24);
for (m_0 = 0; m_0 < 10; ++m_0) {
cornx = CPermMove[corn][ud2std[m_0]];
symx = cornx & 15;
midx = MPermConj[MPermMove[mid][m_0]][symx];
cornx = cornx >>> 4;
idx = cornx * 24 + midx;
if (MCPermPrun[idx] === check) {
++done;
if (inv) {
MCPermPrun[i] = depth;
break;
} else {
MCPermPrun[idx] = depth;
sym = SymState[cornx];
if (sym != 0) {
for (j = 1; j < 16; ++j) {
sym = sym >> 1;
if ((sym & 1) === 1) {
idxx = cornx * 24 + MPermConj[midx][j ^ e2c[j]];
if (MCPermPrun[idxx] === -1) {
MCPermPrun[idxx] = depth;
++done;
}
}
}
}
}
}
}
}
}
if (done / 66432 > 0.01) {
callback('MCPermPrun: ' + Math.floor(done * 100 / 66432) + '% (' + done + '/66432)');
}
}
}
function initMPermConj() {
var c, d, i, j;
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 24; ++i) {
$setMPerm(c, i);
for (j = 0; j < 16; ++j) {
EdgeConjugate(c, SymInv[j], d);
MPermConj[i][j] = $getMPerm(d);
}
}
}
function initMPermMove() {
var c, d, i, j;
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 24; ++i) {
$setMPerm(c, i);
for (j = 0; j < 10; ++j) {
EdgeMult(c, moveCube[ud2std[j]], d);
MPermMove[i][j] = $getMPerm(d);
}
}
}
function initMid32MPerm() {
var c, i;
c = new CubieCube_0();
for (i = 0; i < 24; ++i) {
$setMPerm(c, i);
Mid32MPerm[$getMid3(c) % 24] = i;
}
}
function initMid3Move() {
var c, d, i, j;
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 1320; ++i) {
$setMid3(c, i);
for (j = 0; j < 18; ++j) {
EdgeMult(c, moveCube[j], d);
Mid3Move[i][j] = $getMid3(d);
}
}
}
function initTwistFlipSlicePrun(callback) {
var SymState, SymStateF, c, check, d, depth, done, flip, flipx, fsym, fsymx, fsymxx, i, idx, idxx, inv, j, k, m_0, select, slice, slicex, sym, symF, symx, tsymx, twist, twistx;
SymState = Array(324);
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 324; ++i) {
SymState[i] = 0;
$setTwist(c, TwistS2R[i]);
for (j = 0; j < 8; ++j) {
CornMultSym(CubeSym[SymInv[j << 1]], c, temp_0);
CornMultSym(temp_0, CubeSym[j << 1], d);
binarySearch(TwistS2R, $getTwist(d)) != 65535 && (SymState[i] = SymState[i] | 1 << j);
}
}
SymStateF = Array(336);
for (i = 0; i < 336; ++i) {
SymStateF[i] = 0;
$setFlip(c, FlipS2R[i]);
for (j = 0; j < 8; ++j) {
EdgeMult(CubeSym[SymInv[j << 1]], c, temp_0);
EdgeMult(temp_0, CubeSym[j << 1], d);
binarySearch(FlipS2R, $getFlip(d)) != 65535 && (SymStateF[i] = SymStateF[i] | 1 << j);
}
}
for (i = 0; i < 870912; ++i) {
TwistFlipPrun[i] = -1;
}
for (i = 0; i < 8; ++i) {
TwistFlipPrun[i] = 0;
}
depth = 0;
done = 8;
while (done < 870912) {
inv = depth > 6;
select = inv ? -1 : depth;
check = inv ? depth : -1;
++depth;
for (i = 0; i < 870912; ++i) {
if (TwistFlipPrun[i] != select) continue;
twist = ~~(i / 2688);
flip = i % 2688;
fsym = i & 7;
flip >>>= 3;
for (m_0 = 0; m_0 < 18; ++m_0) {
twistx = TwistMove[twist][m_0];
tsymx = twistx & 7;
twistx >>>= 3;
flipx = FlipMove[flip][Sym8Move[fsym][m_0]];
fsymx = Sym8MultInv[Sym8Mult[flipx & 7][fsym]][tsymx];
flipx >>>= 3;
idx = twistx * 2688 + (flipx << 3 | fsymx);
if (TwistFlipPrun[idx] === check) {
++done;
if (inv) {
TwistFlipPrun[i] = depth;
break;
} else {
TwistFlipPrun[idx] = depth;
sym = SymState[twistx];
symF = SymStateF[flipx];
if (sym != 1 || symF != 1) {
for (j = 0; j < 8; ++j, symF = symF >> 1) {
if ((symF & 1) === 1) {
fsymxx = Sym8MultInv[fsymx][j];
for (k = 0; k < 8; ++k) {
if ((sym & 1 << k) != 0) {
idxx = twistx * 2688 + (flipx << 3 | Sym8MultInv[fsymxx][k]);
if (TwistFlipPrun[idxx] === -1) {
TwistFlipPrun[idxx] = depth;
++done;
}
}
}
}
}
}
}
}
}
}
if (done / 870912 > 0.01) {
callback('TwistFlipPrun: ' + Math.floor(done * 100 / 870912) + '% (' + done + '/870912)');
}
}
for (i = 0; i < 160380; ++i) {
UDSliceTwistPrun[i] = -1;
}
UDSliceTwistPrun[0] = 0;
depth = 0;
done = 1;
while (done < 160380) {
inv = depth > 6;
select = inv ? -1 : depth;
check = inv ? depth : -1;
++depth;
for (i = 0; i < 160380; ++i) {
if (UDSliceTwistPrun[i] === select) {
slice = i % 495;
twist = ~~(i / 495);
for (m_0 = 0; m_0 < 18; ++m_0) {
twistx = TwistMove[twist][m_0];
symx = twistx & 7;
slicex = UDSliceConj[UDSliceMove[slice][m_0]][symx];
twistx >>>= 3;
idx = twistx * 495 + slicex;
if (UDSliceTwistPrun[idx] === check) {
++done;
if (inv) {
UDSliceTwistPrun[i] = depth;
break;
} else {
UDSliceTwistPrun[idx] = depth;
sym = SymState[twistx];
if (sym != 1) {
for (j = 1; j < 8; ++j) {
sym = sym >> 1;
if ((sym & 1) === 1) {
idxx = twistx * 495 + UDSliceConj[slicex][j];
if (UDSliceTwistPrun[idxx] === -1) {
UDSliceTwistPrun[idxx] = depth;
++done;
}
}
}
}
}
}
}
}
}
if (done / 160380 > 0.01) {
callback('UDSliceTwistPrun: ' + Math.floor(done * 100 / 160380) + '% (' + done + '/160380)');
}
}
for (i = 0; i < 166320; ++i) {
UDSliceFlipPrun[i] = -1;
}
UDSliceFlipPrun[0] = 0;
depth = 0;
done = 1;
while (done < 166320) {
inv = depth > 6;
select = inv ? -1 : depth;
check = inv ? depth : -1;
++depth;
for (i = 0; i < 166320; ++i) {
if (UDSliceFlipPrun[i] === select) {
slice = i % 495;
flip = ~~(i / 495);
for (m_0 = 0; m_0 < 18; ++m_0) {
flipx = FlipMove[flip][m_0];
symx = flipx & 7;
slicex = UDSliceConj[UDSliceMove[slice][m_0]][symx];
flipx >>>= 3;
idx = flipx * 495 + slicex;
if (UDSliceFlipPrun[idx] === check) {
++done;
if (inv) {
UDSliceFlipPrun[i] = depth;
break;
} else {
UDSliceFlipPrun[idx] = depth;
sym = SymStateF[flipx];
if (sym != 1) {
for (j = 1; j < 8; ++j) {
sym = sym >> 1;
if ((sym & 1) === 1) {
idxx = flipx * 495 + UDSliceConj[slicex][j];
if (UDSliceFlipPrun[idxx] === -1) {
UDSliceFlipPrun[idxx] = depth;
++done;
}
}
}
}
}
}
}
}
}
if (done / 166320 > 0.01) {
callback('UDSliceFlipPrun: ' + Math.floor(done * 100 / 166320) + '% (' + done + '/166320)');
}
}
}
function initTwistMove() {
var c, d, i, j;
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 324; ++i) {
$setTwist(c, TwistS2R[i]);
for (j = 0; j < 18; ++j) {
CornMult(c, moveCube[j], d);
TwistMove[i][j] = $getTwistSym(d);
}
}
}
function initUDSliceConj() {
var c, d, i, j;
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 495; ++i) {
$setUDSlice(c, i);
for (j = 0; j < 16; j = j + 2) {
EdgeConjugate(c, SymInv[j], d);
UDSliceConj[i][j >>> 1] = $getUDSlice(d);
}
}
}
function initUDSliceMove() {
var c, d, i, j;
c = new CubieCube_0();
d = new CubieCube_0();
for (i = 0; i < 495; ++i) {
$setUDSlice(c, i);
for (j = 0; j < 18; ++j) {
EdgeMult(c, moveCube[j], d);
UDSliceMove[i][j] = $getUDSlice(d);
}
}
}
var CParity, CPermMove, EPermMove, FlipMove, MCPermPrun, MEPermPrun, MPermConj, MPermMove, Mid32MPerm, Mid3Move, TwistFlipPrun, TwistMove, UDSliceConj, UDSliceFlipPrun, UDSliceMove, UDSliceTwistPrun;
function $clinit_CubieCube() {
$clinit_CubieCube = noop;
temp_0 = new CubieCube_0();
CubeSym = Array(16);
SymInv = Array(16);
SymMult = createArray(16, 16);
SymMove = createArray(16, 18);
Sym8Mult = createArray(8, 8);
Sym8Move = createArray(8, 18);
Sym8MultInv = createArray(8, 8);
SymMoveUD = createArray(16, 10);
FlipS2R = Array(336);
TwistS2R = Array(324);
CPermS2R = Array(2768);
EPermS2R = CPermS2R;
MtoEPerm = Array(40320);
merge = createArray(56, 56);
e2c = [0, 0, 0, 0, 1, 3, 1, 3, 1, 3, 1, 3, 0, 0, 0, 0];
urf1 = new CubieCube_2(2531, 1373, 67026819, 1877);
urf2 = new CubieCube_2(2089, 1906, 322752913, 255);
urfMove = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], [6, 7, 8, 0, 1, 2, 3, 4, 5, 15, 16, 17, 9, 10, 11, 12, 13, 14], [3, 4, 5, 6, 7, 8, 0, 1, 2, 12, 13, 14, 15, 16, 17, 9, 10, 11], [2, 1, 0, 5, 4, 3, 8, 7, 6, 11, 10, 9, 14, 13, 12, 17, 16, 15], [8, 7, 6, 2, 1, 0, 5, 4, 3, 17, 16, 15, 11, 10, 9, 14, 13, 12], [5, 4, 3, 8, 7, 6, 2, 1, 0, 14, 13, 12, 17, 16, 15, 11, 10, 9]];
initMove();
initSym();
}
function $$init(obj) {
obj.cp = [0, 1, 2, 3, 4, 5, 6, 7];
obj.co = [0, 0, 0, 0, 0, 0, 0, 0];
obj.ep = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
obj.eo = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
}
function $copy(obj, c) {
var i;
for (i = 0; i < 8; ++i) {
obj.cp[i] = c.cp[i];
obj.co[i] = c.co[i];
}
for (i = 0; i < 12; ++i) {
obj.ep[i] = c.ep[i];
obj.eo[i] = c.eo[i];
}
}
function $getCPermSym(obj) {
var idx, k;
if (EPermR2S != null) {
idx = EPermR2S[get8Perm(obj.cp)];
idx = idx ^ e2c[idx & 15];
return idx;
}
for (k = 0; k < 16; ++k) {
CornConjugate(obj, SymInv[k], obj.temps);
idx = binarySearch(CPermS2R, get8Perm(obj.temps.cp));
if (idx != 65535) {
return idx << 4 | k;
}
}
return 0;
}
function $getDRtoDL(obj) {
var i, idxA, idxB, mask, r, t;
idxA = 0;
idxB = 0;
mask = 0;
r = 3;
for (i = 11; i >= 0; --i) {
if (4 <= obj.ep[i] && obj.ep[i] <= 6) {
idxA = idxA + Cnk[i][r--];
t = 1 << obj.ep[i];
idxB = idxB + bitCount(mask & t - 1) * fact[2 - r];
mask = mask | t;
}
}
return idxA * 6 + idxB;
}
function $getEPermSym(obj) {
var idx, k;
if (EPermR2S != null) {
return EPermR2S[get8Perm(obj.ep)];
}
for (k = 0; k < 16; ++k) {
EdgeConjugate(obj, SymInv[k], obj.temps);
idx = binarySearch(EPermS2R, get8Perm(obj.temps.ep));
if (idx != 65535) {
return idx << 4 | k;
}
}
return 0;
}
function $getEdgePerm(obj) {
var i, idx, m_0, t;
m_0 = 1 << obj.ep[11];
idx = 0;
for (i = 10; i >= 0; --i) {
t = 1 << obj.ep[i];
idx += bitCount(m_0 & t - 1) * fact[11 - i];
m_0 |= t;
}
return idx;
}
function $getFlip(obj) {
var i, idx;
idx = 0;
for (i = 0; i < 11; ++i) {
idx = idx | obj.eo[i] << i;
}
return idx;
}
function $getFlipSym(obj) {
var idx, k;
if (FlipR2S != null) {
return FlipR2S[$getFlip(obj)];
}
for (k = 0; k < 16; k = k + 2) {
EdgeConjugate(obj, SymInv[k], obj.temps);
idx = binarySearch(FlipS2R, $getFlip(obj.temps));
if (idx != 65535) {
return idx << 3 | k >>> 1;
}
}
return 0;
}
function $getMPerm(obj) {
var i, idx, m_0, t;
m_0 = 1 << obj.ep[11];
idx = 0;
for (i = 10; i >= 8; --i) {
t = 1 << obj.ep[i];
idx += bitCount(m_0 & t - 1) * fact[11 - i];
m_0 |= t;
}
return idx;
}
function $getMid3(obj) {
var i, idxA, idxB, mask, r, t;
idxA = 0;
idxB = 0;
mask = 0;
r = 3;
for (i = 11; i >= 0; --i) {
if (obj.ep[i] >= 9) {
idxA = idxA + Cnk[i][r--];
t = 1 << obj.ep[i];
idxB = idxB + bitCount(mask & t - 1) * fact[2 - r];
mask = mask | t;
}
}
return idxA * 6 + idxB;
}
function $getTwist(obj) {
var i, idx;
idx = 0;
for (i = 0; i < 7; ++i) {
idx = idx * 3;
idx = idx + obj.co[i];
}
return idx;
}
function $getTwistSym(obj) {
var idx, k;
if (TwistR2S != null) {
return TwistR2S[$getTwist(obj)];
}
for (k = 0; k < 16; k = k + 2) {
CornConjugate(obj, SymInv[k], obj.temps);
idx = $getTwist(obj.temps);
idx = binarySearch(TwistS2R, idx);
if (idx != 65535) {
return idx << 3 | k >>> 1;
}
}
return 0;
}
function $getUDSlice(obj) {
var i, idx, r;
idx = 0;
r = 4;
for (i = 0; i < 12; ++i) {
obj.ep[i] >= 8 && (idx = idx + Cnk[11 - i][r--]);
}
return idx;
}
function $getURtoUL(obj) {
var i, idxA, idxB, mask, r, t;
idxA = 0;
idxB = 0;
mask = 0;
r = 3;
for (i = 11; i >= 0; --i) {
if (obj.ep[i] <= 2) {
idxA = idxA + Cnk[i][r--];
t = 1 << obj.ep[i];
idxB = idxB + bitCount(mask & t - 1) * fact[2 - r];
mask = mask | t;
}
}
return idxA * 6 + idxB;
}
function $invCubieCube(obj) {
var corn, edge, ori;
for (edge = 0; edge < 12; ++edge) {
obj.temps.ep[obj.ep[edge]] = edge;
}for (edge = 0; edge < 12; ++edge) {
obj.temps.eo[edge] = obj.eo[obj.temps.ep[edge]];
}for (corn = 0; corn < 8; ++corn) {
obj.temps.cp[obj.cp[corn]] = corn;
}for (corn = 0; corn < 8; ++corn) {
ori = obj.co[obj.temps.cp[corn]];
obj.temps.co[corn] = -ori;
obj.temps.co[corn] < 0 && (obj.temps.co[corn] = obj.temps.co[corn] + 3);
}
$copy(obj, obj.temps);
}
function $setEdgePerm(obj, idx) {
var i, j;
obj.ep[11] = 0;
for (i = 10; i >= 0; --i) {
obj.ep[i] = idx % (12 - i);
idx = ~~(idx / (12 - i));
for (j = i + 1; j < 12; ++j) {
obj.ep[j] >= obj.ep[i] && ++obj.ep[j];
}
}
}
function $setFlip(obj, idx) {
var i;
obj.eo[11] = bitOdd(idx);
for (i = 0; i < 11; ++i) {
obj.eo[i] = idx & 1;
idx = idx >>> 1;
}
}
function $setMPerm(obj, idx) {
var i, j;
obj.ep[11] = 8;
for (i = 10; i >= 8; --i) {
obj.ep[i] = idx % (12 - i) + 8;
idx = ~~(idx / (12 - i));
for (j = i + 1; j < 12; ++j) {
obj.ep[j] >= obj.ep[i] && ++obj.ep[j];
}
}
}
function $setMid3(obj, idxA) {
var edge, i, r;
edge = perm3[idxA % 6];
idxA = ~~(idxA / 6);
r = 3;
for (i = 11; i >= 0; --i) {
if (idxA >= Cnk[i][r]) {
idxA = idxA - Cnk[i][r--];
obj.ep[i] = edge[2 - r];
} else {
obj.ep[i] = 8 - i + r;
}
}
}
function $setTwist(obj, idx) {
var i, twst;
twst = 0;
for (i = 6; i >= 0; --i) {
twst = twst + (obj.co[i] = idx % 3);
idx = ~~(idx / 3);
}
obj.co[7] = (15 - twst) % 3;
}
function $setUDSlice(obj, idx) {
var i, r;
r = 4;
for (i = 0; i < 12; ++i) {
if (idx >= Cnk[11 - i][r]) {
idx = idx - Cnk[11 - i][r--];
obj.ep[i] = 11 - r;
} else {
obj.ep[i] = i + r - 4;
}
}
}
function $verify(obj) {
var c, cornMask, e, edgeMask, i, sum;
sum = 0;
edgeMask = 0;
for (e = 0; e < 12; ++e) {
edgeMask = edgeMask | 1 << obj.ep[e];
}if (edgeMask != 4095) return -2;
for (i = 0; i < 12; ++i) {
sum = sum ^ obj.eo[i];
}if (sum % 2 != 0) return -3;
cornMask = 0;
for (c = 0; c < 8; ++c) {
cornMask = cornMask | 1 << obj.cp[c];
}if (cornMask != 255) return -4;
sum = 0;
for (i = 0; i < 8; ++i) {
sum = sum + obj.co[i];
}if (sum % 3 != 0) return -5;
if ((get12Parity($getEdgePerm(obj)) ^ get8Parity(get8Perm(obj.cp))) != 0) return -6;
return 0;
}
function CornConjugate(a, idx, b) {
CornMultSym(CubeSym[SymInv[idx]], a, temp_0);
CornMultSym(temp_0, CubeSym[idx], b);
}
function CornMult(a, b, prod) {
var corn;
for (corn = 0; corn < 8; ++corn) {
prod.cp[corn] = a.cp[b.cp[corn]];
prod.co[corn] = (a.co[b.cp[corn]] + b.co[corn]) % 3;
}
}
function CornMultSym(a, b, prod) {
var corn, ori, oriA, oriB;
for (corn = 0; corn < 8; ++corn) {
prod.cp[corn] = a.cp[b.cp[corn]];
oriA = a.co[b.cp[corn]];
oriB = b.co[corn];
ori = oriA;
ori = ori + (oriA < 3 ? oriB : 3 - oriB);
ori = ori % 3;oriA < 3 ^ oriB < 3 && (ori = ori + 3);
prod.co[corn] = ori;
}
}
function CubieCube_0() {
$$init(this);
}
function CubieCube_1(cp, co, ep, eo) {
var i;
$$init(this);
for (i = 0; i < 8; ++i) {
this.cp[i] = cp[i];
this.co[i] = co[i];
}
for (i = 0; i < 12; ++i) {
this.ep[i] = ep[i];
this.eo[i] = eo[i];
}
}
function CubieCube_2(cperm, twist, eperm, flip) {
$$init(this);
set8Perm(this.cp, cperm);
$setTwist(this, twist);
$setEdgePerm(this, eperm);
$setFlip(this, flip);
}
function CubieCube_3(c) {
CubieCube_1.call(this, c.cp, c.co, c.ep, c.eo);
}
function EdgeConjugate(a, idx, b) {
EdgeMult(CubeSym[SymInv[idx]], a, temp_0);
EdgeMult(temp_0, CubeSym[idx], b);
}
function EdgeMult(a, b, prod) {
var ed;
for (ed = 0; ed < 12; ++ed) {
prod.ep[ed] = a.ep[b.ep[ed]];
prod.eo[ed] = b.eo[ed] ^ a.eo[b.ep[ed]];
}
}
function get8Perm(arr) {
var i, idx, v, val;
idx = 0;
val = 1985229328;
for (i = 0; i < 7; ++i) {
v = arr[i] << 2;
idx = (8 - i) * idx + (val >> v & 7);
val -= 286331152 << v;
}
return idx;
}
function initMove() {
var m_0, mc, p;
mc = Array(18);
moveCube = [new CubieCube_2(15120, 0, 119750400, 0), new CubieCube_2(21021, 1494, 323403417, 0), new CubieCube_2(8064, 1236, 29441808, 802), new CubieCube_2(9, 0, 5880, 0), new CubieCube_2(1230, 412, 2949660, 0), new CubieCube_2(224, 137, 328552, 1160)];
for (m_0 = 0; m_0 < 6; ++m_0) {
mc[m_0 * 3] = moveCube[m_0];
for (p = 0; p < 2; ++p) {
mc[m_0 * 3 + p + 1] = new CubieCube_0();
EdgeMult(mc[m_0 * 3 + p], moveCube[m_0], mc[m_0 * 3 + p + 1]);
CornMult(mc[m_0 * 3 + p], moveCube[m_0], mc[m_0 * 3 + p + 1]);
}
}
moveCube = mc;
}
function initSym() {
var c, d, f2, i, j, k, lr2, m_0, s, temp, u4;
c = new CubieCube_0();
d = new CubieCube_0();
f2 = new CubieCube_2(28783, 0, 259268407, 0);
u4 = new CubieCube_2(15138, 0, 119765538, 1792);
lr2 = new CubieCube_2(5167, 0, 83473207, 0);
lr2.co = [3, 3, 3, 3, 3, 3, 3, 3];
for (i = 0; i < 16; ++i) {
CubeSym[i] = new CubieCube_3(c);
CornMultSym(c, u4, d);
EdgeMult(c, u4, d);
temp = d;
d = c;
c = temp;
if (i % 4 === 3) {
CornMultSym(temp, lr2, d);
EdgeMult(temp, lr2, d);
temp = d;
d = c;
c = temp;
}
if (i % 8 === 7) {
CornMultSym(temp, f2, d);
EdgeMult(temp, f2, d);
temp = d;
d = c;
c = temp;
}
}
for (j = 0; j < 16; ++j) {
for (k = 0; k < 16; ++k) {
CornMultSym(CubeSym[j], CubeSym[k], c);
if (c.cp[0] === 0 && c.cp[1] === 1 && c.cp[2] === 2) {
SymInv[j] = k;
break;
}
}
}
for (i = 0; i < 16; ++i) {
for (j = 0; j < 16; ++j) {
CornMultSym(CubeSym[i], CubeSym[j], c);
for (k = 0; k < 16; ++k) {
if (CubeSym[k].cp[0] === c.cp[0] && CubeSym[k].cp[1] === c.cp[1] && CubeSym[k].cp[2] === c.cp[2]) {
SymMult[i][j] = k;
break;
}
}
}
}
for (j = 0; j < 18; ++j) {
for (s = 0; s < 16; ++s) {
CornConjugate(moveCube[j], SymInv[s], c);
CONTINUE: for (m_0 = 0; m_0 < 18; ++m_0) {
for (i = 0; i < 8; ++i) {
if (c.cp[i] != moveCube[m_0].cp[i] || c.co[i] != moveCube[m_0].co[i]) {
continue CONTINUE;
}
}
SymMove[s][j] = m_0;
}
}
}
for (j = 0; j < 10; ++j) {
for (s = 0; s < 16; ++s) {
SymMoveUD[s][j] = std2ud[SymMove[s][ud2std[j]]];
}
}
for (j = 0; j < 8; ++j) {
for (s = 0; s < 8; ++s) {
Sym8Mult[s][j] = SymMult[s << 1][j << 1] >>> 1;
}
}
for (j = 0; j < 18; ++j) {
for (s = 0; s < 8; ++s) {
Sym8Move[s][j] = SymMove[s << 1][j];
}
}
for (j = 0; j < 8; ++j) {
for (s = 0; s < 8; ++s) {
Sym8MultInv[j][s] = Sym8Mult[j][SymInv[s << 1] >> 1];
}
}
}
function initSym2Raw() {
var a, b, c, count, d, i, idx, j, m_0, mask, occ, s;
c = new CubieCube_0();
d = new CubieCube_0();
occ = Array(1260);
count = 0;
for (i = 0; i < 64; occ[i++] = 0) {}
for (i = 0; i < 2048; ++i) {
if ((occ[i >>> 5] & 1 << (i & 31)) === 0) {
$setFlip(c, i);
for (s = 0; s < 16; s = s + 2) {
EdgeMult(CubeSym[SymInv[s]], c, temp_0);
EdgeMult(temp_0, CubeSym[s], d);
idx = $getFlip(d);
occ[idx >>> 5] |= 1 << (idx & 31);
FlipR2S[idx] = count << 3 | s >>> 1;
}
FlipS2R[count++] = i;
}
}
count = 0;
for (i = 0; i < 69; occ[i++] = 0) {}
for (i = 0; i < 2187; ++i) {
if ((occ[i >>> 5] & 1 << (i & 31)) === 0) {
$setTwist(c, i);
for (s = 0; s < 16; s = s + 2) {
CornMultSym(CubeSym[SymInv[s]], c, temp_0);
CornMultSym(temp_0, CubeSym[s], d);
idx = $getTwist(d);
occ[idx >>> 5] |= 1 << (idx & 31);
TwistR2S[idx] = count << 3 | s >>> 1;
}
TwistS2R[count++] = i;
}
}
mask = Array(2);
mask[0] = Array(56);
mask[1] = Array(56);
for (i = 0; i < 56; ++i) {
mask[0][i] = mask[1][i] = 0;
}
for (i = 0; i < 40320; ++i) {
set8Perm(c.ep, i);
a = ~~($getURtoUL(c) / 6);
b = ~~($getDRtoDL(c) / 6);
mask[b >> 5][a] |= 1 << (b & 0x1f);
}
for (i = 0; i < 56; ++i) {
count = 0;
for (j = 0; j < 56; ++j) {
;(mask[j >> 5][i] & 1 << (j & 0x1f)) != 0 && (merge[i][j] = count++);
}
}
count = 0;
for (i = 0; i < 1260; occ[i++] = 0) {}
for (i = 0; i < 40320; ++i) {
if ((occ[i >>> 5] & 1 << (i & 31)) === 0) {
set8Perm(c.ep, i);
for (s = 0; s < 16; ++s) {
EdgeMult(CubeSym[SymInv[s]], c, temp_0);
EdgeMult(temp_0, CubeSym[s], d);
idx = get8Perm(d.ep);
occ[idx >>> 5] |= 1 << (idx & 31);
a = $getURtoUL(d);
b = $getDRtoDL(d);
m_0 = merge[~~(a / 6)][~~(b / 6)] * 4032 + a * 12 + b % 6 * 2 + get8Parity(idx);
MtoEPerm[m_0] = count << 4 | s;
EPermR2S[idx] = count << 4 | s;
}
EPermS2R[count++] = i;
}
}
}
function set8Perm(arr, idx) {
var i, m_0, p, v, val;
val = 1985229328;
for (i = 0; i < 7; ++i) {
p = fact[7 - i];
v = ~~(idx / p);
idx = idx - v * p;
v <<= 2;
arr[i] = val >> v & 7;
m_0 = (1 << v) - 1;
val = (val & m_0) + (val >> 4 & ~m_0);
}
arr[7] = val;
}
function CubieCube() {}
_ = CubieCube_3.prototype = CubieCube_2.prototype = CubieCube_0.prototype = CubieCube.prototype;
_.temps = null;
var CPermS2R,
CubeSym,
EPermR2S = null,
EPermS2R,
FlipR2S = null,
FlipS2R,
MtoEPerm,
Sym8Move,
Sym8Mult,
Sym8MultInv,
SymInv,
SymMove,
SymMoveUD,
SymMult,
TwistR2S = null,
TwistS2R,
e2c,
merge,
moveCube = null,
temp_0,
urf1,
urf2,
urfMove;
function $Solve(obj, c) {
var i;
c.temps = new CubieCube_0();
for (i = 0; i < 6; ++i) {
obj.twist[i] = $getTwistSym(c);
obj.tsym[i] = obj.twist[i] & 7;
obj.twist[i] >>>= 3;
obj.flip[i] = $getFlipSym(c);
obj.fsym[i] = obj.flip[i] & 7;
obj.flip[i] >>>= 3;
obj.slice_0[i] = $getUDSlice(c);
obj.corn0[i] = $getCPermSym(c);
obj.csym0[i] = obj.corn0[i] & 15;
obj.corn0[i] >>>= 4;
obj.mid30[i] = $getMid3(c);
obj.e10[i] = $getURtoUL(c);
obj.e20[i] = $getDRtoDL(c);
obj.prun[i] = Math.max(Math.max(UDSliceTwistPrun[obj.twist[i] * 495 + UDSliceConj[obj.slice_0[i]][obj.tsym[i]]], UDSliceFlipPrun[obj.flip[i] * 495 + UDSliceConj[obj.slice_0[i]][obj.fsym[i]]]), TwistFlipPrun[obj.twist[i] * 2688 + (obj.flip[i] << 3 | Sym8MultInv[obj.fsym[i]][obj.tsym[i]])]);
CornMult(urf2, c, c.temps);
CornMult(c.temps, urf1, c);
EdgeMult(urf2, c, c.temps);
EdgeMult(c.temps, urf1, c);
i === 2 && $invCubieCube(c);
}
obj.solution = null;
for (obj.length1 = 0; obj.length1 < obj.sol; ++obj.length1) {
obj.maxlength2 = Math.min(~~(obj.sol / 2) + 1, obj.sol - obj.length1);
for (obj.urfidx = 0; obj.urfidx < 6; ++obj.urfidx) {
obj.corn[0] = obj.corn0[obj.urfidx];
obj.csym[0] = obj.csym0[obj.urfidx];
obj.mid3[0] = obj.mid30[obj.urfidx];
obj.e1[0] = obj.e10[obj.urfidx];
obj.e2[0] = obj.e20[obj.urfidx];
if (obj.prun[obj.urfidx] <= obj.length1 && $phase1(obj, obj.twist[obj.urfidx], obj.tsym[obj.urfidx], obj.flip[obj.urfidx], obj.fsym[obj.urfidx], obj.slice_0[obj.urfidx], obj.length1, 18)) {
return obj.solution === null ? 'Error 8' : obj.solution;
}
}
}
return 'Error 7';
}
function $init2(obj) {
var cornx, edge, esym, ex, i, lm, m_0, mid, prun, s, sb, urf;
obj.valid2 = Math.min(obj.valid2, obj.valid1);
for (i = obj.valid1; i < obj.length1; ++i) {
m_0 = obj.move[i];
obj.corn[i + 1] = CPermMove[obj.corn[i]][SymMove[obj.csym[i]][m_0]];
obj.csym[i + 1] = SymMult[obj.corn[i + 1] & 15][obj.csym[i]];
obj.corn[i + 1] >>>= 4;
obj.mid3[i + 1] = Mid3Move[obj.mid3[i]][m_0];
}
obj.valid1 = obj.length1;
mid = Mid32MPerm[obj.mid3[obj.length1] % 24];
prun = MCPermPrun[obj.corn[obj.length1] * 24 + MPermConj[mid][obj.csym[obj.length1]]];
if (prun >= obj.maxlength2) {
return false;
}
for (i = obj.valid2; i < obj.length1; ++i) {
obj.e1[i + 1] = Mid3Move[obj.e1[i]][obj.move[i]];
obj.e2[i + 1] = Mid3Move[obj.e2[i]][obj.move[i]];
}
obj.valid2 = obj.length1;
cornx = obj.corn[obj.length1];
ex = merge[~~(obj.e1[obj.length1] / 6)][~~(obj.e2[obj.length1] / 6)] * 4032 + obj.e1[obj.length1] * 12 + obj.e2[obj.length1] % 6 * 2 + (CParity[cornx >>> 3] >>> (cornx & 7) & 1 ^ parity4[mid]);
edge = MtoEPerm[ex];
esym = edge & 15;
edge >>>= 4;
prun = Math.max(MEPermPrun[edge * 24 + MPermConj[mid][esym]], prun);
if (prun >= obj.maxlength2) {
return false;
}
lm = obj.length1 === 0 ? 10 : std2ud[~~(obj.move[obj.length1 - 1] / 3) * 3 + 1];
for (i = prun; i < obj.maxlength2; ++i) {
if ($phase2(obj, edge, esym, obj.corn[obj.length1], obj.csym[obj.length1], mid, i, obj.length1, lm)) {
obj.sol = obj.length1 + i;
sb = '';
urf = obj.urfidx;
urf = (urf + 3) % 6;
if (urf < 3) {
for (s = 0; s < obj.length1; ++s) {
sb += move2str[urfMove[urf][obj.move[s]]];
sb += ' ';
}
obj.useSeparator && (sb.impl.string += '.', sb);
for (s = obj.length1; s < obj.sol; ++s) {
sb += move2str[urfMove[urf][obj.move[s]]];
sb += ' ';
}
} else {
for (s = obj.sol - 1; s >= obj.length1; --s) {
sb += move2str[urfMove[urf][obj.move[s]]];
sb += ' ';
}
obj.useSeparator && (sb += '.', sb);
for (s = obj.length1 - 1; s >= 0; --s) {
sb += move2str[urfMove[urf][obj.move[s]]];
sb += ' ';
}
}
obj.solution = sb;
return true;
}
}
return false;
}
function $phase1(obj, twist, tsym, flip, fsym, slice, maxl, lm) {
var flipx, fsymx, m_0, slicex, tsymx, twistx;
if (twist === 0 && flip === 0 && slice === 0 && maxl < 5) {
return maxl === 0 && $init2(obj);
}
for (m_0 = 0; m_0 < 18; ++m_0) {
if (ckmv[lm][m_0]) {
m_0 += 2;
continue;
}
slicex = UDSliceMove[slice][m_0];
twistx = TwistMove[twist][Sym8Move[tsym][m_0]];
tsymx = Sym8Mult[twistx & 7][tsym];
twistx >>>= 3;
if (UDSliceTwistPrun[twistx * 495 + UDSliceConj[slicex][tsymx]] >= maxl) {
continue;
}
flipx = FlipMove[flip][Sym8Move[fsym][m_0]];
fsymx = Sym8Mult[flipx & 7][fsym];
flipx >>>= 3;
if (TwistFlipPrun[twistx * 2688 + (flipx << 3 | Sym8MultInv[fsymx][tsymx])] >= maxl || UDSliceFlipPrun[flipx * 495 + UDSliceConj[slicex][fsymx]] >= maxl) {
continue;
}
obj.move[obj.length1 - maxl] = m_0;
obj.valid1 = Math.min(obj.valid1, obj.length1 - maxl);
if ($phase1(obj, twistx, tsymx, flipx, fsymx, slicex, maxl - 1, m_0)) {
return true;
}
}
return false;
}
function $phase2(obj, edge, esym, corn, csym, mid, maxl, depth, lm) {
var cornx, csymx, edgex, esymx, m_0, midx;
if (edge === 0 && corn === 0 && mid === 0) {
return true;
}
for (m_0 = 0; m_0 < 10; ++m_0) {
if (ckmv2[lm][m_0]) {
continue;
}
midx = MPermMove[mid][m_0];
edgex = EPermMove[edge][SymMoveUD[esym][m_0]];
esymx = SymMult[edgex & 15][esym];
edgex >>>= 4;
if (MEPermPrun[edgex * 24 + MPermConj[midx][esymx]] >= maxl) {
continue;
}
cornx = CPermMove[corn][SymMove[csym][ud2std[m_0]]];
csymx = SymMult[cornx & 15][csym];
cornx >>>= 4;
if (MCPermPrun[cornx * 24 + MPermConj[midx][csymx]] >= maxl) {
continue;
}
obj.move[depth] = ud2std[m_0];
if ($phase2(obj, edgex, esymx, cornx, csymx, midx, maxl - 1, depth + 1, m_0)) {
return true;
}
}
return false;
}
function $solution(obj, facelets) {
var $e0, cc, i, s;
init_0();
for (i = 0; i < 54; ++i) {
switch (facelets.charCodeAt(i)) {
case 85:
obj.f[i] = 0;
break;
case 82:
obj.f[i] = 1;
break;
case 70:
obj.f[i] = 2;
break;
case 68:
obj.f[i] = 3;
break;
case 76:
obj.f[i] = 4;
break;
case 66:
obj.f[i] = 5;
break;
default:
return 'Error 1';
}
}
cc = toCubieCube(obj.f);
obj.sol = 22;
return $Solve(obj, cc);
}
function Search() {
this.move = Array(31);
this.corn = Array(20);
this.csym = Array(20);
this.mid3 = Array(20);
this.e1 = Array(20);
this.e2 = Array(20);
this.twist = Array(6);
this.tsym = Array(6);
this.flip = Array(6);
this.fsym = Array(6);
this.slice_0 = Array(6);
this.corn0 = Array(6);
this.csym0 = Array(6);
this.mid30 = Array(6);
this.e10 = Array(6);
this.e20 = Array(6);
this.prun = Array(6);
this.count = Array(6);
this.f = Array(54);
}
_ = Search.prototype;
_.inverse = false;
_.length1 = 0;
_.maxlength2 = 0;
_.sol = 999;
_.solution = null;
_.urfidx = 0;
_.useSeparator = false;
_.valid1 = 0;
_.valid2 = 0;
function init_0(safeStatusCallback) {
if (inited) return;
$clinit_Util();
safeStatusCallback('[0/9] Initializing Cubie Cube...');
$clinit_CubieCube();
FlipR2S = Array(2048);
TwistR2S = Array(2187);
EPermR2S = Array(40320);
safeStatusCallback('[1/9] Initializing Sym2Raw...');
initSym2Raw();
safeStatusCallback('[2/9] Initializing CoordCube...');
$clinit_CoordCube();
safeStatusCallback('[3/9] Initializing Perm, Flip, and Twist Moves...');
initCPermMove();
initEPermMove();
initFlipMove();
initTwistMove();
safeStatusCallback('[4/9] Initializing UDSlice...');
EPermR2S = null;
FlipR2S = null;
TwistR2S = null;
initUDSliceMove();
initUDSliceConj();
safeStatusCallback('[5/9] Initializing Mid3Move...');
initMid3Move();
initMid32MPerm();
initCParity();
safeStatusCallback('[6/9] Initializing Perms...');
initMPermMove();
initMPermConj();
safeStatusCallback('[7/9] Initializing TwistFlipSlicePrun...');
initTwistFlipSlicePrun(safeStatusCallback);
safeStatusCallback('[8/9] Initializing MCEPermPrum...');
initMCEPermPrun(safeStatusCallback);
safeStatusCallback('[9/9] Done initializing 3x3x3...');
inited = true;
}
function randomCube_0() {
var cperm, eperm;
do {
eperm = randInt(479001600);
cperm = randInt(40320);
} while ((get8Parity(cperm) ^ get12Parity(eperm)) != 0);
return toFaceCube(new CubieCube_2(cperm, randInt(2187), eperm, randInt(2048)));
}
var inited = false;
function $clinit_Util() {
$clinit_Util = noop;
var i, j;
cornerFacelet = [[8, 9, 20], [6, 18, 38], [0, 36, 47], [2, 45, 11], [29, 26, 15], [27, 44, 24], [33, 53, 42], [35, 17, 51]];
edgeFacelet = [[5, 10], [7, 19], [3, 37], [1, 46], [32, 16], [28, 25], [30, 43], [34, 52], [23, 12], [21, 41], [50, 39], [48, 14]];
cornerColor = [[0, 1, 2], [0, 2, 4], [0, 4, 5], [0, 5, 1], [3, 2, 1], [3, 4, 2], [3, 5, 4], [3, 1, 5]];
edgeColor = [[0, 1], [0, 2], [0, 4], [0, 5], [3, 1], [3, 2], [3, 4], [3, 5], [2, 1], [2, 4], [5, 4], [5, 1]];
Cnk = createArray(12, 12);
fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600];
move2str = ['U ', 'U2', "U'", 'R ', 'R2', "R'", 'F ', 'F2', "F'", 'D ', 'D2', "D'", 'L ', 'L2', "L'", 'B ', 'B2', "B'"];
ud2std = [0, 1, 2, 4, 7, 9, 10, 11, 13, 16];
std2ud = Array(18);
ckmv = createArray(19, 18);
ckmv2 = createArray(11, 10);
parity4 = Array(24);
perm3 = [[11, 10, 9], [10, 11, 9], [11, 9, 10], [9, 11, 10], [10, 9, 11], [9, 10, 11]];
for (i = 0; i < 10; ++i) {
std2ud[ud2std[i]] = i;
}
for (i = 0; i < 18; ++i) {
for (j = 0; j < 18; ++j) {
ckmv[i][j] = ~~(i / 3) === ~~(j / 3) || ~~(i / 3) % 3 === ~~(j / 3) % 3 && i >= j;
}
ckmv[18][i] = false;
}
for (i = 0; i < 10; ++i) {
for (j = 0; j < 10; ++j) {
ckmv2[i][j] = ckmv[ud2std[i]][ud2std[j]];
}
ckmv2[10][i] = false;
}
for (i = 0; i < 12; ++i) {
for (j = 0; j < 12; ++j) {
Cnk[i][j] = 0;
}
}for (i = 0; i < 12; ++i) {
Cnk[i][0] = 1;
Cnk[i][i] = 1;
for (j = 1; j < i; ++j) {
Cnk[i][j] = Cnk[i - 1][j - 1] + Cnk[i - 1][j];
}
}
for (i = 0; i < 24; ++i) {
parity4[i] = get4Parity(i);
}
}
function binarySearch(arr, key) {
var l_0, length_0, mid, r, val;
length_0 = arr.length;
if (key <= arr[length_0 - 1]) {
l_0 = 0;
r = length_0 - 1;
while (l_0 <= r) {
mid = l_0 + r >>> 1;
val = arr[mid];
if (key > val) {
l_0 = mid + 1;
} else if (key < val) {
r = mid - 1;
} else {
return mid;
}
}
}
return 65535;
}
function bitCount(i) {
i = i - (i >>> 1 & 1431655765);
i = (i & 858993459) + (i >>> 2 & 858993459);
return i + (i >>> 8) + (i >>> 4) & 15;
}
function bitOdd(i) {
i = i ^ i >>> 1;
i = i ^ i >>> 2;
i = i ^ i >>> 4;
i = i ^ i >>> 8;
return i & 1;
}
function get12Parity(idx) {
var i, p;
p = 0;
for (i = 10; i >= 0; --i) {
p = p + idx % (12 - i);
idx = ~~(idx / (12 - i));
}
p = p & 1;
return p;
}
function get4Parity(idx) {
var i, p;
p = 0;
for (i = 2; i >= 0; --i) {
p = p + idx % (4 - i);
idx = ~~(idx / (4 - i));
}
p = p & 1;
return p;
}
function get8Parity(idx) {
var i, p;
p = 0;
for (i = 6; i >= 0; --i) {
p = p + idx % (8 - i);
idx = ~~(idx / (8 - i));
}
p = p & 1;
return p;
}
function toCubieCube(f) {
var ccRet, col1, col2, i, j, ori;
ccRet = new CubieCube_0();
for (i = 0; i < 8; ++i) {
ccRet.cp[i] = 0;
}for (i = 0; i < 12; ++i) {
ccRet.ep[i] = 0;
}for (i = 0; i < 8; ++i) {
for (ori = 0; ori < 3; ++ori) {
if (f[cornerFacelet[i][ori]] === 0 || f[cornerFacelet[i][ori]] === 3) break;
}col1 = f[cornerFacelet[i][(ori + 1) % 3]];
col2 = f[cornerFacelet[i][(ori + 2) % 3]];
for (j = 0; j < 8; ++j) {
if (col1 === cornerColor[j][1] && col2 === cornerColor[j][2]) {
ccRet.cp[i] = j;
ccRet.co[i] = ori % 3;
break;
}
}
}
for (i = 0; i < 12; ++i) {
for (j = 0; j < 12; ++j) {
if (f[edgeFacelet[i][0]] === edgeColor[j][0] && f[edgeFacelet[i][1]] === edgeColor[j][1]) {
ccRet.ep[i] = j;
ccRet.eo[i] = 0;
break;
}
if (f[edgeFacelet[i][0]] === edgeColor[j][1] && f[edgeFacelet[i][1]] === edgeColor[j][0]) {
ccRet.ep[i] = j;
ccRet.eo[i] = 1;
break;
}
}
}
return ccRet;
}
function toFaceCube(cc) {
var c, e, f, i, j, n, ori, ts;
f = Array(54);
ts = [85, 82, 70, 68, 76, 66];
for (i = 0; i < 54; ++i) {
f[i] = ts[~~(i / 9)];
}
for (c = 0; c < 8; ++c) {
j = cc.cp[c];
ori = cc.co[c];
for (n = 0; n < 3; ++n) {
f[cornerFacelet[c][(n + ori) % 3]] = ts[cornerColor[j][n]];
}
}
for (e = 0; e < 12; ++e) {
j = cc.ep[e];
ori = cc.eo[e];
for (n = 0; n < 2; ++n) {
f[edgeFacelet[e][(n + ori) % 2]] = ts[edgeColor[j][n]];
}
}
return String.fromCharCode.apply(null, f);
}
var Cnk, ckmv, ckmv2, cornerColor, cornerFacelet, edgeColor, edgeFacelet, fact, move2str, parity4, perm3, std2ud, ud2std;
//"UF UR UB UL DF DR DB DL FR FL BR BL UFR URB UBL ULF DRF DFL DLB DBR URFLBD";
//0 3 6 9 12 15 18 21 24 27 30 33 36 40 44 48 52 56 60 64 68
var drawingStickerMap = [[
// U
[0, 1, 2], [3, 4, 5], [6, 7, 8]], [
// R
[9, 10, 11], [12, 13, 14], [15, 16, 17]], [
// F
[18, 19, 20], [21, 22, 23], [24, 25, 26]], [
// L
[36, 37, 38], [39, 40, 41], [42, 43, 44]], [
// B
[45, 46, 47], [48, 49, 50], [51, 52, 53]], [
// D
[27, 28, 29], [30, 31, 32], [33, 34, 35]]];
var border = 2;
var width = 12;
var gap = 4;
//URFLBD
var drawingCenters = [[border + width / 2 * 9 + gap * 1, border + width / 2 * 3], [border + width / 2 * 15 + gap * 2, border + width / 2 * 9 + gap * 1], [border + width / 2 * 9 + gap * 1, border + width / 2 * 9 + gap * 1], [border + width / 2 * 3 + gap * 0, border + width / 2 * 9 + gap * 1], [border + width / 2 * 21 + gap * 3, border + width / 2 * 9 + gap * 1], [border + width / 2 * 9 + gap * 1, border + width / 2 * 15 + gap * 2]];
function colorGet(col) {
if (col === 'r') return '#FF0000';
if (col === 'o') return '#FF8000';
if (col === 'b') return '#0000FF';
if (col === 'g') return '#00FF00';
if (col === 'y') return '#FFFF00';
if (col === 'w') return '#FFFFFF';
if (col === 'x') return '#000000';
}
var scalePoint = function scalePoint(w, h, ptIn) {
var defaultWidth = border * 2 + width * 12 + gap * 3;
var defaultHeight = border * 2 + width * 9 + gap * 2;
var scale = Math.min(w / defaultWidth, h / defaultHeight);
var x = Math.floor(ptIn[0] * scale + (w - defaultWidth * scale) / 2) + 0.5;
var y = Math.floor(ptIn[1] * scale + (h - defaultHeight * scale) / 2) + 0.5;
return [x, y];
};
function drawSquare(r, wi, h, cx, cy, w, fillColor) {
var arrx = [cx - w, cx - w, cx + w, cx + w];
var arry = [cy - w, cy + w, cy + w, cy - w];
var pathString = '';
for (var i = 0; i < arrx.length; i++) {
var scaledPoint = scalePoint(wi, h, [arrx[i], arry[i]]);
pathString += (i === 0 ? 'M' : 'L') + scaledPoint[0] + ',' + scaledPoint[1];
}
pathString += 'z';
r.path(pathString).attr({ fill: colorGet(fillColor), stroke: '#000' });
}
var drawScramble = function drawScramble(parentElement, state, w, h) {
if (typeof window === 'undefined') {
throw new Error('You cannot use drawScramble outside of the browser.');
}
var colorString = 'wrgoby'; // UFRLBD
var colorScheme = {
U: colorString[0],
R: colorString[1],
F: colorString[2],
L: colorString[3],
B: colorString[4],
D: colorString[5]
};
parentElement.innerHTML = '';
var r = Raphael(parentElement, w, h);
var stateWithCenters = state + ' URFLBD';
for (var i = 0; i < 6; i++) {
for (var j = 0; j < 3; j++) {
for (var k = 0; k < 3; k++) {
var face = stateWithCenters[drawingStickerMap[i][j][k]];
drawSquare(r, w, h, drawingCenters[i][0] + (k - 1) * width, drawingCenters[i][1] + (j - 1) * width, width / 2, colorScheme[face]);
}
}
}
};
var initialized = false;
var search;
var ini = function ini(callback, _, statusCallback) {
if (initialized) {
return;
}
if (typeof statusCallback !== 'function') {
statusCallback = function statusCallback() {};
}
search = new Search();
init_0(statusCallback);
initialized = true;
if (callback) setTimeout(callback, 0);
};
var getRandomScramble = function getRandomScramble() {
ini();
var posit = randomCube_0();
var solution = $solution(search, posit);
return {
state: posit,
scrambleString: solution.replace(/ +(?= )/g, '').trim()
};
};
var scrambler = {
initialize: ini,
getRandomScramble: getRandomScramble,
drawScramble: drawScramble
};
module.exports = scrambler;