//-1: no solution found // X: solution with X moves shorter than expectation. Hence, the length of the solution is depth - X private int phase2(int eidx, int esym, int cidx, int csym, int mid, int maxl, int depth, int lm) { if (eidx == 0 && cidx == 0 && mid == 0) { return(maxl); } for (int m = 0; m < 10; m++) { if (lm < 0 ? (m == -lm) : 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 & 0xf, csym]; 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 & 0xf, esym]; eidxx >>= 4; if (CoordCube.getPruning(CoordCube.EPermCCombPrun, eidxx * 70 + CoordCube.CCombConj[CubieCube.Perm2Comb[cidxx], CubieCube.SymMultInv[esymx, csymx]]) >= maxl) { continue; } if (CoordCube.getPruning(CoordCube.MEPermPrun, eidxx * 24 + CoordCube.MPermConj[midx, esymx]) >= maxl) { continue; } int ret = phase2(eidxx, esymx, cidxx, csymx, midx, maxl - 1, depth + 1, (lm < 0 && m + lm == -5) ? -lm : m); if (ret >= 0) { move[depth] = Util.ud2std[m]; return(ret); } } return(-1); }
/** * @return * 0: Found or Probe limit exceeded * 1: Try Next Power * 2: Try Next Axis */ private int initPhase2() { isRec = false; if (probe >= (this.solution_ == null ? probeMax : probeMin)) { return(0); } ++probe; int cidx = corn0[urfIdx, preIdx] >> 4; int csym = corn0[urfIdx, preIdx] & 0xf; int mid = node0[urfIdx, preIdx].slice; for (int i = 0; i < depth1; i++) { int m = move[i]; cidx = CoordCube.CPermMove[cidx, CubieCube.SymMove[csym, m]]; csym = CubieCube.SymMult[cidx & 0xf, csym]; cidx >>= 4; int cx = CoordCube.UDSliceMove[mid & 0x1ff, m]; mid = Util.permMult[mid >> 9, cx >> 9] << 9 | cx & 0x1ff; } mid >>= 9; int prun = CoordCube.getPruning(CoordCube.MCPermPrun, cidx * 24 + CoordCube.MPermConj[mid, csym]); if (prun >= maxDep2) { return(prun > maxDep2 ? 2 : 1); } int u4e = ud8e0[urfIdx, preIdx] >> 16; int d4e = ud8e0[urfIdx, preIdx] & 0xffff; for (int i = 0; i < depth1; i++) { int m = move[i]; int cx = CoordCube.UDSliceMove[u4e & 0x1ff, m]; u4e = Util.permMult[u4e >> 9, cx >> 9] << 9 | cx & 0x1ff; cx = CoordCube.UDSliceMove[d4e & 0x1ff, m]; d4e = Util.permMult[d4e >> 9, cx >> 9] << 9 | cx & 0x1ff; } int edge = CubieCube.MtoEPerm[494 - (u4e & 0x1ff) + (u4e >> 9) * 70 + (d4e >> 9) * 1680]; int esym = edge & 0xf; edge >>= 4; prun = Math.Max(prun, Math.Max( CoordCube.getPruning(CoordCube.MEPermPrun, edge * 24 + CoordCube.MPermConj[mid, esym]), CoordCube.getPruning(CoordCube.EPermCCombPrun, edge * 70 + CoordCube.CCombConj[CubieCube.Perm2Comb[cidx], CubieCube.SymMultInv[esym, csym]]))); if (prun >= maxDep2) { return(prun > maxDep2 ? 2 : 1); } int lm = 10; if (depth1 >= 2 && move[depth1 - 1] / 3 % 3 == move[depth1 - 2] / 3 % 3) { lm = Util.std2ud[Math.Max(move[depth1 - 1], move[depth1 - 2]) / 3 * 3 + 1]; } else if (depth1 >= 1) { lm = Util.std2ud[move[depth1 - 1] / 3 * 3 + 1]; if (move[depth1 - 1] > Util.Fx3) { lm = -lm; } } int depth2; for (depth2 = maxDep2 - 1; depth2 >= prun; depth2--) { int ret = phase2(edge, esym, cidx, csym, mid, depth2, depth1, lm); if (ret < 0) { break; } depth2 = depth2 - ret; sol = depth1 + depth2; if (preIdx != 0) { // assert depth2 > 0; //If depth2 == 0, the solution is optimal. In this case, we won't try preScramble to find shorter solutions. int axisPre = Util.preMove[preIdx] / 3; int axisLast = move[sol - 1] / 3; if (axisPre == axisLast) { int pow = (Util.preMove[preIdx] % 3 + move[sol - 1] % 3 + 1) % 4; move[sol - 1] = axisPre * 3 + pow; } else if (depth2 > 1 && axisPre % 3 == axisLast % 3 && move[sol - 2] / 3 == axisPre) { int pow = (Util.preMove[preIdx] % 3 + move[sol - 2] % 3 + 1) % 4; move[sol - 2] = axisPre * 3 + pow; } else { move[sol++] = Util.preMove[preIdx]; } } this.solution_ = solutionTostring(); } if (depth2 != maxDep2 - 1) { //At least one solution has been found. maxDep2 = Math.Min(MAX_DEPTH2, sol - length1); return(probe >= probeMin ? 0 : 1); } else { return(1); } }