Exemplo n.º 1
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());
        }
        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();
        }