Ejemplo n.º 1
0
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Compute the inverse CubieCube
 void invCubieCube(CubieCube c)
 {
     foreach (Edge edge in (Edge[])Enum.GetValues(typeof(Edge)))
     {
         c.ep[(int)ep[(int)edge]] = edge;
     }
     foreach (Edge edge in (Edge[])Enum.GetValues(typeof(Edge)))
     {
         c.eo[(int)edge] = eo[(int)c.ep[(int)edge]];
     }
     foreach (Corner corn in (Corner[])Enum.GetValues(typeof(Corner)))
     {
         c.cp[(int)cp[(int)corn]] = corn;
     }
     foreach (Corner corn in (Corner[])Enum.GetValues(typeof(Corner)))
     {
         byte ori = co[(int)c.cp[(int)corn]];
         if (ori >= 3) // Just for completeness. We do not invert mirrored
                       // cubes in the program.
         {
             c.co[(int)corn] = ori;
         }
         else
         {// the standard case
             c.co[(int)corn] = (byte)-ori;
             if (c.co[(int)corn] < 0)
             {
                 c.co[(int)corn] += 3;
             }
         }
     }
 }
Ejemplo n.º 2
0
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Check if the cube string s represents a solvable cube.
        // 0: Cube is solvable
        // -1: There is not exactly one facelet of each colour
        // -2: Not all 12 edges exist exactly once
        // -3: Flip error: One edge has to be flipped
        // -4: Not all corners exist exactly once
        // -5: Twist error: One corner has to be twisted
        // -6: Parity error: Two corners or two edges have to be exchanged
        //
        /// <summary>
        /// Check if the cube definition string s represents a solvable cube.
        /// </summary>
        /// <param name="s"> is the cube definition string , see <seealso cref="Facelet"/> </param>
        /// <returns> 0: Cube is solvable<br>
        ///         -1: There is not exactly one facelet of each colour<br>
        ///         -2: Not all 12 edges exist exactly once<br>
        ///         -3: Flip error: One edge has to be flipped<br>
        ///         -4: Not all 8 corners exist exactly once<br>
        ///         -5: Twist error: One corner has to be twisted<br>
        ///         -6: Parity error: Two corners or two edges have to be exchanged </returns>
        public static int verify(string s)
        {
            int[] count = new int[6];
            try
            {
                for (int i = 0; i < 54; i++)
                {
                    count[(int)CubeColor.Parse(typeof(CubeColor), i.ToString())]++;
                }
            }
            catch (Exception)
            {
                return(-1);
            }

            for (int i = 0; i < 6; i++)
            {
                if (count[i] != 9)
                {
                    return(-1);
                }
            }

            FaceCube  fc = new FaceCube(s);
            CubieCube cc = fc.toCubieCube();

            return(cc.verify());
        }
Ejemplo n.º 3
0
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Multiply this CubieCube with another cubiecube b, restricted to the corners.<br>
        // Because we also describe reflections of the whole cube by permutations, we get a complication with the corners. The
        // orientations of mirrored corners are described by the numbers 3, 4 and 5. The composition of the orientations
        // cannot
        // be computed by addition modulo three in the cyclic group C3 any more. Instead the rules below give an addition in
        // the dihedral group D3 with 6 elements.<br>
        //
        // NOTE: Because we do not use symmetry reductions and hence no mirrored cubes in this simple implementation of the
        // Two-Phase-Algorithm, some code is not necessary here.
        //
        public void cornerMultiply(CubieCube b)
        {
            Corner[] cPerm = new Corner[8];
            byte[]   cOri  = new byte[8];
            foreach (Corner corn in (Corner[])Enum.GetValues(typeof(Corner)))
            {
                cPerm[(int)corn] = cp[(int)b.cp[(int)corn]];

                byte oriA = co[(int)b.cp[(int)corn]];
                byte oriB = b.co[(int)corn];
                byte ori  = 0;
                ;
                if (oriA < 3 && oriB < 3)      // if both cubes are regular cubes...
                {
                    ori = (byte)(oriA + oriB); // just do an addition modulo 3 here
                    if (ori >= 3)
                    {
                        ori -= 3; // the composition is a regular cube
                    }
                    // +++++++++++++++++++++not used in this implementation +++++++++++++++++++++++++++++++++++
                }
                else if (oriA < 3 && oriB >= 3) // if cube b is in a mirrored
                                                // state...
                {
                    ori = (byte)(oriA + oriB);
                    if (ori >= 6)
                    {
                        ori -= 3; // the composition is a mirrored cube
                    }
                }
                else if (oriA >= 3 && oriB < 3) // if cube a is an a mirrored
                                                // state...
                {
                    ori = (byte)(oriA - oriB);
                    if (ori < 3)
                    {
                        ori += 3; // the composition is a mirrored cube
                    }
                }
                else if (oriA >= 3 && oriB >= 3) // if both cubes are in mirrored
                                                 // states...
                {
                    ori = (byte)(oriA - oriB);
                    if (ori < 0)
                    {
                        ori += 3; // the composition is a regular cube
                    }
                    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                }
                cOri[(int)corn] = ori;
            }

            foreach (Corner c in (Corner[])Enum.GetValues(typeof(Corner)))
            {
                cp[(int)c] = cPerm[(int)c];
                co[(int)c] = cOri[(int)c];
            }
        }
