Ejemplo n.º 1
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
        //

        /**
         * Check if the cube definition string s represents a solvable cube.
         *
         * @param s is the cube definition string , see {@link Facelet}
         * @return 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
         */
        public static int verify(String s)
        {
            int[] count = new int[6];
            try
            {
                for (int i = 0; i < 54; i++)
                {
                    Color col;
                    if (!Enum.TryParse(s.Substring(i, 1), out col))
                    {
                        throw new Exception("Invalid color");
                    }
                    count[(int)col]++;
                }
            }
            catch (Exception e)
            {
                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.º 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
        //
        /**
         * Check if the cube definition string s represents a solvable cube.
         *
         * @param s is the cube definition string , see {@link Facelet}
         * @return 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
         */
        public static int verify(String s)
        {
            int[] count = new int[6];
            try
            {
                for (int i = 0; i < 54; i++)
                {
                    Color col;
                    if (!Enum.TryParse(s.Substring(i,1), out col)) throw new Exception("Invalid color");
                    count[(int)col]++;
                }
            }
            catch (Exception e)
            {
                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
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // return cube in facelet representation
        public FaceCube toFaceCube()
        {
            FaceCube fcRet = new FaceCube();

            foreach (Corner c in Enums.Corners)
            {
                int i = (int)c;
                int j = (int)cp[i]; // cornercubie with index j is at
                // cornerposition with index i
                sbyte ori = co[i];  // Orientation of this cubie
                for (int n = 0; n < 3; n++)
                {
                    fcRet.f[(int)FaceCube.cornerFacelet[i][(n + ori) % 3]] = FaceCube.cornerColor[j][n];
                }
            }
            foreach (Edge e in Enums.Edges)
            {
                int i = (int)e;
                int j = (int)ep[i]; // edgecubie with index j is at edgeposition
                // with index i
                sbyte ori = eo[i];  // Orientation of this cubie
                for (int n = 0; n < 2; n++)
                {
                    fcRet.f[(int)FaceCube.edgeFacelet[i][(n + ori) % 2]] = FaceCube.edgeColor[j][n];
                }
            }
            return(fcRet);
        }
Ejemplo n.º 4
0
        /**
         * Generates a random cube.
         * @return A random cube in the string representation. Each cube of the cube space has the same probability.
         */
        public static String randomCube()
        {
            CubieCube cc  = new CubieCube();
            Random    gen = new 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_String());
        }
Ejemplo n.º 5
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, int maxDepth, bool useSeparator)
        {
            int s;
            // +++++++++++++++++++++check for wrong input +++++++++++++++++++++++++++++
            int[] count = new int[6];
            try {
            for (int i = 0; i < 54; i++)
            {
                Color col;
                if (!Enum.TryParse(facelets.Substring(i,1), out col)) throw new Exception("Invalid color");
                count[(int)col]++;
            }

            } catch (Exception e) {
            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 +++++++++++++++++++++++++++++++++
            CoordCube c = new CoordCube(cc);

            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;
            // +++++++++++++++++++ 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 (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;
            sbyte[] table = CoordCube.Slice_Flip_Prun;
            int index = CoordCube.N_SLICE1 * flip[n + 1]
                        + slice[n + 1];
            sbyte[] table1 = CoordCube.Slice_Twist_Prun;
            int index1 = CoordCube.N_SLICE1 * twist[n + 1]
                         + slice[n + 1];
            minDistPhase1[n + 1] = Math.Max((index % 2 == 0) ? (table[index >> 1] & 0x0f) : ((table[index >> 1] & 0xf0) >> 4), (index1 % 2 == 0) ? (table1[index1 >> 1] & 0x0f) : ((table1[index1 >> 1] & 0xf0) >> 4));
            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

            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.º 6
0
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // return cube in facelet representation
 public FaceCube toFaceCube()
 {
     FaceCube fcRet = new FaceCube();
     foreach (Corner c in Enums.Corners)
     {
         int i = (int) c;
         int j = (int) cp[i]; // cornercubie with index j is at
         // cornerposition with index i
         sbyte ori = co[i]; // Orientation of this cubie
         for (int n = 0; n < 3; n++)
             fcRet.f[(int) FaceCube.cornerFacelet[i][(n + ori)%3]] = FaceCube.cornerColor[j][n];
     }
     foreach (Edge e in Enums.Edges)
     {
         int i = (int) e;
         int j = (int) ep[i]; // edgecubie with index j is at edgeposition
         // with index i
         sbyte ori = eo[i]; // Orientation of this cubie
         for (int n = 0; n < 2; n++)
             fcRet.f[(int) FaceCube.edgeFacelet[i][(n + ori)%2]] = FaceCube.edgeColor[j][n];
     }
     return fcRet;
 }
Ejemplo n.º 7
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, int maxDepth, bool useSeparator)
        {
            int s;

            // +++++++++++++++++++++check for wrong input +++++++++++++++++++++++++++++
            int[] count = new int[6];
            try {
                for (int i = 0; i < 54; i++)
                {
                    Color col;
                    if (!Enum.TryParse(facelets.Substring(i, 1), out col))
                    {
                        throw new Exception("Invalid color");
                    }
                    count[(int)col]++;
                }
            } catch (Exception e) {
                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 +++++++++++++++++++++++++++++++++
            CoordCube c = new CoordCube(cc);

            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;

            // +++++++++++++++++++ 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 (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;
                sbyte[] table = CoordCube.Slice_Flip_Prun;
                int     index = CoordCube.N_SLICE1 * flip[n + 1]
                                + slice[n + 1];
                sbyte[] table1 = CoordCube.Slice_Twist_Prun;
                int     index1 = CoordCube.N_SLICE1 * twist[n + 1]
                                 + slice[n + 1];
                minDistPhase1[n + 1] = Math.Max((index % 2 == 0) ? (table[index >> 1] & 0x0f) : ((table[index >> 1] & 0xf0) >> 4), (index1 % 2 == 0) ? (table1[index1 >> 1] & 0x0f) : ((table1[index1 >> 1] & 0xf0) >> 4));
                // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                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);
        }