scramby
Version:
Generates scrambles for twisty puzzles.
2,015 lines (1,902 loc) • 45.9 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(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(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(callback, _, statusCallback) {
if (initialized) {
return
}
if (typeof statusCallback !== 'function') {
statusCallback = function() {}
}
search = new Search()
init_0(statusCallback)
initialized = true
if (callback) setTimeout(callback, 0)
}
var getRandomScramble = function() {
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