Ejemplo n.º 4
0
        static CubieCube SetMoveU()
        {
            CubieCube move = new CubieCube();

            move.cp = cpU;
            move.co = coU;
            move.ep = epU;
            move.eo = eoU;
            return(move);
        }
Ejemplo n.º 5
0
        static CubieCube SetMoveD()
        {
            CubieCube move = new CubieCube();

            move.cp = cpD;
            move.co = coD;
            move.ep = epD;
            move.eo = eoD;
            return(move);
        }
Ejemplo n.º 6
0
        static CubieCube SetMoveL()
        {
            CubieCube move = new CubieCube();

            move.cp = cpL;
            move.co = coL;
            move.ep = epL;
            move.eo = eoL;
            return(move);
        }
Ejemplo n.º 7
0
        static CubieCube SetMoveB()
        {
            CubieCube move = new CubieCube();

            move.cp = cpB;
            move.co = coB;
            move.ep = epB;
            move.eo = eoB;
            return(move);
        }
Ejemplo n.º 8
0
        static CubieCube SetMoveF()
        {
            CubieCube move = new CubieCube();

            move.cp = cpF;
            move.co = coF;
            move.ep = epF;
            move.eo = eoF;
            return(move);
        }
Ejemplo n.º 9
0
        static CubieCube SetMoveR()
        {
            CubieCube move = new CubieCube();

            move.cp = cpR;
            move.co = coR;
            move.ep = epR;
            move.eo = eoR;
            return(move);
        }
Ejemplo n.º 10
0
        public static string fromScramble(int[] scramble)
        {
            CubieCube c1 = new CubieCube();
            CubieCube c2 = new CubieCube();
            CubieCube tmp;

            for (int i = 0; i < scramble.Length; i++)
            {
                c1.cornerMultiply(CubieCube.moveCube[scramble[i]]);
                c2.cornerMultiply(CubieCube.moveCube[scramble[i]]);
                tmp = c1; c1 = c2; c2 = tmp;
            }
            return(c1.toFaceCube().to_fc_String());
        }
Ejemplo n.º 11
0
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Generate a CoordCube from a CubieCube
        internal CoordCube(CubieCube c, DateTime startTime, string currentTime, out string info)
        {
            info  = currentTime;
            twist = c.getTwist();

            flip   = c.getFlip();
            parity = c.cornerParity();
            FRtoBR = c.getFRtoBR();

            URFtoDLF = c.getURFtoDLF();
            URtoUL   = c.getURtoUL();
            UBtoDF   = c.getUBtoDF();
            URtoDF   = c.getURtoDF();// only needed in phase2
            info    += "[ Finished Initialiation: " + String.Format(@"{0:mm\:ss\.ffff}", (DateTime.Now - startTime)) + " ] ";
        }
Ejemplo n.º 12
0
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Multiply this CubieCube with another cubiecube b, restricted to the edges.
 public void edgeMultiply(CubieCube b)
 {
     Edge[] ePerm = new Edge[12];
     byte[] eOri  = new byte[12];
     foreach (Edge edge in (Edge[])Enum.GetValues(typeof(Edge)))
     {
         ePerm[(int)edge] = ep[(int)b.ep[(int)edge]];
         eOri[(int)edge]  = (byte)((b.eo[(int)edge] + eo[(int)b.ep[(int)edge]]) % 2);
     }
     foreach (Edge e in (Edge[])Enum.GetValues(typeof(Edge)))
     {
         ep[(int)e] = ePerm[(int)e];
         eo[(int)e] = eOri[(int)e];
     }
 }
