internal static void InitTwistSym2Raw() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); int[] occ = new int[2187 / 32 + 1]; int count = 0; for (int i = 0; i < 2187 / 32 + 1; occ[i++] = 0) { ; } TwistR2S = new char[2187]; for (int i = 0; i < 2187; i++) { if ((occ[i >> 5] & (1 << (i & 0x1f))) == 0) { c.SetTwist(i); for (int s = 0; s < 16; s += 2) { CornConjugate(c, s, d); int idx = d.GetTwist(); if (idx == i) { SymStateTwist[count] |= (char)(1 << (s >> 1)); } occ[idx >> 5] |= 1 << (idx & 0x1f); TwistR2S[idx] = (char)((count << 3) | (s >> 1)); } TwistS2R[count++] = (char)i; } } }
internal static void InitFlipSym2Raw() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); int[] occ = new int[2048 >> 5]; int count = 0; for (int i = 0; i < 2048 >> 5; occ[i++] = 0) { ; } FlipR2S = new char[2048]; for (int i = 0; i < 2048; i++) { if ((occ[i >> 5] & (1 << (i & 0x1f))) == 0) { c.SetFlip(i); for (int s = 0; s < 16; s += 2) { EdgeConjugate(c, s, d); int idx = d.GetFlip(); if (idx == i) { SymStateFlip[count] |= (char)(1 << (s >> 1)); } occ[idx >> 5] |= 1 << (idx & 0x1f); FlipR2S[idx] = (char)((count << 3) | (s >> 1)); } FlipS2R[count++] = (char)i; } } }
internal static string ToFaceCube(CubieCube cc) { char[] f = new char[54]; char[] ts = { 'U', 'R', 'F', 'D', 'L', 'B' }; for (int i = 0; i < 54; i++) { f[i] = ts[i / 9]; } for (sbyte c = 0; c < 8; c++) { sbyte j = cc.CP[c]; // cornercubie with index j is at // cornerposition with index c sbyte ori = cc.CO[c]; // Orientation of this cubie for (sbyte n = 0; n < 3; n++) { f[CornerFacelet[c][(n + ori) % 3]] = ts[CornerFacelet[j][n] / 9]; } } for (sbyte e = 0; e < 12; e++) { sbyte j = cc.EP[e]; // edgecubie with index j is at edgeposition // with index e sbyte ori = cc.EO[e]; // Orientation of this cubie for (sbyte n = 0; n < 2; n++) { f[EdgeFacelet[e][(n + ori) % 2]] = ts[EdgeFacelet[j][n] / 9]; } } return(new string(f)); }
internal static void InitUDSliceMoveConj() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_SLICE; i++) { c.SetUDSlice(i); for (int j = 0; j < N_MOVES; j += 3) { CubieCube.EdgeMult(c, CubieCube.MoveCube[j], d); UDSliceMove[i][j] = (char)d.GetUDSlice(); } for (uint j = 0; j < 16; j += 2) { CubieCube.EdgeConjugate(c, CubieCube.SymInv[j], d); UDSliceConj[i][j >> 1] = (char)(d.GetUDSlice() & 0x1ff); } } for (int i = 0; i < N_SLICE; i++) { for (int j = 0; j < N_MOVES; j += 3) { int udslice = UDSliceMove[i][j]; for (int k = 1; k < 3; k++) { int cx = UDSliceMove[udslice & 0x1ff][j]; udslice = Util.PermMult[(uint)udslice >> 9][((uint)cx >> 9)] << 9 | cx & 0x1ff; UDSliceMove[i][j + k] = (char)(udslice); } } } }
internal static void ToCubieCube(sbyte[] f, CubieCube ccRet) { sbyte ori; for (int i = 0; i < 8; i++) { ccRet.CP[i] = 0;// invalidate corners } for (int i = 0; i < 12; i++) { ccRet.EP[i] = 0;// and edges } sbyte col1, col2; for (sbyte i = 0; i < 8; i++) { // get the colors of the cubie at corner i, starting with U/D for (ori = 0; ori < 3; ori++) { if (f[CornerFacelet[i][ori]] == U || f[CornerFacelet[i][ori]] == D) { break; } } col1 = f[CornerFacelet[i][(ori + 1) % 3]]; col2 = f[CornerFacelet[i][(ori + 2) % 3]]; for (sbyte j = 0; j < 8; j++) { if (col1 == CornerFacelet[j][1] / 9 && col2 == CornerFacelet[j][2] / 9) { // in cornerposition i we have cornercubie j ccRet.CP[i] = j; ccRet.CO[i] = (sbyte)(ori % 3); break; } } } for (sbyte i = 0; i < 12; i++) { for (sbyte j = 0; j < 12; j++) { if (f[EdgeFacelet[i][0]] == EdgeFacelet[j][0] / 9 && f[EdgeFacelet[i][1]] == EdgeFacelet[j][1] / 9) { ccRet.EP[i] = j; ccRet.EO[i] = 0; break; } if (f[EdgeFacelet[i][0]] == EdgeFacelet[j][1] / 9 && f[EdgeFacelet[i][1]] == EdgeFacelet[j][0] / 9) { ccRet.EP[i] = j; ccRet.EO[i] = 1; break; } } } }
internal static void EdgeMult(CubieCube a, CubieCube b, CubieCube prod) { for (int ed = 0; ed < 12; ed++) { prod.EP[ed] = a.EP[b.EP[ed]]; prod.EO[ed] = (sbyte)(b.EO[ed] ^ a.EO[b.EP[ed]]); } }
internal void URFConjugate() { if (temps == null) { temps = new CubieCube(); } CornMult(URF2, this, temps); CornMult(temps, URF1, this); EdgeMult(URF2, this, temps); EdgeMult(temps, URF1, this); }
internal static void EdgeConjugate(CubieCube a, int idx, CubieCube b) { CubieCube sinv = CubeSym[SymInv[idx]]; CubieCube s = CubeSym[idx]; for (int ed = 0; ed < 12; ed++) { b.EP[ed] = sinv.EP[a.EP[s.EP[ed]]]; b.EO[ed] = (sbyte)(s.EO[ed] ^ a.EO[s.EP[ed]] ^ sinv.EO[a.EP[s.EP[ed]]]); } }
internal static void CornConjugate(CubieCube a, int idx, CubieCube b) { CubieCube sinv = CubeSym[SymInv[idx]]; CubieCube s = CubeSym[idx]; for (int corn = 0; corn < 8; corn++) { b.CP[corn] = sinv.CP[a.CP[s.CP[corn]]]; sbyte oriA = sinv.CO[a.CP[s.CP[corn]]]; sbyte oriB = a.CO[s.CP[corn]]; b.CO[corn] = (oriA < 3) ? oriB : (sbyte)((3 - oriB) % 3); } }
private void Copy(CubieCube c) { for (int i = 0; i < 8; i++) { CP[i] = c.CP[i]; CO[i] = c.CO[i]; } for (int i = 0; i < 12; i++) { EP[i] = c.EP[i]; EO[i] = c.EO[i]; } }
internal static void InitFlipMove() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_FLIP_SYM; i++) { c.SetFlip(CubieCube.FlipS2R[i]); for (int j = 0; j < N_MOVES; j++) { CubieCube.EdgeMult(c, CubieCube.MoveCube[j], d); FlipMove[i][j] = (char)d.GetFlipSym(); } } }
internal static void InitTwistMove() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_TWIST_SYM; i++) { c.SetTwist(CubieCube.TwistS2R[i]); for (int j = 0; j < N_MOVES; j++) { CubieCube.CornMult(c, CubieCube.MoveCube[j], d); TwistMove[i][j] = (char)d.GetTwistSym(); } } }
internal static void InitCPermMove() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_PERM_SYM; i++) { c.SetCPerm(CubieCube.EPermS2R[i]); for (int j = 0; j < N_MOVES; j++) { CubieCube.CornMult(c, CubieCube.MoveCube[j], d); CPermMove[i][j] = (char)d.GetCPermSym(); } } }
internal static void InitEPermMove() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_PERM_SYM; i++) { c.SetEPerm(CubieCube.EPermS2R[i]); for (int j = 0; j < N_MOVES2; j++) { CubieCube.EdgeMult(c, CubieCube.MoveCube[Util.Ud2std[j]], d); EPermMove[i][j] = (char)d.GetEPermSym(); } } }
internal static void CornMult(CubieCube a, CubieCube b, CubieCube prod) { for (int corn = 0; corn < 8; corn++) { prod.CP[corn] = a.CP[b.CP[corn]]; sbyte oriA = a.CO[b.CP[corn]]; sbyte oriB = b.CO[corn]; sbyte ori = oriA; ori += (oriA < 3) ? oriB : (sbyte)(6 - oriB); ori %= 3; if ((oriA >= 3) ^ (oriB >= 3)) { ori += 3; } prod.CO[corn] = ori; } }
// ********************************************* Initialization functions ********************************************* internal static void InitMove() { MoveCube[0] = new CubieCube(15120, 0, 119750400, 0); MoveCube[3] = new CubieCube(21021, 1494, 323403417, 0); MoveCube[6] = new CubieCube(8064, 1236, 29441808, 550); MoveCube[9] = new CubieCube(9, 0, 5880, 0); MoveCube[12] = new CubieCube(1230, 412, 2949660, 0); MoveCube[15] = new CubieCube(224, 137, 328552, 137); for (int a = 0; a < 18; a += 3) { for (int p = 0; p < 2; p++) { MoveCube[a + p + 1] = new CubieCube(); EdgeMult(MoveCube[a + p], MoveCube[a], MoveCube[a + p + 1]); CornMult(MoveCube[a + p], MoveCube[a], MoveCube[a + p + 1]); } } }
internal static void InitMPermMoveConj() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_MPERM; i++) { c.SetMPerm(i); for (int j = 0; j < N_MOVES2; j++) { CubieCube.EdgeMult(c, CubieCube.MoveCube[Util.Ud2std[j]], d); MPermMove[i][j] = (char)d.GetMPerm(); } for (int j = 0; j < 16; j++) { CubieCube.EdgeConjugate(c, CubieCube.SymInv[j], d); MPermConj[i][j] = (char)d.GetMPerm(); } } }
private static void InitIdx(int idx) { switch (idx) { case 0: CubieCube.InitMove(); break; //- case 1: CubieCube.InitSym(); break; //0 case 2: CubieCube.InitFlipSym2Raw(); break; //1 case 3: CubieCube.InitTwistSym2Raw(); break; //1 case 4: CubieCube.InitPermSym2Raw(); break; //1 case 5: CoordCube.InitFlipMove(); break; //0, 1, 2 case 6: CoordCube.InitTwistMove(); break; //0, 1, 3 case 7: CoordCube.InitUDSliceMoveConj(); break; //0, 1 case 8: CoordCube.InitCPermMove(); break; //0, 1, 4 case 9: CoordCube.InitEPermMove(); break; //0, 1, 4 case 10: CoordCube.InitMPermMoveConj(); break; //0, 1 case 11: if (USE_TWIST_FLIP_PRUN) { CoordCube.InitTwistFlipPrun(); } break; //1, 2, 3, 5, 6 case 12: CoordCube.InitSliceTwistPrun(); break; //1, 3, 6, 7 case 13: CoordCube.InitSliceFlipPrun(); break; //1, 2, 5, 7 case 14: CoordCube.InitMEPermPrun(); break; //1, 4, 9, 10 case 15: CoordCube.InitMCPermPrun(); break; //1, 4, 8, 10 } }
internal int GetTwistSym() { if (TwistR2S != null) { return(TwistR2S[GetTwist()]); } if (temps == null) { temps = new CubieCube(); } for (int k = 0; k < 16; k += 2) { CornConjugate(this, SymInv[k], temps); int idx = Util.BinarySearch(TwistS2R, temps.GetTwist()); if (idx != 0xffff) { return((idx << 3) | (k >> 1)); } } return(0); }
internal int GetEPermSym() { if (EPermR2S != null) { return(EPermR2S[GetEPerm()]); } if (temps == null) { temps = new CubieCube(); } for (int k = 0; k < 16; k++) { EdgeConjugate(this, SymInv[k], temps); int idx = Util.BinarySearch(EPermS2R, temps.GetEPerm()); if (idx != 0xffff) { return((idx << 4) | k); } } return(0); }
internal int GetCPermSym() { if (EPermR2S != null) { int idx = EPermR2S[GetCPerm()]; idx ^= E2C[idx & 0x0f]; return(idx); } if (temps == null) { temps = new CubieCube(); } for (int k = 0; k < 16; k++) { CornConjugate(this, SymInv[k], temps); int idx = Util.BinarySearch(EPermS2R, temps.GetCPerm()); if (idx != 0xffff) { return((idx << 4) | k); } } return(0); }
internal static void InitPermSym2Raw() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); int[] occ = new int[40320 / 32]; int count = 0; for (int i = 0; i < 40320 / 32; occ[i++] = 0) { ; } EPermR2S = new char[40320]; for (int i = 0; i < 40320; i++) { if ((occ[i >> 5] & (1 << (i & 0x1f))) == 0) { c.SetEPerm(i); for (int s = 0; s < 16; s++) { EdgeConjugate(c, s, d); int idx = d.GetEPerm(); if (idx == i) { SymStatePerm[count] |= (char)(1 << s); } occ[idx >> 5] |= 1 << (idx & 0x1f); int a = d.GetU4Comb(); int b = d.GetD4Comb() >> 9; int m = 494 - (a & 0x1ff) + (a >> 9) * 70 + b * 1680; MtoEPerm[m] = EPermR2S[idx] = (char)(count << 4 | s); } EPermS2R[count++] = (char)i; } } }
private string Solve(CubieCube c) { Tools.Init(); int conjMask = 0; for (int i = 0; i < 6; i++) { twist[i] = c.GetTwistSym(); flip[i] = c.GetFlipSym(); slice[i] = c.GetUDSlice(); corn0[i] = c.GetCPermSym(); ud8e0[i] = c.GetU4Comb() << 16 | c.GetD4Comb(); for (int j = 0; j < i; j++) { //If S_i^-1 * C * S_i == C, It's unnecessary to compute it again. if (twist[i] == twist[j] && flip[i] == flip[j] && slice[i] == slice[j] && corn0[i] == corn0[j] && ud8e0[i] == ud8e0[j]) { conjMask |= 1 << i; break; } } if ((conjMask & (1 << i)) == 0) { prun[i] = Math.Max(Math.Max( CoordCube.GetPruning(CoordCube.UDSliceTwistPrun, ((int)(twist[i] >> 3)) * 495 + CoordCube.UDSliceConj[slice[i] & 0x1ff][twist[i] & 7]), CoordCube.GetPruning(CoordCube.UDSliceFlipPrun, ((int)((uint)flip[i] >> 3)) * 495 + CoordCube.UDSliceConj[slice[i] & 0x1ff][flip[i] & 7])), Tools.USE_TWIST_FLIP_PRUN ? CoordCube.GetPruning(CoordCube.TwistFlipPrun, ((int)(twist[i] >> 3)) * 2688 + (flip[i] & 0xfff8 | CubieCube.Sym8MultInv[flip[i] & 7][twist[i] & 7])) : 0); } c.URFConjugate(); if (i == 2) { c.InvCubieCube(); } } for (depth1 = 0; depth1 < sol; depth1++) { maxDep2 = Math.Min(12, sol - depth1); for (urfIdx = 0; urfIdx < 6; urfIdx++) { if ((firstAxisRestriction != -1 || lastAxisRestriction != -1) && urfIdx >= 3) { // When urfIdx >= 3, we're solving the // inverse cube. This doesn't work // when we're also restricting the // first turn, so we just skip inverse // solutions when firstAxisRestriction has // been set. continue; } if ((conjMask & (1 << urfIdx)) != 0) { continue; } corn[0] = corn0[urfIdx]; mid4[0] = slice[urfIdx]; ud8e[0] = ud8e0[urfIdx]; valid1 = 0; int lm = firstAxisRestriction == -1 ? -1 : CubieCube.URFMoveInv[urfIdx][firstAxisRestriction] / 3 * 3; if ((prun[urfIdx] <= depth1) && Phase1((int)((uint)twist[urfIdx] >> 3), twist[urfIdx] & 7, (int)((uint)flip[urfIdx] >> 3), flip[urfIdx] & 7, slice[urfIdx] & 0x1ff, depth1, lm) == 0) { return(solution == null ? "Error 8" : solution); } } } return(solution == null ? "Error 7" : solution); }
internal CubieCube(CubieCube c) { Copy(c); }
internal static void InitSym() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); CubieCube t; CubieCube f2 = new CubieCube(28783, 0, 259268407, 0); CubieCube u4 = new CubieCube(15138, 0, 119765538, 7); CubieCube lr2 = new CubieCube(5167, 0, 83473207, 0); lr2.CO = new sbyte[] { 3, 3, 3, 3, 3, 3, 3, 3 }; for (int i = 0; i < 16; i++) { CubeSym[i] = new CubieCube(c); CornMult(c, u4, d); EdgeMult(c, u4, d); t = d; d = c; c = t; if (i % 4 == 3) { CornMult(c, lr2, d); EdgeMult(c, lr2, d); t = d; d = c; c = t; } if (i % 8 == 7) { CornMult(c, f2, d); EdgeMult(c, f2, d); t = d; d = c; c = t; } } for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { CornMult(CubeSym[i], CubeSym[j], c); for (int 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; } } } } for (int j = 0; j < 18; j++) { for (int s = 0; s < 16; s++) { CornConjugate(MoveCube[j], SymInv[s], c); for (int m = 0; m < 18; m++) { for (int i = 0; i < 8; i += 2) { if (c.CP[i] != MoveCube[m].CP[i]) { goto CONTINUE; } } SymMove[s][j] = m; break; CONTINUE : { } } } } for (int j = 0; j < 10; j++) { for (int s = 0; s < 16; s++) { SymMoveUD[s][j] = Util.Std2ud[SymMove[s][Util.Ud2std[j]]]; } } for (int j = 0; j < 8; j++) { for (int s = 0; s < 8; s++) { Sym8Mult[j][s] = SymMult[j << 1][s << 1] >> 1; Sym8MultInv[j][s] = SymMult[j << 1][SymInv[s << 1]] >> 1; } } for (int j = 0; j < 18; j++) { for (int s = 0; s < 8; s++) { Sym8Move[s][j] = SymMove[s << 1][j]; } } }