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