Ejemplo n.º 13
0
        /// <summary>
        /// Generates a random cube. </summary>
        /// <returns> A random cube in the string representation. Each cube of the cube space has the same probability. </returns>
        public static string randomCube()
        {
            CubieCube cc = new CubieCube();

            System.Random gen = new System.Random();
            cc.setFlip((short)gen.Next(CoordCube.N_FLIP));
            cc.setTwist((short)gen.Next(CoordCube.N_TWIST));
            do
            {
                cc.setURFtoDLB(gen.Next(CoordCube.N_URFtoDLB));
                cc.setURtoBR(gen.Next(CoordCube.N_URtoBR));
            } while ((cc.edgeParity() ^ cc.cornerParity()) != 0);
            FaceCube fc = cc.toFaceCube();

            return(fc.to_fc_String());
        }
Ejemplo n.º 14
0
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Permutation of the six edges UR,UF,UL,UB,DR,DF
        public static int getURtoDF(short idx1, short idx2)
        {
            CubieCube a = new CubieCube();
            CubieCube b = new CubieCube();

            a.setURtoUL(idx1);
            b.setUBtoDF(idx2);
            for (int i = 0; i < 8; i++)
            {
                if (a.ep[i] != Edge.BR)
                {
                    if (b.ep[i] != Edge.BR)// collision
                    {
                        return(-1);
                    }
                    else
                    {
                        b.ep[i] = a.ep[i];
                    }
                }
            }
            return(b.getURtoDF());
        }
