private bool Phase2(int eidx, int esym, int cidx, int csym, int mid, int maxl, int depth, int lm) { if (maxl == 0) { // We've done the last move we're allowed to do, make sure it's permitted // by lastAxisRestriction. if (lastAxisRestriction != -1) { int stdLm = CubieCube.URFMove[urfIdx][Util.Ud2std[lm]]; int lastAxis = (stdLm / 3) * 3; if (lastAxisRestriction == lastAxis || lastAxisRestriction == lastAxis + 9) { return(false); } } return(eidx == 0 && cidx == 0 && mid == 0); } for (int m = 0; m < 10; m++) { if (Util.Ckmv2[lm][m]) { continue; } int midx = CoordCube.MPermMove[mid][m]; int cidxx = CoordCube.CPermMove[cidx][CubieCube.SymMove[csym][Util.Ud2std[m]]]; int csymx = CubieCube.SymMult[cidxx & 15][csym]; cidxx = (int)((uint)cidxx >> 4); if (CoordCube.GetPruning(CoordCube.MCPermPrun, cidxx * 24 + CoordCube.MPermConj[midx][csymx]) >= maxl) { continue; } int eidxx = CoordCube.EPermMove[eidx][CubieCube.SymMoveUD[esym][m]]; int esymx = CubieCube.SymMult[eidxx & 15][esym]; eidxx = (int)((uint)eidxx >> 4); if (CoordCube.GetPruning(CoordCube.MEPermPrun, eidxx * 24 + CoordCube.MPermConj[midx][esymx]) >= maxl) { continue; } if (Phase2(eidxx, esymx, cidxx, csymx, midx, maxl - 1, depth + 1, m)) { move[depth] = Util.Ud2std[m]; return(true); } } return(false); }
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 } }
/** * @return * 0: Found or Timeout * 1: Try Next Power * 2: Try Next Axis */ private int Phase1(int twist, int tsym, int flip, int fsym, int slice, int maxl, int lastAxis) { if (twist == 0 && flip == 0 && slice == 0 && maxl < 5) { return(maxl == 0 ? InitPhase2() : 1); } for (int axis = 0; axis < 18; axis += 3) { if (axis == lastAxis || axis == lastAxis - 9) { continue; } for (int power = 0; power < 3; power++) { int m = axis + power; int slicex = CoordCube.UDSliceMove[slice][m] & 0x1ff; int twistx = CoordCube.TwistMove[twist][CubieCube.Sym8Move[tsym][m]]; int tsymx = CubieCube.Sym8Mult[twistx & 7][tsym]; twistx = (int)((uint)twistx >> 3); int prun = CoordCube.GetPruning(CoordCube.UDSliceTwistPrun, twistx * 495 + CoordCube.UDSliceConj[slicex][tsymx]); if (prun > maxl) { break; } else if (prun == maxl) { continue; } int flipx = CoordCube.FlipMove[flip][CubieCube.Sym8Move[fsym][m]]; int fsymx = CubieCube.Sym8Mult[flipx & 7][fsym]; flipx = (int)((uint)flipx >> 3); if (Tools.USE_TWIST_FLIP_PRUN) { prun = CoordCube.GetPruning(CoordCube.TwistFlipPrun, (twistx * 336 + flipx) << 3 | CubieCube.Sym8MultInv[fsymx][tsymx]); if (prun > maxl) { break; } else if (prun == maxl) { continue; } } prun = CoordCube.GetPruning(CoordCube.UDSliceFlipPrun, flipx * 495 + CoordCube.UDSliceConj[slicex][fsymx]); if (prun > maxl) { break; } else if (prun == maxl) { continue; } move[depth1 - maxl] = m; valid1 = Math.Min(valid1, depth1 - maxl); int ret = Phase1(twistx, tsymx, flipx, fsymx, slicex, maxl - 1, axis); if (ret != 1) { return(ret >> 1); } } } return(1); }
/** * @return * 0: Found or Timeout * 1: Try Next Power * 2: Try Next Axis */ private int InitPhase2() { if (Environment.TickCount >= (solution == null ? timeOut : timeMin)) { return(0); } valid2 = Math.Min(valid2, valid1); int cidx = (int)((uint)corn[valid1] >> 4); int csym = corn[valid1] & 0xf; for (int i = valid1; i < depth1; i++) { int m = move[i]; cidx = CoordCube.CPermMove[cidx][CubieCube.SymMove[csym][m]]; csym = CubieCube.SymMult[cidx & 0xf][csym]; cidx = (int)((uint)cidx >> 4); corn[i + 1] = cidx << 4 | csym; int cx = CoordCube.UDSliceMove[mid4[i] & 0x1ff][m]; mid4[i + 1] = Util.PermMult[(uint)mid4[i] >> 9][(uint)cx >> 9] << 9 | cx & 0x1ff; } valid1 = depth1; int mid = (int)((uint)mid4[depth1] >> 9); int prun = CoordCube.GetPruning(CoordCube.MCPermPrun, cidx * 24 + CoordCube.MPermConj[mid][csym]); if (prun >= maxDep2) { return(prun > maxDep2 ? 2 : 1); } int u4e = (int)((uint)ud8e[valid2] >> 16); int d4e = ud8e[valid2] & 0xffff; for (int i = valid2; i < depth1; i++) { int m = move[i]; int cx = CoordCube.UDSliceMove[u4e & 0x1ff][m]; u4e = Util.PermMult[(uint)u4e >> 9][(uint)cx >> 9] << 9 | cx & 0x1ff; cx = CoordCube.UDSliceMove[d4e & 0x1ff][m]; d4e = Util.PermMult[(uint)d4e >> 9][(uint)cx >> 9] << 9 | cx & 0x1ff; ud8e[i + 1] = u4e << 16 | d4e; } valid2 = depth1; int edge = CubieCube.MtoEPerm[494 - (u4e & 0x1ff) + ((int)((uint)u4e >> 9)) * 70 + ((int)((uint)d4e >> 9)) * 1680]; int esym = edge & 15; edge = (int)((uint)edge >> 4); prun = Math.Max(CoordCube.GetPruning(CoordCube.MEPermPrun, edge * 24 + CoordCube.MPermConj[mid][esym]), prun); if (prun >= maxDep2) { return(prun > maxDep2 ? 2 : 1); } int firstAxisRestrictionUd = firstAxisRestriction == -1 ? 10 : Util.Std2ud[CubieCube.URFMoveInv[urfIdx][firstAxisRestriction] / 3 * 3 + 1]; int lm = depth1 == 0 ? firstAxisRestrictionUd : Util.Std2ud[move[depth1 - 1] / 3 * 3 + 1]; for (int depth2 = prun; depth2 < maxDep2; depth2++) { if (Phase2(edge, esym, cidx, csym, mid, depth2, depth1, lm)) { sol = depth1 + depth2; maxDep2 = Math.Min(12, sol - depth1); solution = SolutionToString(); return(Environment.TickCount >= timeMin ? 0 : 1); } } return(1); }
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); }