public static void CreateTables()
        {
            int totalcombinations = 594 * 2048 * 495;

            // create files to write table to
            byte[] zeroes = new byte[594 * 495];
            FileStream moves = new FileStream("c:/temp/phase1.bin", FileMode.Create, FileAccess.ReadWrite);
            for (int i = 0; i < 2048; i++)
            {
                moves.Write(zeroes, 0, zeroes.Length);
            }

            Cube c = new Cube();

            // initialize to not reached
            byte[] steps = new byte[totalcombinations];
            for (int index=0; index<steps.Length; index++)
            {
                steps[index] = 255;
            }

            // create the root situation for this phase
            int dummym;
            steps[getindex(c, out dummym)] = 0;

            // iteratively add newly reachable situations
            for (int distance=0; distance<250; distance++)
            {
                int currentsituations = 0;
                int foundnew = 0;
                int foundfaster = 0;

                long start = DateTime.Now.Ticks / 10000;  // ms

                for (int index = 0; index < totalcombinations; index++)
                {
                    // consider only situations with current distance to get next situations
                    if (steps[index] == distance)
                    {
                        currentsituations++;    // count situtaions with this distance

                        setcube(c, index);
                        for (int a= 1; a <= Cube.B3D3; a++)
                        {
                            c.DoIncrementalAction(a);

                            int mir;
                            int ni = getindex(c, out mir);

                            int newdistance = distance+Cube.time_actions[a];
                            if (newdistance < steps[ni])       // found a faster route
                            {
                                if (steps[ni]==255)
                                {   foundnew++;
                                }
                                else
                                {   foundfaster++;
                                }
                                // memorize shorter distance
                                steps[ni] = (byte) newdistance;

                                // write to file
                                moves.Seek(ni, SeekOrigin.Begin);
                                moves.WriteByte((byte) (Cube.sym_actions[mir][a]));
                            }
                        }
                    }
                }

                long end = DateTime.Now.Ticks / 10000;  // ms
                Console.WriteLine(distance+": Situations: "+currentsituations+" New: " + foundnew+" Improved: "+foundfaster+"  ("+(end-start)+" ms)");
            }

            // finish writing
            moves.Close();
        }
        private static void BuildSymmetricalIndizes()
        {
            Cube c = new Cube();

            symEdgeFlipIndex = new int[2048][];
            for (int i = 0; i < symEdgeFlipIndex.Length; i++)
            {
                c.SetEdgeFlipFromIndex(i);
                int s0 = c.GetEdgeFlipIndex();
                c.MirrorUD();
                int ud = c.GetEdgeFlipIndex();
                c.MirrorLR();
                int ud_lr = c.GetEdgeFlipIndex();
                c.MirrorUD();
                int lr = c.GetEdgeFlipIndex();
                c.MirrorLR();
                if (i != s0 || i!=c.GetEdgeFlipIndex())
                {
                    Console.WriteLine("Edge flip mirror calcuation error");
                }
                symEdgeFlipIndex[i] = new int[] { s0, ud, lr, ud_lr };
            }

            symMiddleEdgeDistributionIndex = new int[495][];
            for (int i = 0; i < symMiddleEdgeDistributionIndex.Length; i++)
            {
                c.SetMiddleEdgeDistributionFromIndex(i);
                int s0 = c.GetMiddleEdgeDistributionIndex();
                c.MirrorUD();
                int ud = c.GetMiddleEdgeDistributionIndex();
                c.MirrorLR();
                int ud_lr = c.GetMiddleEdgeDistributionIndex();
                c.MirrorUD();
                int lr = c.GetMiddleEdgeDistributionIndex();
                c.MirrorLR();
                if (i != s0 || i != c.GetMiddleEdgeDistributionIndex())
                {
                    Console.WriteLine("Middle Edge Distribution mirror calcuation error: "+i+"!="+s0);
                }
                symMiddleEdgeDistributionIndex[i] = new int[] { s0, ud, lr, ud_lr };
            }
        }
        private static void BuildTwistSymGroup()
        {
            twistSymGroup = new int[2187];
            symGroupMembers = new int[594][];
            for (int i = 0; i < twistSymGroup.Length; i++)
            {
                twistSymGroup[i] = -1;
            }
            int numGroups = 0;

            Cube c = new Cube();

            for (int i=0; i<twistSymGroup.Length; i++)
            {
                if (twistSymGroup[i]<0)
                {
                    c.SetCornerTwistFromIndex(i);
                    int s0 = c.GetCornerTwistIndex();
                    c.MirrorUD();
                    int ud = c.GetCornerTwistIndex();
                    c.MirrorLR();
                    int ud_lr = c.GetCornerTwistIndex();
                    c.MirrorUD();
                    int lr = c.GetCornerTwistIndex();
                    c.MirrorLR();
                    if (s0!=c.GetCornerTwistIndex() || i!=s0)
                    {
                        Console.WriteLine("ERROR: symmetry action do not match original situation!");
                    }

                    int g = numGroups++;

                    if (twistSymGroup[s0] >= 0 || twistSymGroup[ud]>=0 || twistSymGroup[lr]>=0 || twistSymGroup[ud_lr]>= 0)
                    {
                        Console.WriteLine("ERROR: Overwriting symmetry group member");
                    }

                    twistSymGroup[s0] = g;
                    twistSymGroup[ud] = g;
                    twistSymGroup[lr] = g;
                    twistSymGroup[ud_lr] = g;

                    symGroupMembers[g] = new int[] { s0, ud, lr, ud_lr };

            //                    Console.Write(g + ": " + s0 + " " + ud+ " " + lr+ " " + ud_lr + "  ");
            //                    if ((numGroups % 2) == 0) Console.WriteLine();
                }
            }
        }
        public static void setcube(Cube c, int index, int symtype)
        {
            int tg = (index % 594);
            index = index / 594;
            int e = (index % 2048);
            index = index / 2048;
            int d = index;

            c.SetCornerTwistFromIndex(symGroupMembers[tg][symtype]);
            c.SetEdgeFlipFromIndex(symEdgeFlipIndex[e][symtype]);
            c.SetMiddleEdgeDistributionFromIndex(symMiddleEdgeDistributionIndex[d][symtype]);
        }
        public static int Solve(Cube c, int[] histogram)
        {
            FileStream file = new FileStream("c:/temp/phase1.bin", FileMode.Open, FileAccess.Read);

            int m;
            int i = getindex(c, out m);
            Console.Write(i + ":" + m + " ");

            int turns = 0;
            int time = 0;
            for (;;)
            {
                i = getindex(c, out m);
            //                Console.Write("("+m+")");

                file.Seek(i, SeekOrigin.Begin);
                int b = file.ReadByte();
                if (b <= 0)
                {
                    if (c.GetCornerTwistIndex() != 0 || c.GetEdgeFlipIndex() != 0 || c.GetMiddleEdgeDistributionIndex()!=0)
                    {
                        Console.WriteLine("Phase 1 leads to unfinished cube");
                        return -1;
                    }
                    break;  // no more moves - finish operation
                }
                int a = Cube.sym_actions[m].IndexOf((char)b);

                turns++;
                time += Cube.time_actions[a];

                histogram[a]++;

                Console.Write(Cube.sym_actions[0][a]);
                c.DoReverseAction(a);

                if (turns==35)
                {
                    Console.WriteLine("Not finding solution...");
                }
            }
            //            Console.Write("  ("+turns + "/"+time+")");
            file.Close();

            return time;
        }
        public static int getindex(Cube c, out int symtype)
        {
            int t = c.GetCornerTwistIndex();
            int tg = twistSymGroup[t];
            int e = c.GetEdgeFlipIndex();
            int d = c.GetMiddleEdgeDistributionIndex();

            int es = int.MaxValue;
            int ds = int.MaxValue;
            symtype = -1;

            for (int s=0; s<4; s++)
            {
                if (symGroupMembers[tg][s]==t)
                {
                    int etmp = symEdgeFlipIndex[e][s];
                    int dtmp = symMiddleEdgeDistributionIndex[d][s];
                    if ( (etmp < es) || (etmp==es && dtmp<ds) )
                    {
                        es = etmp;
                        ds = dtmp;
                        symtype = s;
                    }
                }
            }

            return tg + 594 * (es + 2048 * ds);
        }
 public static void setcube(Cube c, int index)
 {
     setcube(c, index, Cube.SYMTYPE_NONE);
 }
        public static void CreateTables()
        {
            long totalcombinations = 10368L * 40320 * 12;

            // create files to write table parts to
            FileStream moves = new FileStream("c:/temp/phase2.log", FileMode.Create, FileAccess.Write);
            byte[] fbuffer = new byte[6];

            // initialize to not reached
            HugeByteArray steps = new HugeByteArray(totalcombinations);
            for (long index = 0; index < totalcombinations; index++)
            {
                steps[index] = 255;
            }

            // create the root situation for this phase
            Cube c = new Cube();

            int dummym;
            steps[getindex(c, out dummym)] = 0;

            Console.WriteLine("Start computing reachable positions...");

            // iteratively add newly reachable situations
            for (int distance = 0; distance < 250; distance++)
            {
                int currentsituations = 0;
                int foundnew = 0;
                int foundfaster = 0;

                long start = DateTime.Now.Ticks / 10000;  // ms

                for (long index = 0; index < totalcombinations; index++)
                {
                    // consider only situations with current distance to get next situations
                    if (steps[index] == distance)
                    {
                        currentsituations++;    // count situations with this distance

                        setcube(c, index);
                        for (int a = 1; a <= Cube.B3D3; a++)
                        {
                            c.DoIncrementalAction(a);

                            // disallow moves that would bring cube out of S1
                            if (!Cube.s1_actions[a])
                            {
                                continue;
                            }

                            int mir;
                            long ni = getindex(c, out mir);

                            int newdistance = distance + Cube.time_actions[a];
                            if (newdistance < steps[ni])       // found a faster route
                            {
                                if (steps[ni] == 255)
                                {
                                    foundnew++;
                                }
                                else
                                {
                                    foundfaster++;
                                }
                                // memorize shorter distance
                                steps[ni] = (byte)newdistance;

                                // write to spool file (position: 5 byte, move: 1 byte)
                                fbuffer[0] = (byte)(ni & 0xff);
                                fbuffer[1] = (byte)((ni >> 8) & 0xff);
                                fbuffer[2] = (byte)((ni >> 16) & 0xff);
                                fbuffer[3] = (byte)((ni >> 24) & 0xff);
                                fbuffer[4] = (byte)((ni >> 32) & 0xff);
                                fbuffer[5] = (byte)(Cube.sym_actions[mir][a]);
                                moves.Write(fbuffer, 0, 6);
                            }
                        }
                    }
                }

                long end = DateTime.Now.Ticks / 10000;  // ms
                Console.WriteLine(distance + ": Situations: " + currentsituations + " New: " + foundnew + " Improved: " + foundfaster + "  (" + (end - start) + " ms)");
            }

            // finish writing
            moves.Close();
        }
        private static void BuildSymmetricalIndizes()
        {
            Cube c = new Cube();

            symOuterEdgePermutationIndex = new int[40320][];
            for (int i = 0; i < symOuterEdgePermutationIndex.Length; i++)
            {
                c.SetOuterEdgePermutationFromIndex(i);
                int s0 = c.GetOuterEdgePermutationIndex();
                c.MirrorUD();
                int ud = c.GetOuterEdgePermutationIndex();
                c.MirrorLR();
                int ud_lr = c.GetOuterEdgePermutationIndex();
                c.MirrorUD();
                int lr = c.GetOuterEdgePermutationIndex();
                c.MirrorLR();
                if (i != s0 || i != c.GetOuterEdgePermutationIndex())
                {
                    Console.WriteLine("outer edge permutation mirror calcuation error");
                }
                symOuterEdgePermutationIndex[i] = new int[] { s0, ud, lr, ud_lr  };
            }

            symMiddleEdgePermutationIndex = new int[24][];
            for (int i = 0; i < symMiddleEdgePermutationIndex.Length; i++)
            {
                c.SetMiddleEdgePermutationFromIndex(i);
                int s0 = c.GetMiddleEdgePermutationIndex();
                c.MirrorUD();
                int ud = c.GetMiddleEdgePermutationIndex();
                c.MirrorLR();
                int ud_lr = c.GetMiddleEdgePermutationIndex();
                c.MirrorUD();
                int lr = c.GetMiddleEdgePermutationIndex();
                c.MirrorLR();
                if (i != s0 || i != c.GetMiddleEdgePermutationIndex())
                {
                    Console.WriteLine("Middle Edge Permutation mirror calcuation error: " + i + "!=" + s0);
                }
                symMiddleEdgePermutationIndex[i] = new int[] { s0, ud, lr, ud_lr };
            }
        }
        private static void BuildCornerSymGroup()
        {
            cornerSymGroup = new int[40320];
            symGroupMembers = new int[10368][];
            for (int i = 0; i < cornerSymGroup.Length; i++)
            {
                cornerSymGroup[i] = -1;
            }
            int numGroups = 0;

            Cube c = new Cube();

            for (int i = 0; i < cornerSymGroup.Length; i++)
            {
                if (cornerSymGroup[i] < 0)
                {
                    c.SetCornerPermutationFromIndex(i);
                    int s0 = c.GetCornerPermutationIndex();
                    c.MirrorUD();
                    int ud = c.GetCornerPermutationIndex();
                    c.MirrorLR();
                    int ud_lr = c.GetCornerPermutationIndex();
                    c.MirrorUD();
                    int lr = c.GetCornerPermutationIndex();
                    c.MirrorLR();
                    if (s0 != c.GetCornerPermutationIndex() || i != s0)
                    {
                        Console.WriteLine("ERROR: symmetry action do not match original situation!");
                    }

                    int g = numGroups++;

                    if (cornerSymGroup[s0] >= 0 || cornerSymGroup[ud] >= 0 ||  cornerSymGroup[lr] >= 0 || cornerSymGroup[ud_lr] >= 0
                    )
                    {
                        Console.WriteLine("ERROR: Overwriting symmetry group member");
                    }

                    cornerSymGroup[s0] = g;
                    cornerSymGroup[ud] = g;
                    cornerSymGroup[lr] = g;
                    cornerSymGroup[ud_lr] = g;

                    symGroupMembers[g] = new int[] { s0, ud, lr, ud_lr };

            //                        Console.Write(g + ": " + s0 + " " + ud + " " + lr + " " + ud_lr + "  ");
            //                        Console.WriteLine();
                }
            }
        }
        public static int Solve(Cube c, int[] histogram)
        {
            long totalcombinations = 10368L * 40320 * 12;

            FileStream file0 = new FileStream("c:/temp/phase2_0.bin", FileMode.Open, FileAccess.Read);
            FileStream file1 = new FileStream("c:/temp/phase2_1.bin", FileMode.Open, FileAccess.Read);

            int m;
            long i = getindex(c, out m);
            //            Console.Write(i + ":" + m + " ");

            int turns = 0;
            int time = 0;
            for (; ; )
            {
                i = getindex(c, out m);
            //                Console.Write("("+m+")");

                int b;
                if (i < totalcombinations / 2)
                {
                    file0.Seek(i, SeekOrigin.Begin);
                    b = file0.ReadByte();
                }
                else
                {
                    file1.Seek(i - (totalcombinations/2), SeekOrigin.Begin);
                    b = file1.ReadByte();
                }

                if (b <= 0)
                {
                    if (c.GetCornerPermutationIndex() != 0 || c.GetOuterEdgePermutationIndex() != 0 || c.GetMiddleEdgePermutationIndex()!=0)
                    {
                        Console.WriteLine("Phase 2 leads to unfinished cube");
                    }
                    break;  // no more moves - finish operation
                }

                int a = Cube.sym_actions[m].IndexOf((char)b);

                turns++;
                time += Cube.time_actions[a];

                histogram[a]++;

                Console.Write(Cube.sym_actions[0][a]);
                c.DoReverseAction(a);

                if (turns==35)
                {
                    Console.WriteLine("Not finding solution...");
                }
            }

            //            Console.Write("  (" + turns + "/" + time + ")");

            file0.Close();
            file1.Close();

            return time;
        }
        public static void setcube(Cube c, long index, int symtype)
        {
            int tg = (int)(index % 10368);
            int t = symGroupMembers[tg][symtype];
            index = index / 10368;
            int os = (int)(index % 40320);
            index = index / 40320;
            int ms = (int)(index * 2) + (t + os) % 2;      // match the permutation parity

            int m = symMiddleEdgePermutationIndex[ms][symtype];
            int o = symOuterEdgePermutationIndex[os][symtype];

            c.SetCornerPermutationFromIndex(t);
            c.SetOuterEdgePermutationFromIndex(o);
            c.SetMiddleEdgePermutationFromIndex(m);
        }
        public static long getindex(Cube c, out int symtype)
        {
            int t = c.GetCornerPermutationIndex();
            int tg = cornerSymGroup[t];
            int o = c.GetOuterEdgePermutationIndex();
            int m = c.GetMiddleEdgePermutationIndex();
            //       Console.WriteLine("get: corner:" + t+ " outer:"+o+" middle:"+m);

            int os = int.MaxValue;
            int ms = int.MaxValue;
            symtype = -1;

            for (int s = 0; s < 4; s++)
            {
                if (symGroupMembers[tg][s] == t)
                {
                    int otmp = symOuterEdgePermutationIndex[o][s];
                    int mtmp = symMiddleEdgePermutationIndex[m][s];
                    if ((otmp < os) || (otmp == os && mtmp < ms))
                    {
                        os = otmp;
                        ms = mtmp;
                        symtype = s;
                    }
                }
            }

            return tg + 10368L * (os + 40320 * (ms / 2));
        }
Exemple #14
0
 public Cube(Cube c)
 {
     cornercubie = new int[8];
     for (int i = 0; i < 8; i++) cornercubie[i] = c.cornercubie[i];
     cornertwist = new int[8];
     for (int i = 0; i < 8; i++) cornertwist[i] = c.cornertwist[i];
     edgecubie = new int[12];
     for (int i = 0; i < 12; i++) edgecubie[i] = c.edgecubie[i];
     edgeflip = new int[12];
     for (int i = 0; i < 12; i++) edgeflip[i] = c.edgeflip[i];
 }