Ejemplo n.º 15
0
        /**
         * Computes the solver string for a given cube.
         *
         * @param facelets
         *          is the cube definition string, see {@link Facelet} for the format.
         *
         * @param maxDepth
         *          defines the maximal allowed maneuver length. For random cubes, a maxDepth of 21 usually will return a
         *          solution in less than 0.5 seconds. With a maxDepth of 20 it takes a few seconds on average to find a
         *          solution, but it may take much longer for specific cubes.
         *
         *@param timeOut
         *          defines the maximum computing time of the method in seconds. If it does not return with a solution, it returns with
         *          an error code.
         *
         * @param useSeparator
         *          determines if a " . " separates the phase1 and phase2 parts of the solver string like in F' R B R L2 F .
         *          U2 U D for example.<br>
         * @return The solution string or an error code:<br>
         *         Error 1: There is not exactly one facelet of each colour<br>
         *         Error 2: Not all 12 edges exist exactly once<br>
         *         Error 3: Flip error: One edge has to be flipped<br>
         *         Error 4: Not all corners exist exactly once<br>
         *         Error 5: Twist error: One corner has to be twisted<br>
         *         Error 6: Parity error: Two corners or two edges have to be exchanged<br>
         *         Error 7: No solution exists for the given maxDepth<br>
         *         Error 8: Timeout, no solution within given time
         */
        public static string solution(string facelets, out string info, int maxDepth = 50, long timeOut = 6000, bool useSeparator = false, bool buildTables = false)
        {
            info = "Warning, this solution builds tables at run time which is very slow. This will find a solution, however it is reccomended to use the K_SearchRunTime class only to create a local copy of the tables, then use the K_Search class to search for solutions instead.";
            if (facelets == "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB")
            {
                return("");
            }
            int s;

            // +++++++++++++++++++++check for wrong input +++++++++++++++++++++++++++++
            int[] count = new int[6];
            try
            {
                for (int i = 0; i < 54; i++)
                {
                    count[(int)CubeColor.Parse(typeof(CubeColor), facelets.Substring(i, 1))]++;
                }
            }
            catch (Exception)
            {
                return("Error 1");
            }
            for (int i = 0; i < 6; i++)
            {
                if (count[i] != 9)
                {
                    return("Error 1");
                }
            }

            FaceCube  fc = new FaceCube(facelets);
            CubieCube cc = fc.toCubieCube();

            if ((s = cc.verify()) != 0)
            {
                return("Error " + Math.Abs(s));
            }
            // +++++++++++++++++++++++ initialization +++++++++++++++++++++++++++++++++
            CoordCubeBuildTables c = new CoordCubeBuildTables(cc, buildTables);

            //return "lol";

            po[0]            = 0;
            ax[0]            = 0;
            flip[0]          = c.flip;
            twist[0]         = c.twist;
            parity[0]        = c.parity;
            slice[0]         = c.FRtoBR / 24;
            URFtoDLF[0]      = c.URFtoDLF;
            FRtoBR[0]        = c.FRtoBR;
            URtoUL[0]        = c.URtoUL;
            UBtoDF[0]        = c.UBtoDF;
            minDistPhase1[1] = 1; // else failure for depth=1, n=0
            int  mv = 0, n = 0;
            bool busy        = false;
            int  depthPhase1 = 1;
            long tStart      = DateTimeHelper.CurrentUnixTimeMillis();

            // +++++++++++++++++++ Main loop ++++++++++++++++++++++++++++++++++++++++++
            do
            {
                do
                {
                    if ((depthPhase1 - n > minDistPhase1[n + 1]) && !busy)
                    {
                        if (ax[n] == 0 || ax[n] == 3) // Initialize next move
                        {
                            ax[++n] = 1;
                        }
                        else
                        {
                            ax[++n] = 0;
                        }
                        po[n] = 1;
                    }
                    else if (++po[n] > 3)
                    {
                        do
                        { // increment axis
                            if (++ax[n] > 5)
                            {
                                if (DateTimeHelper.CurrentUnixTimeMillis() - tStart > timeOut << 10)
                                {
                                    return("Error 8");
                                }

                                if (n == 0)
                                {
                                    if (depthPhase1 >= maxDepth)
                                    {
                                        return("Error 7");
                                    }
                                    else
                                    {
                                        depthPhase1++;
                                        ax[n] = 0;
                                        po[n] = 1;
                                        busy  = false;
                                        break;
                                    }
                                }
                                else
                                {
                                    n--;
                                    busy = true;
                                    break;
                                }
                            }
                            else
                            {
                                po[n] = 1;
                                busy  = false;
                            }
                        } while (n != 0 && (ax[n - 1] == ax[n] || ax[n - 1] - 3 == ax[n]));
                    }
                    else
                    {
                        busy = false;
                    }
                } while (busy);

                // +++++++++++++ compute new coordinates and new minDistPhase1 ++++++++++
                // if minDistPhase1 =0, the H subgroup is reached
                mv                   = 3 * ax[n] + po[n] - 1;
                flip[n + 1]          = CoordCubeBuildTables.flipMove[flip[n], mv];
                twist[n + 1]         = CoordCubeBuildTables.twistMove[twist[n], mv];
                slice[n + 1]         = CoordCubeBuildTables.FRtoBR_Move[slice[n] * 24, mv] / 24;
                minDistPhase1[n + 1] = Math.Max(CoordCubeBuildTables.getPruning(CoordCubeBuildTables.Slice_Flip_Prun, CoordCubeBuildTables.N_SLICE1 * flip[n + 1] + slice[n + 1]), CoordCubeBuildTables.getPruning(CoordCubeBuildTables.Slice_Twist_Prun, CoordCubeBuildTables.N_SLICE1 * twist[n + 1] + slice[n + 1]));
                // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                if (minDistPhase1[n + 1] == 0 && n >= depthPhase1 - 5)
                {
                    minDistPhase1[n + 1] = 10; // instead of 10 any value >5 is possible
                    if (n == depthPhase1 - 1 && (s = totalDepth(depthPhase1, maxDepth)) >= 0)
                    {
                        if (s == depthPhase1 || (ax[depthPhase1 - 1] != ax[depthPhase1] && ax[depthPhase1 - 1] != ax[depthPhase1] + 3))
                        {
                            return(useSeparator ? solutionToString(s, depthPhase1) : solutionToString(s));
                        }
                    }
                }
            } while (true);
        }
