Created
April 7, 2012 16:38
-
-
Save cs0x7f/2330203 to your computer and use it in GitHub Desktop.
generate random state subset scramble
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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"; | |
if (typeof scramblers == "undefined") { | |
var scramblers = {}; | |
} | |
scramblers["333fm"] = scramblers["333ft"] = scramblers["333bf"] = scramblers["333oh"] = scramblers["333"] = (function() { | |
var cornerFacelet, edgeFacelet, cornerColor, edgeColor, Cnk, fact, move2str, ud2std, std2ud, ckmv, ckmv2, parity4, perm3, moveCube, CubeSym, SymInv, SymMult, SymMove, Sym8Mult, Sym8Move, Sym8MultInv, SymMoveUD, e2c, merge, FlipS2R, TwistS2R, PermS2R, FlipR2S, TwistR2S, PermR2S, MtoEPerm, SymStateTwist, SymStateFlip, SymStatePerm, UDSliceMove, TwistMove, FlipMove, UDSliceConj, UDSliceTwistPrun, UDSliceFlipPrun, TwistFlipPrun, Mid3Move, Mid32MPerm, CParity, CPermMove, EPermMove, MPermMove, MPermConj, MCPermPrun, MEPermPrun, urf1, urf2, urfMove; | |
function createArray(length1, length2){ | |
var result, i; | |
result = []; | |
if (length2 == undefined) { | |
result[i] = 0; | |
} else { | |
for (i=0; i<length1; i++) { | |
result[i] = []; | |
} | |
} | |
return result; | |
} | |
function initCParity(){ | |
CParity = createArray(346); | |
for (var i=0; i<2768; ++i) { | |
CParity[i >>> 3] = (CParity[i >>> 3] | getNParity(8,PermS2R[i]) << (i & 7)); | |
} | |
} | |
function initCPermMove(){ | |
CPermMove = createArray(2768, 18); | |
var c = new CubieCube_0; | |
var d = new CubieCube_0; | |
for (var i = 0; i < 2768; ++i) { | |
set8Perm(c.cp, PermS2R[i]); | |
for (var j = 0; j < 18; ++j) { | |
CornMult(c, moveCube[j], d); | |
CPermMove[i][j] = getCPermSym(d); | |
} | |
} | |
} | |
function initEPermMove(){ | |
EPermMove = createArray(2768, 10); | |
var c = new CubieCube_0; | |
var d = new CubieCube_0; | |
for (var i = 0; i < 2768; ++i) { | |
set8Perm(c.ep, PermS2R[i]); | |
for (var j = 0; j < 10; ++j) { | |
EdgeMult(c, moveCube[ud2std[j]], d); | |
EPermMove[i][j] = getEPermSym(d); | |
} | |
} | |
} | |
function initFlipMove(){ | |
FlipMove = createArray(336, 18); | |
var c = new CubieCube_0; | |
var d = new CubieCube_0; | |
for (var i = 0; i < 336; ++i) { | |
setFlip(c, FlipS2R[i]); | |
for (var j = 0; j < 18; ++j) { | |
EdgeMult(c, moveCube[j], d); | |
FlipMove[i][j] = getFlipSym(d); | |
} | |
} | |
} | |
function initMCEPermPrun(callback){ | |
var check, corn, cornx, depth, done, edge, edgex, i, idx, idxx, inv, j, m, mid, midx, select, sym, symx; | |
depth = 0; | |
done = 1; | |
MEPermPrun = [];//Array(66432); | |
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) | |
continue; | |
mid = i % 24; | |
edge = ~~(i / 24); | |
for (m = 0; m < 10; ++m) { | |
edgex = EPermMove[edge][m]; | |
symx = edgex & 15; | |
midx = MPermConj[MPermMove[mid][m]][symx]; | |
edgex >>>= 4; | |
idx = edgex * 24 + midx; | |
if (MEPermPrun[idx] == check) { | |
++done; | |
if (inv) { | |
MEPermPrun[i] = depth; | |
break; | |
} else { | |
MEPermPrun[idx] = depth; | |
sym = SymStatePerm[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; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
// callback("MEPermPrun: " + (Math.floor(done * 100 / 66432)) +"% (" + done + "/66432)"); | |
} | |
MCPermPrun = [];//Array(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) | |
continue; | |
mid = i % 24; | |
corn = ~~(i / 24); | |
for (m = 0; m < 10; ++m) { | |
cornx = CPermMove[corn][ud2std[m]]; | |
symx = (cornx & 15); | |
midx = MPermConj[MPermMove[mid][m]][symx]; | |
cornx = cornx >>> 4; | |
idx = cornx * 24 + midx; | |
if (MCPermPrun[idx] == check) { | |
++done; | |
if (inv) { | |
MCPermPrun[i] = depth; | |
break; | |
} else { | |
MCPermPrun[idx] = depth; | |
sym = SymStatePerm[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; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
// callback("MCPermPrun: " + (Math.floor(done * 100 / 66432)) +"% (" + done + "/66432)"); | |
} | |
} | |
function initMPermMoveConj(){ | |
MPermMove = createArray(24, 10); | |
MPermConj = createArray(24, 16); | |
var c = new CubieCube_0; | |
var d = new CubieCube_0; | |
for (var i = 0; i < 24; ++i) { | |
setMPerm(c, i); | |
for (var j = 0; j < 10; ++j) { | |
EdgeMult(c, moveCube[ud2std[j]], d); | |
MPermMove[i][j] = getMPerm(d); | |
} | |
for (var j = 0; j < 16; ++j) { | |
EdgeConjugate(c, SymInv[j], d); | |
MPermConj[i][j] = getMPerm(d); | |
} | |
} | |
} | |
function initMid32MPerm(){ | |
Mid32MPerm = [];//24); | |
var c = new CubieCube_0; | |
for (var i = 0; i < 24; ++i) { | |
setMPerm(c, i); | |
Mid32MPerm[getMid3(c) % 24] = i; | |
} | |
} | |
function initMid3Move(){ | |
Mid3Move = createArray(1320, 18); | |
var c = new CubieCube_0; | |
var d = new CubieCube_0; | |
for (var i = 0; i < 1320; ++i) { | |
setMid3(c, i); | |
for (var j = 0; j < 18; ++j) { | |
EdgeMult(c, moveCube[j], d); | |
Mid3Move[i][j] = getMid3(d); | |
} | |
} | |
} | |
function initTwistFlipSlicePrun(callback){ | |
var check, depth, done, flip, flipx, fsym, fsymx, fsymxx, idx, idxx, inv, j, k, select, slice, slicex, sym, symF, symx, tsymx, twist, twistx; | |
TwistFlipPrun = []; | |
for (var i = 0; i < 870912; ++i) { | |
TwistFlipPrun[i] = -1; | |
} | |
for (var 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 (var i = 0; i < 870912; ++i) { | |
if (TwistFlipPrun[i] != select) | |
continue; | |
twist = ~~(i / 2688); | |
flip = i % 2688; | |
fsym = i & 7; | |
flip >>>= 3; | |
for (var m = 0; m < 18; ++m) { | |
twistx = TwistMove[twist][m]; | |
tsymx = twistx & 7; | |
twistx >>>= 3; | |
flipx = FlipMove[flip][Sym8Move[fsym][m]]; | |
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 = SymStateTwist[twistx]; | |
symF = SymStateFlip[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; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
// callback("TwistFlipPrun: " + (Math.floor(done * 100 / 870912)) +"% (" + done + "/870912)"); | |
} | |
UDSliceTwistPrun = []; | |
for (var 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 (var i = 0; i < 160380; ++i) { | |
if (UDSliceTwistPrun[i] != select) | |
continue; | |
slice = i % 495; | |
twist = ~~(i / 495); | |
for (var m = 0; m < 18; ++m) { | |
twistx = TwistMove[twist][m]; | |
symx = twistx & 7; | |
slicex = UDSliceConj[UDSliceMove[slice][m]][symx]; | |
twistx >>>= 3; | |
idx = twistx * 495 + slicex; | |
if (UDSliceTwistPrun[idx] == check) { | |
++done; | |
if (inv) { | |
UDSliceTwistPrun[i] = depth; | |
break; | |
} else { | |
UDSliceTwistPrun[idx] = depth; | |
sym = SymStateTwist[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; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
// callback("UDSliceTwistPrun: " + (Math.floor(done * 100 / 160380)) +"% (" + done + "/160380)"); | |
} | |
UDSliceFlipPrun = []; | |
for (var 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 (var i = 0; i < 166320; ++i) { | |
if (UDSliceFlipPrun[i] != select) | |
continue; | |
slice = i % 495; | |
flip = ~~(i / 495); | |
for (var m = 0; m < 18; ++m) { | |
flipx = FlipMove[flip][m]; | |
symx = flipx & 7; | |
slicex = UDSliceConj[UDSliceMove[slice][m]][symx]; | |
flipx >>>= 3; | |
idx = flipx * 495 + slicex; | |
if (UDSliceFlipPrun[idx] == check) { | |
++done; | |
if (inv) { | |
UDSliceFlipPrun[i] = depth; | |
break; | |
} else { | |
UDSliceFlipPrun[idx] = depth; | |
sym = SymStateFlip[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; | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
// callback("UDSliceFlipPrun: " + (Math.floor(done * 100 / 166320)) +"% (" + done + "/166320)"); | |
} | |
} | |
function initTwistMove(){ | |
TwistMove = createArray(324, 18); | |
var c = new CubieCube_0; | |
var d = new CubieCube_0; | |
for (var i = 0; i < 324; ++i) { | |
setTwist(c, TwistS2R[i]); | |
for (var j = 0; j < 18; ++j) { | |
CornMult(c, moveCube[j], d); | |
TwistMove[i][j] = getTwistSym(d); | |
} | |
} | |
} | |
function initUDSliceMoveConj(){ | |
UDSliceMove = createArray(495, 18); | |
UDSliceConj = createArray(495, 8); | |
var c = new CubieCube_0; | |
var d = new CubieCube_0; | |
for (var i = 0; i < 495; ++i) { | |
setUDSlice(c, i); | |
for (var j = 0; j < 18; ++j) { | |
EdgeMult(c, moveCube[j], d); | |
UDSliceMove[i][j] = getUDSlice(d); | |
} | |
for (var j = 0; j < 16; j = j + 2) { | |
EdgeConjugate(c, SymInv[j], d); | |
UDSliceConj[i][j >>> 1] = getUDSlice(d); | |
} | |
} | |
} | |
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 = PermR2S[get8Perm(obj.cp)]; | |
return idx ^ e2c[idx & 15]; | |
} | |
function getDRtoDL(obj){ | |
var idxA = 0; | |
var idxB = 0; | |
var mask = 0; | |
var r = 3; | |
for (var i = 11; i >= 0; --i) { | |
if (4 <= obj.ep[i] && obj.ep[i] <= 6) { | |
idxA = idxA + Cnk[i][r--]; | |
var t = 1 << obj.ep[i]; | |
idxB = idxB + bitCount(mask & t - 1) * fact[2 - r]; | |
mask = (mask | t); | |
} | |
} | |
return idxA * 6 + idxB; | |
} | |
function getEPermSym(obj){ | |
return PermR2S[get8Perm(obj.ep)]; | |
} | |
function getEdgePerm(obj){ | |
var i, idx, m, t; | |
m = 1 << obj.ep[11]; | |
idx = 0; | |
for (i = 10; i >= 0; --i) { | |
t = 1 << obj.ep[i]; | |
idx += bitCount(m & t - 1) * fact[11 - i]; | |
m |= 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){ | |
return FlipR2S[getFlip(obj)]; | |
} | |
function getMPerm(obj) { | |
var idx = 0; | |
var val = 0x76543210; | |
for (var i=0; i<3; i++) { | |
var v = (obj.ep[i+8]-8) << 2; | |
idx = (4 - i) * idx + ((val >> v) & 0x0f); | |
val -= 0x11111110 << v; | |
} | |
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 *= 3; | |
idx += obj.co[i]; | |
} | |
return idx; | |
} | |
function getTwistSym(obj){ | |
return TwistR2S[getTwist(obj)]; | |
} | |
function getUDSlice(obj){ | |
var idx = 0; | |
var r = 4; | |
for (var i = 0; i < 12; ++i) { | |
obj.ep[i] >= 8 && (idx += Cnk[11 - i][r--]); | |
} | |
return idx; | |
} | |
function getURtoUL(obj){ | |
var idxA = 0; | |
var idxB = 0; | |
var mask = 0; | |
var r = 3; | |
for (var i = 11; i >= 0; --i) { | |
if (obj.ep[i] <= 2) { | |
idxA += Cnk[i][r--]; | |
var t = 1 << obj.ep[i]; | |
idxB += bitCount(mask & t - 1) * fact[2 - r]; | |
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 parity = 0; | |
for (var i=0; i<11; ++i) { | |
parity ^= obj.eo[i] = (idx & 1); | |
idx >>>= 1; | |
} | |
obj.eo[11] = parity; | |
} | |
function setMPerm(obj, idx) { | |
var val = 0x3210; | |
for (var i=8; i<11; i++) { | |
var p = fact[11-i]; | |
var v = (~~(idx / p)) << 2; | |
idx %= p; | |
obj.ep[i] = (val >> v) & 0xf | 8; | |
var m = (1 << v) - 1; | |
val = (val & m) + ((val >> 4) & ~m); | |
} | |
obj.ep[11] = (val|8); | |
} | |
function setMid3(obj, idxA){ | |
var edge = perm3[idxA % 6]; | |
idxA = ~~(idxA / 6); | |
var r = 3; | |
for (var i = 11; i >= 0; --i) { | |
if (idxA >= Cnk[i][r]) { | |
idxA -= Cnk[i][r--]; | |
obj.ep[i] = edge[2 - r]; | |
} | |
else { | |
obj.ep[i] = 8 - i + r; | |
} | |
} | |
} | |
function setTwist(obj, idx){ | |
var twst = 0; | |
for (var 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 r = 4; | |
for (var 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 ^= obj.eo[i]; | |
if (sum % 2 != 0) | |
return -3; | |
cornMask = 0; | |
for (c = 0; c < 8; ++c) | |
cornMask |= 1 << obj.cp[c]; | |
if (cornMask != 255) | |
return -4; | |
sum = 0; | |
for (i = 0; i < 8; ++i) | |
sum += obj.co[i]; | |
if (sum % 3 != 0) | |
return -5; | |
if ((getNParity(12,getEdgePerm(obj)) ^ getNParity(8,get8Perm(obj.cp))) != 0) | |
return -6; | |
return 0; | |
} | |
function CornConjugate(a, idx, b) { | |
var sinv = CubeSym[SymInv[idx]]; | |
var s = CubeSym[idx]; | |
for (var corn=0; corn<8; corn++) { | |
b.cp[corn] = sinv.cp[a.cp[s.cp[corn]]]; | |
var oriA = sinv.co[a.cp[s.cp[corn]]]; | |
var oriB = a.co[s.cp[corn]]; | |
b.co[corn] = ((oriA<3) ? oriB : (3-oriB) % 3); | |
} | |
} | |
function CornMult(a, b, prod){ | |
for (var corn = 0; corn < 8; ++corn) { | |
prod.cp[corn] = a.cp[b.cp[corn]]; | |
var oriA = a.co[b.cp[corn]]; | |
var oriB = b.co[corn]; | |
var ori = oriA; | |
ori = ori + (oriA < 3?oriB:3 - oriB); | |
ori %= 3; | |
oriA < 3 ^ oriB < 3 && (ori += 3); | |
prod.co[corn] = ori; | |
} | |
} | |
function CubieCube_0(){ | |
$$init(this); | |
} | |
function CubieCube_1(cp, co, ep, eo){ | |
$$init(this); | |
for (var i = 0; i < 8; ++i) { | |
this.cp[i] = cp[i]; | |
this.co[i] = co[i]; | |
} | |
for (var 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){ | |
var sinv = CubeSym[SymInv[idx]]; | |
var s = CubeSym[idx]; | |
for (var ed=0; ed<12; ed++) { | |
b.ep[ed] = sinv.ep[a.ep[s.ep[ed]]]; | |
b.eo[ed] = (s.eo[ed] ^ a.eo[s.ep[ed]] ^ sinv.eo[a.ep[s.ep[ed]]]); | |
} | |
} | |
function EdgeMult(a, b, prod){ | |
for (var 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 idx = 0; | |
var val = 0x76543210; | |
for (var i = 0; i < 7; ++i) { | |
var v = arr[i] << 2; | |
idx = (8 - i) * idx + (val >> v & 7); | |
val -= 0x11111110 << v; | |
} | |
return idx; | |
} | |
function getNPerm(d,N){for(var c=0,a=0;N>a;a++){for(var e=0,b=0;N>b&&!(d[b]==a);b++)d[b]>a&&e++;c=c*(N-a)+e}return c}; | |
function initMove(){ | |
var mc = [];//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 (var m = 0; m < 6; ++m) { | |
mc[m*3] = moveCube[m]; | |
for (var p=0; p<2; ++p) { | |
mc[m * 3 + p + 1] = new CubieCube_0; | |
EdgeMult(mc[m * 3 + p], moveCube[m], mc[m * 3 + p + 1]); | |
CornMult(mc[m * 3 + p], moveCube[m], mc[m * 3 + p + 1]); | |
} | |
} | |
moveCube = mc; | |
} | |
function initSym(){ | |
var i, j, k, m, s, temp; | |
var c = new CubieCube_0; | |
var d = new CubieCube_0; | |
var f2 = new CubieCube_2(28783, 0, 259268407, 0); | |
var u4 = new CubieCube_2(15138, 0, 119765538, 1792); | |
var lr2 = new CubieCube_2(5167, 0, 83473207, 0); | |
lr2.co = [3, 3, 3, 3, 3, 3, 3, 3]; | |
CubeSym = [];//16); | |
for (i = 0; i < 16; ++i) { | |
CubeSym[i] = new CubieCube_3(c); | |
CornMult(c, u4, d); | |
EdgeMult(c, u4, d); | |
temp = d; | |
d = c; | |
c = temp; | |
if (i % 4 == 3) { | |
CornMult(temp, lr2, d); | |
EdgeMult(temp, lr2, d); | |
temp = d; | |
d = c; | |
c = temp; | |
} | |
if (i % 8 == 7) { | |
CornMult(temp, f2, d); | |
EdgeMult(temp, f2, d); | |
temp = d; | |
d = c; | |
c = temp; | |
} | |
} | |
SymInv = [];//Array(16); | |
SymMult = createArray(16, 16); | |
for (i = 0; i < 16; ++i) { | |
for (j = 0; j < 16; ++j) { | |
CornMult(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; | |
if (k==0) { | |
SymInv[i] = j; | |
} | |
break; | |
} | |
} | |
} | |
} | |
SymMove = createArray(16, 18); | |
for (j = 0; j < 18; ++j) { | |
for (s = 0; s < 16; ++s) { | |
CornConjugate(moveCube[j], SymInv[s], c); | |
CONTINUE: for (m = 0; m < 18; ++m) { | |
for (i = 0; i < 8; ++i) { | |
if (c.cp[i] != moveCube[m].cp[i] || c.co[i] != moveCube[m].co[i]) { | |
continue CONTINUE; | |
} | |
} | |
SymMove[s][j] = m; | |
} | |
} | |
} | |
Sym8Mult = createArray(8, 8); | |
Sym8Move = createArray(8, 18); | |
Sym8MultInv = createArray(8, 8); | |
SymMoveUD = createArray(16, 10); | |
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, count, idx, j, m; | |
var c = new CubieCube_0; | |
var d = new CubieCube_0; | |
var occ = createArray(1260); | |
var count = 0; | |
FlipS2R = []; | |
FlipR2S = []; | |
SymStateFlip = createArray(336); | |
for (var i = 0; i < 2048; ++i) { | |
if ((occ[i >>> 5] & 1 << (i & 31)) == 0) { | |
setFlip(c, i); | |
for (var s = 0; s < 16; s += 2) { | |
EdgeConjugate(c, s, d); | |
idx = getFlip(d); | |
if (idx == i) { | |
SymStateFlip[count] |= 1 << (s >> 1); | |
} | |
occ[idx >>> 5] |= 1 << (idx & 31); | |
FlipR2S[idx] = count << 3 | s >>> 1; | |
} | |
FlipS2R[count++] = i; | |
} | |
} | |
count = 0; | |
for (var i = 0; i < 69; i++)occ[i]=0; | |
TwistS2R = []; | |
TwistR2S = []; | |
SymStateTwist = createArray(324); | |
for (var i = 0; i < 2187; ++i) { | |
if ((occ[i >>> 5] & 1 << (i & 31)) == 0) { | |
setTwist(c, i); | |
for (var s = 0; s < 16; s += 2) { | |
CornConjugate(c, s, d); | |
idx = getTwist(d); | |
if (idx == i) { | |
SymStateTwist[count] |= 1 << (s >> 1); | |
} | |
occ[idx >>> 5] |= 1 << (idx & 31); | |
TwistR2S[idx] = count << 3 | s >>> 1; | |
} | |
TwistS2R[count++] = i; | |
} | |
} | |
merge = createArray(56, 56); | |
for (var i=0; i<40320; i++) { | |
set8Perm(c.ep, i); | |
merge[~~(getURtoUL(c)/6)][~~(getDRtoDL(c)/6)] = 1; | |
} | |
for (var i=0; i<56; i++) { | |
var count = 0; | |
for (var j=0; j<56; j++) { | |
if (merge[i][j] != 0) { | |
merge[i][j] = count++; | |
} | |
} | |
} | |
count = 0; | |
for (var i = 0; i < 1260; i++) occ[i] = 0; | |
PermS2R = []; | |
PermR2S = []; | |
MtoEPerm = []; | |
SymStatePerm = createArray(2768); | |
for (var i = 0; i < 40320; ++i) { | |
if ((occ[i >>> 5] & 1 << (i & 31)) == 0) { | |
set8Perm(c.ep, i); | |
for (var s = 0; s < 16; ++s) { | |
EdgeConjugate(c, s, d); | |
idx = get8Perm(d.ep); | |
if (idx == i) { | |
SymStatePerm[count] |= 1 << s; | |
} | |
occ[idx >>> 5] |= 1 << (idx & 31); | |
a = getURtoUL(d); | |
b = getDRtoDL(d); | |
m = merge[~~(a/6)][~~(b/6)] * 4032 + a * 12 + b % 6 * 2 + getNParity(8,idx); | |
MtoEPerm[m] = (count << 4 | s); | |
PermR2S[idx] = (count << 4 | s); | |
} | |
PermS2R[count++] = i; | |
} | |
} | |
} | |
function set8Perm(arr, idx){ | |
var val = 1985229328; | |
for (var i = 0; i < 7; ++i) { | |
var p = fact[7 - i]; | |
var v = ~~(idx / p); | |
var idx = idx - v * p; | |
v <<= 2; | |
arr[i] = (val >> v & 7); | |
var m = (1 << v) - 1; | |
val = (val & m) + (val >> 4 & ~m); | |
} | |
arr[7] = val; | |
} | |
function CubieCube(){ | |
} | |
var _ = CubieCube_3.prototype = CubieCube_2.prototype = CubieCube_0.prototype = CubieCube.prototype; | |
_.temps = null; | |
var initTime; | |
function $Solve(obj, c){ | |
initTime = new Date().getTime(); | |
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 obj.solution; | |
} | |
function $init2(obj){ | |
if (obj.solution != null && new Date().getTime() - initTime > 50) { | |
return true; | |
} | |
var cornx, edge, esym, ex, i, lm, m, mid, prun, s, sb, urf; | |
obj.valid2 = Math.min(obj.valid2, obj.valid1); | |
for (i = obj.valid1; i < obj.length1; ++i) { | |
m = obj.move[i]; | |
obj.corn[i + 1] = CPermMove[obj.corn[i]][SymMove[obj.csym[i]][m]]; | |
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]; | |
} | |
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; | |
if (new Date().getTime() - initTime < 50) { | |
return false; | |
} | |
return true; | |
} | |
} | |
return false; | |
} | |
function $phase1(obj, twist, tsym, flip, fsym, slice, maxl, lm){ | |
var flipx, fsymx, m, slicex, tsymx, twistx; | |
if (twist == 0 && flip == 0 && slice == 0 && maxl < 5) { | |
return maxl == 0 && $init2(obj); | |
} | |
for (m = 0; m < 18; ++m) { | |
if (ckmv[lm][m]) { | |
m += 2; | |
continue; | |
} | |
slicex = UDSliceMove[slice][m]; | |
twistx = TwistMove[twist][Sym8Move[tsym][m]]; | |
tsymx = Sym8Mult[twistx & 7][tsym]; | |
twistx >>>= 3; | |
if (UDSliceTwistPrun[twistx * 495 + UDSliceConj[slicex][tsymx]] >= maxl) { | |
continue; | |
} | |
flipx = FlipMove[flip][Sym8Move[fsym][m]]; | |
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; | |
obj.valid1 = Math.min(obj.valid1, obj.length1 - maxl); | |
if ($phase1(obj, twistx, tsymx, flipx, fsymx, slicex, maxl - 1, m)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
function $phase2(obj, edge, esym, corn, csym, mid, maxl, depth, lm){ | |
var cornx, csymx, edgex, esymx, m, midx; | |
if (edge == 0 && corn == 0 && mid == 0) { | |
return true; | |
} | |
for (m = 0; m < 10; ++m) { | |
if (ckmv2[lm][m]) { | |
continue; | |
} | |
midx = MPermMove[mid][m]; | |
edgex = EPermMove[edge][SymMoveUD[esym][m]]; | |
esymx = SymMult[edgex & 15][esym]; | |
edgex >>>= 4; | |
if (MEPermPrun[edgex * 24 + MPermConj[midx][esymx]] >= maxl) { | |
continue; | |
} | |
cornx = CPermMove[corn][SymMove[csym][ud2std[m]]]; | |
csymx = SymMult[cornx & 15][csym]; | |
cornx >>>= 4; | |
if (MCPermPrun[cornx * 24 + MPermConj[midx][csymx]] >= maxl) { | |
continue; | |
} | |
obj.move[depth] = ud2std[m]; | |
if ($phase2(obj, edgex, esymx, cornx, csymx, midx, maxl - 1, depth + 1, m)) { | |
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 = []; | |
this.corn = []; | |
this.csym = []; | |
this.mid3 = []; | |
this.e1 = []; | |
this.e2 = []; | |
this.twist = []; | |
this.tsym = []; | |
this.flip = []; | |
this.fsym = []; | |
this.slice_0 = []; | |
this.corn0 = []; | |
this.csym0 = []; | |
this.mid30 = []; | |
this.e10 = []; | |
this.e20 = []; | |
this.prun = []; | |
this.count = []; | |
this.f = []; | |
} | |
_ = 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; | |
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]]; | |
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'"]; | |
perm3 = [[11, 10, 9], [10, 11, 9], [11, 9, 10], [9, 11, 10], [10, 9, 11], [9, 10, 11]]; | |
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]]; | |
var i, j; | |
ud2std = [0, 1, 2, 4, 7, 9, 10, 11, 13, 16]; | |
std2ud = []; | |
for (i = 0; i < 10; ++i) { | |
std2ud[ud2std[i]] = i; | |
} | |
ckmv = createArray(19, 18); | |
ckmv2 = createArray(11, 10); | |
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; | |
} | |
Cnk = createArray(12, 12); | |
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]; | |
} | |
} | |
parity4 = [];//24); | |
for (i = 0; i < 24; ++i) { | |
parity4[i] = getNParity(4,i); | |
} | |
initMove(); | |
initSym(); | |
initSym2Raw(); | |
initCPermMove(); | |
initEPermMove(); | |
initFlipMove(); | |
initTwistMove(); | |
initUDSliceMoveConj(); | |
initMid3Move(); | |
initMid32MPerm(); | |
initCParity(); | |
initMPermMoveConj(); | |
initTwistFlipSlicePrun(safeStatusCallback); | |
initMCEPermPrun(safeStatusCallback); | |
inited = true; | |
} | |
var inited = false; | |
function bitCount(i){ | |
i = i - (i >>> 1 & 1431655765); | |
i = (i & 858993459) + (i >>> 2 & 858993459); | |
return i + (i >>> 8) + (i >>> 4) & 15; | |
} | |
function getNParity(n, idx){ | |
var p = 0; | |
for (var i = n-2; i >= 0; --i) { | |
p ^= idx % (n - i); | |
idx = ~~(idx / (n - 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 = [];//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); | |
} | |
/* Methods added by Lucas. */ | |
var randomSource = Math; | |
var initialized = false; | |
function ini(iniRandomSource, statusCallback) { | |
if (typeof statusCallback != "function") { | |
statusCallback = function() {}; | |
} | |
if (!initialized) { | |
search = new Search; | |
init_0(statusCallback); | |
randomSource = iniRandomSource; | |
initialized = true; | |
} | |
} | |
// SCRAMBLERS | |
function rn(n) { | |
return ~~(randomSource.random() * n); | |
} | |
var search; | |
function getRandomScramble() { | |
ini(Math); | |
var cperm, eperm = rn(479001600); | |
do { | |
cperm = rn(40320); | |
} while ((getNParity(8,cperm) ^ getNParity(12,eperm)) != 0); | |
var posit = toFaceCube(new CubieCube_2(cperm, rn(2187), eperm, rn(2048))); | |
var solution = $solution(search, posit); | |
return solution; | |
} | |
function cntU(b){for(var c=0,a=0;a<b.length;a++)-1==b[a]&&c++;return c}; | |
function fixOri(arr, cntU, base) { | |
var sum = 0; | |
var idx = 0; | |
for (var i=0; i<arr.length-1; i++) { | |
if (arr[i] == -1) { | |
if (cntU-- == 1) { | |
arr[i] = ((base << 4) - sum) % base; | |
} else { | |
arr[i] = rn(base); | |
} | |
} | |
sum += arr[i]; | |
idx *= base; | |
idx += arr[i]; | |
} | |
return idx; | |
} | |
function fixPerm(arr, cntU, parity) { | |
var val = [0,1,2,3,4,5,6,7,8,9,10,11]; | |
for (var i=0; i<arr.length; i++) { | |
if (arr[i] != -1) { | |
val[arr[i]] = -1; | |
} | |
} | |
for (var i=0, j=0; i<val.length; i++) { | |
if (val[i] != -1) { | |
val[j++] = val[i]; | |
} | |
} | |
var last; | |
for (var i=0; i<arr.length && cntU>0; i++) { | |
if (arr[i] == -1) { | |
var r = rn(cntU); | |
arr[i] = val[r]; | |
for (var j=r; j<11; j++) { | |
val[j] = val[j+1]; | |
} | |
if (cntU-- == 2) { | |
last = i; | |
} | |
} | |
} | |
if (getNParity(arr.length, getNPerm(arr, arr.length)) == 1-parity) { | |
var temp = arr[i-1]; | |
arr[i-1] = arr[last]; | |
arr[last] = temp; | |
} | |
return getNPerm(arr, arr.length); | |
} | |
function getAnyScramble(ep, eo, cp, co) { | |
ini(Math); | |
eo.reverse(); | |
eo.push(eo.shift()); | |
var neo = fixOri(eo, cntU(eo), 2); | |
var nco = fixOri(co, cntU(co), 3); | |
var nep, ncp; | |
var ue = cntU(ep); | |
var uc = cntU(cp); | |
if (ue==0 && uc==0) { | |
nep = getNPerm(ep, 12); | |
ncp = getNPerm(cp, 8); | |
} else if (ue!=0 && uc==0) { | |
ncp = getNPerm(cp, 8); | |
nep = fixPerm(ep, ue, getNParity(8, ncp)); | |
} else if (ue==0 && uc!=0) { | |
nep = getNPerm(ep, 12); | |
ncp = fixPerm(cp, uc, getNParity(12, nep)); | |
} else { | |
nep = fixPerm(ep, ue, -1); | |
ncp = fixPerm(cp, uc, getNParity(12, nep)); | |
} | |
var posit = toFaceCube(new CubieCube_2(ncp, nco, nep, neo)); | |
var solution = $solution(search, posit); | |
return solution; | |
} | |
function getEdgeScramble() { | |
return getAnyScramble([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], | |
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],[0,1,2,3,4,5,6,7],[0,0,0,0,0,0,0,0]); | |
} | |
function getCornerScramble() { | |
return getAnyScramble([0,1,2,3,4,5,6,7,8,9,10,11], | |
[0,0,0,0,0,0,0,0,0,0,0,0],[-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1]); | |
} | |
function getLLScramble() { | |
return getAnyScramble([-1,-1,-1,-1,4,5,6,7,8,9,10,11], | |
[-1,-1,-1,-1,0,0,0,0,0,0,0,0],[-1,-1,-1,-1,4,5,6,7],[-1,-1,-1,-1,0,0,0,0]); | |
} | |
function getLSLLScramble() { | |
return getAnyScramble([-1,-1,-1,-1,4,5,6,7,-1,9,10,11], | |
[-1,-1,-1,-1,0,0,0,0,-1,0,0,0],[-1,-1,-1,-1,-1,5,6,7],[-1,-1,-1,-1,-1,0,0,0]); | |
} | |
function getF2LScramble() { | |
return getAnyScramble([-1,-1,-1,-1,4,5,6,7,-1,-1,-1,-1], | |
[-1,-1,-1,-1,0,0,0,0,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1,-1,-1]); | |
} | |
function getZBLLScramble() { | |
return getAnyScramble([-1,-1,-1,-1,4,5,6,7,8,9,10,11], | |
[0,0,0,0,0,0,0,0,0,0,0,0],[-1,-1,-1,-1,4,5,6,7],[-1,-1,-1,-1,0,0,0,0]); | |
} | |
function getLSEScramble() { | |
switch (rn(4)) { | |
case 0: return getAnyScramble([-1,-1,-1,-1,4,-1,6,-1,8,9,10,11],[-1,-1,-1,-1,0,-1,0,-1,0,0,0,0],[0,1,2,3,4,5,6,7],[0,0,0,0,0,0,0,0]); | |
case 1: return getAnyScramble([-1,-1,-1,-1,8,-1,9,-1,0,2,6,4],[0,-1,0,-1,0,-1,0,-1,0,0,-1,-1],[3,2,6,7,0,1,5,4],[2,1,2,1,1,2,1,2])+"x'"; | |
case 2: return getAnyScramble([-1,-1,-1,-1,0,-1,2,-1,11,10,9,8],[0,-1,0,-1,-1,-1,-1,-1,0,0,0,0],[7,6,5,4,3,2,1,0],[0,0,0,0,0,0,0,0])+"x2"; | |
case 3: return getAnyScramble([-1,-1,-1,-1,11,-1,10,-1,4,6,2,0],[0,-1,0,-1,0,-1,0,-1,-1,-1,0,0],[4,5,1,0,7,6,2,3],[2,1,2,1,1,2,1,2])+"x"; | |
} | |
} | |
function getCMLLScramble() { | |
switch (rn(4)) { | |
case 0: return getAnyScramble([-1,-1,-1,-1,4,-1,6,-1,8,9,10,11],[-1,-1,-1,-1,0,-1,0,-1,0,0,0,0],[-1,-1,-1,-1,4,5,6,7],[-1,-1,-1,-1,0,0,0,0]); | |
case 1: return getAnyScramble([-1,-1,-1,-1,8,-1,9,-1,0,2,6,4],[0,-1,0,-1,0,-1,0,-1,0,0,-1,-1],[-1,-1,-1,-1,0,1,5,4],[2,1,-1,-1,1,2,-1,-1])+"x'"; | |
case 2: return getAnyScramble([-1,-1,-1,-1,0,-1,2,-1,11,10,9,8],[0,-1,0,-1,-1,-1,-1,-1,0,0,0,0],[-1,-1,-1,-1,3,2,1,0],[0,0,0,0,-1,-1,-1,-1])+"x2"; | |
case 3: return getAnyScramble([-1,-1,-1,-1,11,-1,10,-1,4,6,2,0],[0,-1,0,-1,0,-1,0,-1,-1,-1,0,0],[-1,-1,-1,-1,7,6,2,3],[-1,-1,2,1,-1,-1,1,2])+"x"; | |
} | |
} | |
function getCLLScramble() { | |
return getAnyScramble([0,1,2,3,4,5,6,7,8,9,10,11],[0,0,0,0,0,0,0,0,0,0,0,0],[-1,-1,-1,-1,4,5,6,7],[-1,-1,-1,-1,0,0,0,0]); | |
} | |
function getELLScramble() { | |
return getAnyScramble([-1,-1,-1,-1,4,5,6,7,8,9,10,11],[-1,-1,-1,-1,0,0,0,0,0,0,0,0],[0,1,2,3,4,5,6,7],[0,0,0,0,0,0,0,0]); | |
} | |
return { | |
/* mark2 interface */ | |
getRandomScramble: getRandomScramble,//getRandomScramble, | |
/* added methods */ | |
getEdgeScramble: getEdgeScramble, | |
getCornerScramble: getCornerScramble, | |
getLLScramble: getLLScramble, | |
getLSLLScramble: getLSLLScramble, | |
getZBLLScramble: getZBLLScramble, | |
getF2LScramble: getF2LScramble, | |
getLSEScramble: getLSEScramble, | |
getCMLLScramble: getCMLLScramble, | |
getCLLScramble: getCLLScramble, | |
getELLScramble: getELLScramble, | |
getAnyScramble: getAnyScramble | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment