コード例 #1
0
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Compute the inverse CubieCube
        private void invCubieCube(CubieCube c)
        {
            foreach (Edge edge in Enums.Edges)
            {
                c.ep[(int)ep[(int)edge]] = edge;
            }
            foreach (Edge edge in Enums.Edges)
            {
                c.eo[(int)edge] = eo[(int)c.ep[(int)edge]];
            }
            foreach (Corner corn in Enums.Corners)
            {
                c.cp[(int)cp[(int)corn]] = corn;
            }
            foreach (Corner corn in Enums.Corners)
            {
                sbyte 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] = (sbyte)-ori;
                    if (c.co[(int)corn] < 0)
                    {
                        c.co[(int)corn] += 3;
                    }
                }
            }
        }
コード例 #2
0
ファイル: Tools.cs プロジェクト: sitrem/Ev3CubeSolver
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // 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());
        }
コード例 #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];
            sbyte[]  cOri  = new sbyte[8];
            foreach (Corner corn in Enums.Corners)
            {
                cPerm[(int)corn] = cp[(int)b.cp[(int)corn]];

                sbyte oriA = co[(int)b.cp[(int)corn]];
                sbyte oriB = b.co[(int)corn];
                sbyte ori  = 0;
                ;
                if (oriA < 3 && oriB < 3)       // if both cubes are regular cubes...
                {
                    ori = (sbyte)(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 = (sbyte)(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 = (sbyte)(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 = (sbyte)(oriA - oriB);
                    if (ori < 0)
                    {
                        ori += 3; // the composition is a regular cube
                    }
                    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                }
                cOri[(int)corn] = ori;
            }
            foreach (Corner c in Enums.Corners)
            {
                int cornerIdx = (int)c;
                cp[cornerIdx] = cPerm[cornerIdx];
                co[cornerIdx] = cOri[cornerIdx];
            }
        }
コード例 #4
0
ファイル: CoordCube.cs プロジェクト: vankrelian/Rub1k3ks
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Generate a CoordCube from a CubieCube
 public CoordCube(CubieCube c)
 {
     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
 }
コード例 #5
0
ファイル: Tools.cs プロジェクト: Larsjep/Ev3CubeSolver
 /**
  * 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();
 }
コード例 #6
0
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Multiply this CubieCube with another cubiecube b, restricted to the edges.
 public void edgeMultiply(CubieCube b)
 {
     Edge[]  ePerm = new Edge[12];
     sbyte[] eOri  = new sbyte[12];
     foreach (Edge edge in Enums.Edges)
     {
         int edgeIdx = (int)edge;
         ePerm[edgeIdx] = ep[(int)b.ep[edgeIdx]];
         eOri[edgeIdx]  = (sbyte)((b.eo[edgeIdx] + eo[(int)b.ep[edgeIdx]]) % 2);
     }
     foreach (Edge e in Enums.Edges)
     {
         ep[(int)e] = ePerm[(int)e];
         eo[(int)e] = eOri[(int)e];
     }
 }
コード例 #7
0
ファイル: Tools.cs プロジェクト: sitrem/Ev3CubeSolver
        /**
         * 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());
        }
コード例 #8
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());
        }
コード例 #9
0
ファイル: FaceCube.cs プロジェクト: vankrelian/Rub1k3ks
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Gives CubieCube representation of a faceletcube
        public CubieCube toCubieCube()
        {
            sbyte 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
            Color col1, col2;
            foreach (Corner i in Enum.GetValues(typeof (Corner)))
            {
                // get the colors of the cubie at corner i, starting with U/D
                for (ori = 0; ori < 3; ori++)
                    if (f[(int) cornerFacelet[(int) i][ori]] == Color.U || f[(int) cornerFacelet[(int) i][ori]] == Color.D)
                        break;
                col1 = f[(int) cornerFacelet[(int) i][(ori + 1)%3]];
                col2 = f[(int) cornerFacelet[(int) i][(ori + 2)%3]];

                foreach (Corner j in 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] = (sbyte) (ori%3);
                        break;
                    }
                }
            }
            foreach (Edge i in Enum.GetValues(typeof (Edge)))
                foreach (Edge j in 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;
        }
コード例 #10
0
ファイル: CubieCube.cs プロジェクト: Larsjep/Ev3CubeSolver
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // 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();
 }
コード例 #11
0
ファイル: CubieCube.cs プロジェクト: Larsjep/Ev3CubeSolver
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Compute the inverse CubieCube
 private void invCubieCube(CubieCube c)
 {
     foreach (Edge edge in Enums.Edges)
         c.ep[(int) ep[(int) edge]] = edge;
     foreach (Edge edge in Enums.Edges)
         c.eo[(int) edge] = eo[(int) c.ep[(int) edge]];
     foreach (Corner corn in Enums.Corners)
         c.cp[(int) cp[(int) corn]] = corn;
     foreach (Corner corn in Enums.Corners)
     {
         sbyte 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] = (sbyte) -ori;
             if (c.co[(int) corn] < 0)
                 c.co[(int) corn] += 3;
         }
     }
 }
コード例 #12
0
ファイル: CubieCube.cs プロジェクト: Larsjep/Ev3CubeSolver
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Multiply this CubieCube with another CubieCube b.
 public void multiply(CubieCube b)
 {
     cornerMultiply(b);
     // edgeMultiply(b);
 }
コード例 #13
0
ファイル: CubieCube.cs プロジェクト: Larsjep/Ev3CubeSolver
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Multiply this CubieCube with another cubiecube b, restricted to the edges.
 public void edgeMultiply(CubieCube b)
 {
     Edge[] ePerm = new Edge[12];
     sbyte[] eOri = new sbyte[12];
     foreach (Edge edge in Enums.Edges)
     {
         int edgeIdx = (int)edge;
         ePerm[edgeIdx] = ep[(int)b.ep[edgeIdx]];
         eOri[edgeIdx] = (sbyte)((b.eo[edgeIdx] + eo[(int)b.ep[edgeIdx]]) % 2);
     }
     foreach (Edge e in Enums.Edges)
     {
         ep[(int) e] = ePerm[(int) e];
         eo[(int) e] = eOri[(int) e];
     }
 }
コード例 #14
0
ファイル: CoordCube.cs プロジェクト: vankrelian/Rub1k3ks
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Generate a CoordCube from a CubieCube
 public CoordCube(CubieCube c)
 {
     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
 }
コード例 #15
0
ファイル: FaceCube.cs プロジェクト: vankrelian/Rub1k3ks
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // Gives CubieCube representation of a faceletcube
        public CubieCube toCubieCube()
        {
            sbyte     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
            }
            Color col1, col2;

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

                foreach (Corner j in 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] = (sbyte)(ori % 3);
                        break;
                    }
                }
            }
            foreach (Edge i in Enum.GetValues(typeof(Edge)))
            {
                foreach (Edge j in 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);
        }
コード例 #16
0
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 // Multiply this CubieCube with another CubieCube b.
 public void multiply(CubieCube b)
 {
     cornerMultiply(b);
     // edgeMultiply(b);
 }
コード例 #17
0
ファイル: CoordCube.cs プロジェクト: vankrelian/Rub1k3ks
        static CoordCube()
        {
            if (LoadPrunData())
            {
                return;
            }

            // ******************************************Phase 1 move tables*****************************************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the twists of the corners
            // twist < 2187 in phase 2.
            // twist = 0 in phase 2.
            CubieCube a = new CubieCube();

            for (short i = 0; i < N_TWIST; i++)
            {
                a.setTwist(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.cornerMultiply(CubieCube.moveCube[j]);
                        twistMove[i, 3 * j + k] = a.getTwist();
                    }
                    a.cornerMultiply(CubieCube.moveCube[j]);                     // 4. faceturn restores
                    // a
                }
            }


            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the flips of the edges
            // flip < 2048 in phase 1
            // flip = 0 in phase 2.
            a = new CubieCube();
            for (short i = 0; i < N_FLIP; i++)
            {
                a.setFlip(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        flipMove[i, 3 * j + k] = a.getFlip();
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                    // a
                }
            }


            // ***********************************Phase 1 and 2 movetable********************************************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the four UD-slice edges FR, FL, Bl and BR
            // FRtoBRMove < 11880 in phase 1
            // FRtoBRMove < 24 in phase 2
            // FRtoBRMove = 0 for solved cube
            a = new CubieCube();
            for (short i = 0; i < N_FRtoBR; i++)
            {
                a.setFRtoBR(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        FRtoBR_Move[i, 3 * j + k] = a.getFRtoBR();
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                }
            }


            // *******************************************Phase 1 and 2 movetable************************************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for permutation of six corners. The positions of the DBL and DRB corners are determined by the parity.
            // URFtoDLF < 20160 in phase 1
            // URFtoDLF < 20160 in phase 2
            // URFtoDLF = 0 for solved cube.
            a = new CubieCube();
            for (short i = 0; i < N_URFtoDLF; i++)
            {
                a.setURFtoDLF(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.cornerMultiply(CubieCube.moveCube[j]);
                        URFtoDLF_Move[i, 3 * j + k] = a.getURFtoDLF();
                    }
                    a.cornerMultiply(CubieCube.moveCube[j]);
                }
            }


            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the permutation of six U-face and D-face edges in phase2. The positions of the DL and DB edges are
            // determined by the parity.
            // URtoDF < 665280 in phase 1
            // URtoDF < 20160 in phase 2
            // URtoDF = 0 for solved cube.
            a = new CubieCube();
            for (short i = 0; i < N_URtoDF; i++)
            {
                a.setURtoDF(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        URtoDF_Move[i, 3 * j + k] = (short)a.getURtoDF();
                        // Table values are only valid for phase 2 moves!
                        // For phase 1 moves, casting to short is not possible.
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                }
            }


            // **************************helper move tables to compute URtoDF for the beginning of phase2************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the three edges UR,UF and UL in phase1.
            a = new CubieCube();
            for (short i = 0; i < N_URtoUL; i++)
            {
                a.setURtoUL(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        URtoUL_Move[i, 3 * j + k] = a.getURtoUL();
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                }
            }


            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the three edges UB,DR and DF in phase1.
            a = new CubieCube();
            for (short i = 0; i < N_UBtoDF; i++)
            {
                a.setUBtoDF(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        UBtoDF_Move[i, 3 * j + k] = a.getUBtoDF();
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                }
            }


            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Table to merge the coordinates of the UR,UF,UL and UB,DR,DF edges at the beginning of phase2
            // for i, j <336 the six edges UR,UF,UL,UB,DR,DF are not in the
            // UD-slice and the index is <20160
            for (short uRtoUL = 0; uRtoUL < 336; uRtoUL++)
            {
                for (short uBtoDF = 0; uBtoDF < 336; uBtoDF++)
                {
                    MergeURtoULandUBtoDF[uRtoUL, uBtoDF] = (short)CubieCube.getURtoDF(uRtoUL, uBtoDF);
                }
            }


            // ****************************************Pruning tables for the search*********************************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Pruning table for the permutation of the corners and the UD-slice edges in phase2.
            // The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
            for (int i = 0; i < N_SLICE2 * N_URFtoDLF * N_PARITY / 2; i++)
            {
                Slice_URFtoDLF_Parity_Prun[i] = -1;
            }
            int depth = 0;

            setPruning(Slice_URFtoDLF_Parity_Prun, 0, 0);
            int done = 1;

            while (done != N_SLICE2 * N_URFtoDLF * N_PARITY)
            {
                for (int i = 0; i < N_SLICE2 * N_URFtoDLF * N_PARITY; i++)
                {
                    int parity   = i % 2;
                    int URFtoDLF = (i / 2) / N_SLICE2;
                    int slice    = (i / 2) % N_SLICE2;
                    if (((i % 2 == 0) ? (Slice_URFtoDLF_Parity_Prun[i >> 1] & 0x0f) : ((Slice_URFtoDLF_Parity_Prun[i >> 1] & 0xf0) >> 4)) == depth)
                    {
                        for (int j = 0; j < 18; j++)
                        {
                            switch (j)
                            {
                            case 3:
                            case 5:
                            case 6:
                            case 8:
                            case 12:
                            case 14:
                            case 15:
                            case 17:
                                continue;

                            default:
                                int newSlice    = FRtoBR_Move[slice, j];
                                int newURFtoDLF = URFtoDLF_Move[URFtoDLF, j];
                                int newParity   = parityMove[parity][j];
                                int index       = (N_SLICE2 * newURFtoDLF + newSlice) * 2 + newParity;
                                if (((index % 2 == 0) ? (Slice_URFtoDLF_Parity_Prun[index >> 1] & 0x0f) : ((Slice_URFtoDLF_Parity_Prun[index >> 1] & 0xf0) >> 4)) == 0x0f)
                                {
                                    setPruning(Slice_URFtoDLF_Parity_Prun, (N_SLICE2 * newURFtoDLF + newSlice) * 2 + newParity,
                                               (sbyte)(depth + 1));
                                    done++;
                                }
                                break;
                            }
                        }
                    }
                }
                depth++;
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Pruning table for the permutation of the edges in phase2.
            // The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
            for (int i = 0; i < N_SLICE2 * N_URtoDF * N_PARITY / 2; i++)
            {
                Slice_URtoDF_Parity_Prun[i] = -1;
            }
            depth = 0;
            setPruning(Slice_URtoDF_Parity_Prun, 0, 0);
            done = 1;
            while (done != N_SLICE2 * N_URtoDF * N_PARITY)
            {
                for (int i = 0; i < N_SLICE2 * N_URtoDF * N_PARITY; i++)
                {
                    int parity = i % 2;
                    int URtoDF = (i / 2) / N_SLICE2;
                    int slice  = (i / 2) % N_SLICE2;
                    if (((i % 2 == 0) ? (Slice_URtoDF_Parity_Prun[i >> 1] & 0x0f) : ((Slice_URtoDF_Parity_Prun[i >> 1] & 0xf0) >> 4)) == depth)
                    {
                        for (int j = 0; j < 18; j++)
                        {
                            switch (j)
                            {
                            case 3:
                            case 5:
                            case 6:
                            case 8:
                            case 12:
                            case 14:
                            case 15:
                            case 17:
                                continue;

                            default:
                                int newSlice  = FRtoBR_Move[slice, j];
                                int newURtoDF = URtoDF_Move[URtoDF, j];
                                int newParity = parityMove[parity][j];
                                int index     = (N_SLICE2 * newURtoDF + newSlice) * 2 + newParity;
                                if (((index % 2 == 0) ? (Slice_URtoDF_Parity_Prun[index >> 1] & 0x0f) : ((Slice_URtoDF_Parity_Prun[index >> 1] & 0xf0) >> 4)) == 0x0f)
                                {
                                    setPruning(Slice_URtoDF_Parity_Prun, (N_SLICE2 * newURtoDF + newSlice) * 2 + newParity,
                                               (sbyte)(depth + 1));
                                    done++;
                                }
                                break;
                            }
                        }
                    }
                }
                depth++;
            }


            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Pruning table for the twist of the corners and the position (not permutation) of the UD-slice edges in phase1
            // The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.

            for (int i = 0; i < N_SLICE1 * N_TWIST / 2 + 1; i++)
            {
                Slice_Twist_Prun[i] = -1;
            }
            depth = 0;
            setPruning(Slice_Twist_Prun, 0, (sbyte)0);
            done = 1;
            while (done != N_SLICE1 * N_TWIST)
            {
                for (int i = 0; i < N_SLICE1 * N_TWIST; i++)
                {
                    int twist = i / N_SLICE1, slice = i % N_SLICE1;
                    if (((i % 2 == 0) ? (Slice_Twist_Prun[i >> 1] & 0x0f) : ((Slice_Twist_Prun[i >> 1] & 0xf0) >> 4)) == depth)
                    {
                        for (int j = 0; j < 18; j++)
                        {
                            int newSlice = FRtoBR_Move[slice * 24, j] / 24;
                            int newTwist = twistMove[twist, j];
                            int index    = N_SLICE1 * newTwist + newSlice;
                            if (((index % 2 == 0) ? (Slice_Twist_Prun[index >> 1] & 0x0f) : ((Slice_Twist_Prun[index >> 1] & 0xf0) >> 4)) == 0x0f)
                            {
                                setPruning(Slice_Twist_Prun, N_SLICE1 * newTwist + newSlice, (sbyte)(depth + 1));
                                done++;
                            }
                        }
                    }
                }
                depth++;
            }


            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Pruning table for the flip of the edges and the position (not permutation) of the UD-slice edges in phase1
            // The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.

            for (int i = 0; i < N_SLICE1 * N_FLIP / 2; i++)
            {
                Slice_Flip_Prun[i] = -1;
            }
            depth = 0;
            setPruning(Slice_Flip_Prun, 0, 0);
            done = 1;
            while (done != N_SLICE1 * N_FLIP)
            {
                for (int i = 0; i < N_SLICE1 * N_FLIP; i++)
                {
                    int flip = i / N_SLICE1, slice = i % N_SLICE1;
                    if (((i % 2 == 0) ? (Slice_Flip_Prun[i >> 1] & 0x0f) : ((Slice_Flip_Prun[i >> 1] & 0xf0) >> 4)) == depth)
                    {
                        for (int j = 0; j < 18; j++)
                        {
                            int newSlice = FRtoBR_Move[slice * 24, j] / 24;
                            int newFlip  = flipMove[flip, j];
                            int index    = N_SLICE1 * newFlip + newSlice;
                            if (((index % 2 == 0) ? (Slice_Flip_Prun[index >> 1] & 0x0f) : ((Slice_Flip_Prun[index >> 1] & 0xf0) >> 4)) == 0x0f)
                            {
                                setPruning(Slice_Flip_Prun, N_SLICE1 * newFlip + newSlice, (sbyte)(depth + 1));
                                done++;
                            }
                        }
                    }
                }
                depth++;
            }

            SavePrunData();
        }
コード例 #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, 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);
        }
コード例 #19
0
ファイル: CoordCube.cs プロジェクト: vankrelian/Rub1k3ks
        static CoordCube()
        {
            if (LoadPrunData()) return;

            // ******************************************Phase 1 move tables*****************************************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the twists of the corners
            // twist < 2187 in phase 2.
            // twist = 0 in phase 2.
            CubieCube a = new CubieCube();
            for (short i = 0; i < N_TWIST; i++)
            {
                a.setTwist(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.cornerMultiply(CubieCube.moveCube[j]);
                        twistMove[i, 3*j + k] = a.getTwist();
                    }
                    a.cornerMultiply(CubieCube.moveCube[j]); // 4. faceturn restores
                    // a
                }
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the flips of the edges
            // flip < 2048 in phase 1
            // flip = 0 in phase 2.
            a = new CubieCube();
            for (short i = 0; i < N_FLIP; i++)
            {
                a.setFlip(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        flipMove[i, 3*j + k] = a.getFlip();
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                    // a
                }
            }

            // ***********************************Phase 1 and 2 movetable********************************************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the four UD-slice edges FR, FL, Bl and BR
            // FRtoBRMove < 11880 in phase 1
            // FRtoBRMove < 24 in phase 2
            // FRtoBRMove = 0 for solved cube
            a = new CubieCube();
            for (short i = 0; i < N_FRtoBR; i++)
            {
                a.setFRtoBR(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        FRtoBR_Move[i, 3*j + k] = a.getFRtoBR();
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                }
            }

            // *******************************************Phase 1 and 2 movetable************************************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for permutation of six corners. The positions of the DBL and DRB corners are determined by the parity.
            // URFtoDLF < 20160 in phase 1
            // URFtoDLF < 20160 in phase 2
            // URFtoDLF = 0 for solved cube.
            a = new CubieCube();
            for (short i = 0; i < N_URFtoDLF; i++)
            {
                a.setURFtoDLF(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.cornerMultiply(CubieCube.moveCube[j]);
                        URFtoDLF_Move[i, 3*j + k] = a.getURFtoDLF();
                    }
                    a.cornerMultiply(CubieCube.moveCube[j]);
                }
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the permutation of six U-face and D-face edges in phase2. The positions of the DL and DB edges are
            // determined by the parity.
            // URtoDF < 665280 in phase 1
            // URtoDF < 20160 in phase 2
            // URtoDF = 0 for solved cube.
            a = new CubieCube();
            for (short i = 0; i < N_URtoDF; i++)
            {
                a.setURtoDF(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        URtoDF_Move[i, 3*j + k] = (short) a.getURtoDF();
                        // Table values are only valid for phase 2 moves!
                        // For phase 1 moves, casting to short is not possible.
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                }
            }

            // **************************helper move tables to compute URtoDF for the beginning of phase2************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the three edges UR,UF and UL in phase1.
            a = new CubieCube();
            for (short i = 0; i < N_URtoUL; i++)
            {
                a.setURtoUL(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        URtoUL_Move[i, 3*j + k] = a.getURtoUL();
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                }
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Move table for the three edges UB,DR and DF in phase1.
            a = new CubieCube();
            for (short i = 0; i < N_UBtoDF; i++)
            {
                a.setUBtoDF(i);
                for (int j = 0; j < 6; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        a.edgeMultiply(CubieCube.moveCube[j]);
                        UBtoDF_Move[i, 3*j + k] = a.getUBtoDF();
                    }
                    a.edgeMultiply(CubieCube.moveCube[j]);
                }
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Table to merge the coordinates of the UR,UF,UL and UB,DR,DF edges at the beginning of phase2
            // for i, j <336 the six edges UR,UF,UL,UB,DR,DF are not in the
            // UD-slice and the index is <20160
            for (short uRtoUL = 0; uRtoUL < 336; uRtoUL++)
            {
                for (short uBtoDF = 0; uBtoDF < 336; uBtoDF++)
                {
                    MergeURtoULandUBtoDF[uRtoUL, uBtoDF] = (short) CubieCube.getURtoDF(uRtoUL, uBtoDF);
                }
            }

            // ****************************************Pruning tables for the search*********************************************

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Pruning table for the permutation of the corners and the UD-slice edges in phase2.
            // The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
            for (int i = 0; i < N_SLICE2*N_URFtoDLF*N_PARITY/2; i++)
                Slice_URFtoDLF_Parity_Prun[i] = -1;
            int depth = 0;
            setPruning(Slice_URFtoDLF_Parity_Prun, 0, 0);
            int done = 1;
            while (done != N_SLICE2*N_URFtoDLF*N_PARITY)
            {
                for (int i = 0; i < N_SLICE2*N_URFtoDLF*N_PARITY; i++)
                {
                    int parity = i%2;
                    int URFtoDLF = (i/2)/N_SLICE2;
                    int slice = (i/2)%N_SLICE2;
                    if (((i % 2 == 0) ? (Slice_URFtoDLF_Parity_Prun[i >> 1] & 0x0f) : ((Slice_URFtoDLF_Parity_Prun[i >> 1] & 0xf0) >> 4)) == depth)
                    {
                        for (int j = 0; j < 18; j++)
                        {
                            switch (j)
                            {
                            case 3:
                            case 5:
                            case 6:
                            case 8:
                            case 12:
                            case 14:
                            case 15:
                            case 17:
                                continue;
                            default:
                                int newSlice = FRtoBR_Move[slice, j];
                                int newURFtoDLF = URFtoDLF_Move[URFtoDLF, j];
                                int newParity = parityMove[parity][j];
                                int index = (N_SLICE2*newURFtoDLF + newSlice)*2 + newParity;
                                if (((index % 2 == 0) ? (Slice_URFtoDLF_Parity_Prun[index >> 1] & 0x0f) : ((Slice_URFtoDLF_Parity_Prun[index >> 1] & 0xf0) >> 4)) == 0x0f)
                                {
                                    setPruning(Slice_URFtoDLF_Parity_Prun, (N_SLICE2*newURFtoDLF + newSlice)*2 + newParity,
                                        (sbyte) (depth + 1));
                                    done++;
                                }
                                break;
                            }
                        }
                    }
                }
                depth++;
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Pruning table for the permutation of the edges in phase2.
            // The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
            for (int i = 0; i < N_SLICE2*N_URtoDF*N_PARITY/2; i++)
                Slice_URtoDF_Parity_Prun[i] = -1;
            depth = 0;
            setPruning(Slice_URtoDF_Parity_Prun, 0, 0);
            done = 1;
            while (done != N_SLICE2*N_URtoDF*N_PARITY)
            {
                for (int i = 0; i < N_SLICE2*N_URtoDF*N_PARITY; i++)
                {
                    int parity = i%2;
                    int URtoDF = (i/2)/N_SLICE2;
                    int slice = (i/2)%N_SLICE2;
                    if (((i % 2 == 0) ? (Slice_URtoDF_Parity_Prun[i >> 1] & 0x0f) : ((Slice_URtoDF_Parity_Prun[i >> 1] & 0xf0) >> 4)) == depth)
                    {
                        for (int j = 0; j < 18; j++)
                        {
                            switch (j)
                            {
                            case 3:
                            case 5:
                            case 6:
                            case 8:
                            case 12:
                            case 14:
                            case 15:
                            case 17:
                                continue;
                            default:
                                int newSlice = FRtoBR_Move[slice, j];
                                int newURtoDF = URtoDF_Move[URtoDF, j];
                                int newParity = parityMove[parity][j];
                                int index = (N_SLICE2*newURtoDF + newSlice)*2 + newParity;
                                if (((index % 2 == 0) ? (Slice_URtoDF_Parity_Prun[index >> 1] & 0x0f) : ((Slice_URtoDF_Parity_Prun[index >> 1] & 0xf0) >> 4)) == 0x0f)
                                {
                                    setPruning(Slice_URtoDF_Parity_Prun, (N_SLICE2*newURtoDF + newSlice)*2 + newParity,
                                        (sbyte) (depth + 1));
                                    done++;
                                }
                                break;
                            }
                        }
                    }
                }
                depth++;
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Pruning table for the twist of the corners and the position (not permutation) of the UD-slice edges in phase1
            // The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.

            for (int i = 0; i < N_SLICE1*N_TWIST/2 + 1; i++)
                Slice_Twist_Prun[i] = -1;
            depth = 0;
            setPruning(Slice_Twist_Prun, 0, (sbyte) 0);
            done = 1;
            while (done != N_SLICE1*N_TWIST)
            {
                for (int i = 0; i < N_SLICE1*N_TWIST; i++)
                {
                    int twist = i/N_SLICE1, slice = i%N_SLICE1;
                    if (((i % 2 == 0) ? (Slice_Twist_Prun[i >> 1] & 0x0f) : ((Slice_Twist_Prun[i >> 1] & 0xf0) >> 4)) == depth)
                    {
                        for (int j = 0; j < 18; j++)
                        {
                            int newSlice = FRtoBR_Move[slice*24, j]/24;
                            int newTwist = twistMove[twist, j];
                            int index = N_SLICE1*newTwist + newSlice;
                            if (((index % 2 == 0) ? (Slice_Twist_Prun[index >> 1] & 0x0f) : ((Slice_Twist_Prun[index >> 1] & 0xf0) >> 4)) == 0x0f)
                            {
                                setPruning(Slice_Twist_Prun, N_SLICE1*newTwist + newSlice, (sbyte) (depth + 1));
                                done++;
                            }
                        }
                    }
                }
                depth++;
            }

            // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            // Pruning table for the flip of the edges and the position (not permutation) of the UD-slice edges in phase1
            // The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.

            for (int i = 0; i < N_SLICE1*N_FLIP/2; i++)
                Slice_Flip_Prun[i] = -1;
            depth = 0;
            setPruning(Slice_Flip_Prun, 0,  0);
            done = 1;
            while (done != N_SLICE1*N_FLIP)
            {
                for (int i = 0; i < N_SLICE1*N_FLIP; i++)
                {
                    int flip = i/N_SLICE1, slice = i%N_SLICE1;
                    if (((i % 2 == 0) ? (Slice_Flip_Prun[i >> 1] & 0x0f) : ((Slice_Flip_Prun[i >> 1] & 0xf0) >> 4)) == depth)
                    {
                        for (int j = 0; j < 18; j++)
                        {
                            int newSlice = FRtoBR_Move[slice*24, j]/24;
                            int newFlip = flipMove[flip, j];
                            int index = N_SLICE1*newFlip + newSlice;
                            if (((index % 2 == 0) ? (Slice_Flip_Prun[index >> 1] & 0x0f) : ((Slice_Flip_Prun[index >> 1] & 0xf0) >> 4)) == 0x0f)
                            {
                                setPruning(Slice_Flip_Prun, N_SLICE1*newFlip + newSlice, (sbyte) (depth + 1));
                                done++;
                            }
                        }
                    }
                }
                depth++;
            }

            SavePrunData();
        }
コード例 #20
0
ファイル: CubieCube.cs プロジェクト: Larsjep/Ev3CubeSolver
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        // 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];
            sbyte[] cOri = new sbyte[8];
            foreach (Corner corn in Enums.Corners)
            {
                cPerm[(int) corn] = cp[(int) b.cp[(int) corn]];

                sbyte oriA = co[(int) b.cp[(int) corn]];
                sbyte oriB = b.co[(int) corn];
                sbyte ori = 0;
                ;
                if (oriA < 3 && oriB < 3) // if both cubes are regular cubes...
                {
                    ori = (sbyte) (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 = (sbyte) (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 = (sbyte) (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 = (sbyte) (oriA - oriB);
                    if (ori < 0)
                        ori += 3; // the composition is a regular cube
                    // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                }
                cOri[(int) corn] = ori;
            }
            foreach (Corner c in Enums.Corners)
            {
                int cornerIdx = (int) c;
                cp[cornerIdx] = cPerm[cornerIdx];
                co[cornerIdx] = cOri[cornerIdx];
            }
        }