Ejemplo n.º 16
0
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Gives CubieCube representation of a faceletcube
        public CubieCube toCubieCube()
        {
            byte      ori;
            CubieCube ccRet = new CubieCube();

            for (int i = 0; i < 8; i++)
            {
                ccRet.cp[i] = Corner.URF;// invalidate corners
            }
            for (int i = 0; i < 12; i++)
            {
                ccRet.ep[i] = Edge.UR;// and edges
            }
            CubeColor col1, col2;

            foreach (Corner i in (Corner[])Enum.GetValues(typeof(Corner)))
            {
                // get the CubeColors of the cubie at corner i, starting with U/D
                for (ori = 0; ori < 3; ori++)
                {
                    if (f[(int)cornerFacelet[(int)i][ori]] == CubeColor.U || f[(int)cornerFacelet[(int)i][ori]] == CubeColor.D)
                    {
                        break;
                    }
                }
                col1 = f[(int)cornerFacelet[(int)i][(ori + 1) % 3]];
                col2 = f[(int)cornerFacelet[(int)i][(ori + 2) % 3]];

                foreach (Corner j in (Corner[])Enum.GetValues(typeof(Corner)))
                {
                    if (col1 == cornerColor[(int)j][1] && col2 == cornerColor[(int)j][2])
                    {
                        // in cornerposition i we have cornercubie j
                        ccRet.cp[(int)i] = j;
                        ccRet.co[(int)i] = (byte)(ori % 3);
                        break;
                    }
                }
            }
            foreach (Edge i in (Edge[])Enum.GetValues(typeof(Edge)))
            {
                foreach (Edge j in (Edge[])Enum.GetValues(typeof(Edge)))
                {
                    if (f[(int)edgeFacelet[(int)i][0]] == edgeColor[(int)j][0] &&
                        f[(int)edgeFacelet[(int)i][1]] == edgeColor[(int)j][1])
                    {
                        ccRet.ep[(int)i] = j;
                        ccRet.eo[(int)i] = 0;
                        break;
                    }
                    if (f[(int)edgeFacelet[(int)i][0]] == edgeColor[(int)j][1] &&
                        f[(int)edgeFacelet[(int)i][1]] == edgeColor[(int)j][0])
                    {
                        ccRet.ep[(int)i] = j;
                        ccRet.eo[(int)i] = 1;
                        break;
                    }
                }
            }
            return(ccRet);
        }
Ejemplo n.º 17
0
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Multiply this CubieCube with another CubieCube b.
 void multiply(CubieCube b)
 {
     cornerMultiply(b);
     // edgeMultiply(b);
 }
Ejemplo n.º 18
0
        /**
         * Computes the solver string for a given cube.
         *
         * @param facelets
         *          is the cube definition string, see {@link Facelet} for the format.
         *
         * @param maxDepth
         *          defines the maximal allowed maneuver length. For random cubes, a maxDepth of 21 usually will return a
         *          solution in less than 0.5 seconds. With a maxDepth of 20 it takes a few seconds on average to find a
         *          solution, but it may take much longer for specific cubes.
         *
         *@param timeOut
         *          defines the maximum computing time of the method in seconds. If it does not return with a solution, it returns with
         *          an error code.
         *
         * @param useSeparator
         *          determines if a " . " separates the phase1 and phase2 parts of the solver string like in F' R B R L2 F .
         *          U2 U D for example.<br>
         * @return The solution string or an error code:<br>
         *         Error 1: There is not exactly one facelet of each colour<br>
         *         Error 2: Not all 12 edges exist exactly once<br>
         *         Error 3: Flip error: One edge has to be flipped<br>
         *         Error 4: Not all corners exist exactly once<br>
         *         Error 5: Twist error: One corner has to be twisted<br>
         *         Error 6: Parity error: Two corners or two edges have to be exchanged<br>
         *         Error 7: No solution exists for the given maxDepth<br>
         *         Error 8: Timeout, no solution within given time
         */
        public static string solution(string facelets, out string info, int maxDepth = 22, long timeOut = 6000, bool useSeparator = false)
        {
            if (facelets == "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB")
            {
                info = "Already Solved";
                return("");
            }
            DateTime startTime = DateTime.Now;

            info = "";


            int s;

            // +++++++++++++++++++++check for wrong input +++++++++++++++++++++++++++++
            int[] count = new int[6];
            try
            {
                for (int i = 0; i < 54; i++)
                {
                    count[(int)CubeColor.Parse(typeof(CubeColor), facelets.Substring(i, 1))]++;
                }
            }
            catch (Exception)
            {
                return("Error 1");
            }
            for (int i = 0; i < 6; i++)
            {
                if (count[i] != 9)
                {
                    return("Error 1");
                }
            }

            FaceCube  fc = new FaceCube(facelets);
            CubieCube cc = fc.toCubieCube();

            if ((s = cc.verify()) != 0)
            {
                return("Error " + Math.Abs(s));
            }
            // +++++++++++++++++++++++ initialization +++++++++++++++++++++++++++++++++
            string    currentTime = "[ a: " + String.Format(@"{0:mm\:ss\.ffff}", (DateTime.Now - startTime)) + " ] ";
            CoordCube c           = new CoordCube(cc, startTime, currentTime, out info);

            //return "lol";

            po[0]            = 0;
            ax[0]            = 0;
            flip[0]          = c.flip;
            twist[0]         = c.twist;
            parity[0]        = c.parity;
            slice[0]         = c.FRtoBR / 24;
            URFtoDLF[0]      = c.URFtoDLF;
            FRtoBR[0]        = c.FRtoBR;
            URtoUL[0]        = c.URtoUL;
            UBtoDF[0]        = c.UBtoDF;
            minDistPhase1[1] = 1; // else failure for depth=1, n=0
            int  mv = 0, n = 0;
            bool busy        = false;
            int  depthPhase1 = 1;
            long tStart      = DateTimeHelper.CurrentUnixTimeMillis();

            // +++++++++++++++++++ Main loop ++++++++++++++++++++++++++++++++++++++++++
            do
            {
                do
                {
                    if ((depthPhase1 - n > minDistPhase1[n + 1]) && !busy)
                    {
                        if (ax[n] == 0 || ax[n] == 3) // Initialize next move
                        {
                            ax[++n] = 1;
                        }
                        else
                        {
                            ax[++n] = 0;
                        }
                        po[n] = 1;
                    }
                    else if (++po[n] > 3)
                    {
                        do
                        { // increment axis
                            if (++ax[n] > 5)
                            {
                                if (DateTimeHelper.CurrentUnixTimeMillis() - tStart > timeOut << 10)
                                {
                                    return("Error 8");
                                }

                                if (n == 0)
                                {
                                    if (depthPhase1 >= maxDepth)
                                    {
                                        return("Error 7");
                                    }
                                    else
                                    {
                                        depthPhase1++;
                                        ax[n] = 0;
                                        po[n] = 1;
                                        busy  = false;
                                        break;
                                    }
                                }
                                else
                                {
                                    n--;
                                    busy = true;
                                    break;
                                }
                            }
                            else
                            {
                                po[n] = 1;
                                busy  = false;
                            }
                        } while (n != 0 && (ax[n - 1] == ax[n] || ax[n - 1] - 3 == ax[n]));
                    }
                    else
                    {
                        busy = false;
                    }
                } while (busy);

                // +++++++++++++ compute new coordinates and new minDistPhase1 ++++++++++
                // if minDistPhase1 =0, the H subgroup is reached
                mv                   = 3 * ax[n] + po[n] - 1;
                flip[n + 1]          = CoordCube.flipMove[flip[n], mv];
                twist[n + 1]         = CoordCube.twistMove[twist[n], mv];
                slice[n + 1]         = CoordCube.FRtoBR_Move[slice[n] * 24, mv] / 24;
                minDistPhase1[n + 1] = Math.Max(CoordCube.getPruning(CoordCube.Slice_Flip_Prun, CoordCube.N_SLICE1 * flip[n + 1] + slice[n + 1]), CoordCube.getPruning(CoordCube.Slice_Twist_Prun, CoordCube.N_SLICE1 * twist[n + 1] + slice[n + 1]));
                // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                if (minDistPhase1[n + 1] == 0 && n >= depthPhase1 - 5)
                {
                    minDistPhase1[n + 1] = 10; // instead of 10 any value >5 is possible
                    if (n == depthPhase1 - 1 && (s = totalDepth(depthPhase1, maxDepth)) >= 0)
                    {
                        if (s == depthPhase1 || (ax[depthPhase1 - 1] != ax[depthPhase1] && ax[depthPhase1 - 1] != ax[depthPhase1] + 3))
                        {
                            return(useSeparator ? solutionToString(s, depthPhase1) : solutionToString(s));
                        }
                    }
                }
            } while (true);
        }