public static ImmutableArray <ushort> Create() { var udEdgesConj = new ushort[NUdEdges * NSymD4H]; for (var t = 0; t < 0 + NUdEdges; t++) { if ((t + 1) % 400 == 0) { Console.Write("."); } if ((t + 1) % 32000 == 0) { Console.WriteLine(""); } var cc = SolvedCube.Instance.Clone(); cc.set_ud_edges(t); for (var s = 0; s < 0 + NSymD4H; s++) { var ss = Basic.Cubes[s].Clone(); ss.EdgeMultiply(cc); ss.EdgeMultiply(Inverse.GetCube(s)); udEdgesConj[NSymD4H * t + s] = Convert.ToUInt16(ss.get_ud_edges()); //TODO remove all these } } return(udEdgesConj.ToImmutableArray()); }
public void InversesShouldMultiplyToSolvedCube(int i) { var sym = Basic.Cubes[i].Clone(); var inv = Inverse.GetCube(i); sym.Multiply(inv); sym.Should().Be(SolvedCube.Instance); }
/// <summary> /// Get the symmetries and antisymmetries of the cube /// </summary> public static IEnumerable <int> Symmetries(this ICubieCube cubieCube) { for (var j = 0; j < Definitions.NSym; j++) { var c = Basic.Cubes[j].Clone(); c.Multiply(cubieCube); c.Multiply(Inverse.GetCube(j)); if (CubeComparer.Instance.Equals(cubieCube, c)) { yield return(j); } var d = c.Invert(); if (CubeComparer.Instance.Equals(cubieCube, d)) { yield return(j + Definitions.NSym); } } }
/// <summary> /// Creates the new table in memory /// </summary> /// <returns></returns> public override uint[] Create() { const int total = NCornersClass * NUdEdges; var table = new uint[total / 16]; Array.Fill(table, uint.MaxValue); // ##################### create table with the symmetries of the corners classes ################################ var cc = SolvedCube.Instance.Clone(); var cSym = new ushort[NCornersClass]; for (var i = 0; i < 0 + NCornersClass; i++) { if ((i + 1) % 1000 == 0) { Console.Write("."); } var rep = CornerSymmetries.CornerRep[i]; cc.set_corners(rep); for (byte s = 0; s < NSymD4H; s++) { var ss = Basic.Cubes[s].Clone(); ss.CornerMultiply(cc); ss.CornerMultiply(Inverse.GetCube(s)); if (ss.get_corners() == rep) { const ushort u = 1; var q = Convert.ToUInt16(u << s); cSym[i] |= q; } } } Console.WriteLine(); //############################################################################################################### var udEdge = 0; set_corners_ud_edges_depth3(NUdEdges * 0 + udEdge, 0, table); var done = 1; uint depth = 0; Console.WriteLine($"depth: {depth} done: {done}/{total}"); while (depth < 10) { // we fill the table only do depth 9 + 1 var depth3 = depth % 3; var idx = 0; var mult = 2; if (depth > 9) { mult = 1; } for (var cClassIndex = 0; cClassIndex < NCornersClass; cClassIndex++) { { if ((cClassIndex + 1) % (20 * mult) == 0) { Console.Write("."); } if ((cClassIndex + 1) % (1600 * mult) == 0) { Console.WriteLine(""); } udEdge = 0; while (udEdge < NUdEdges) { // ################ if table entries are not populated, this is very fast: ########################## if (idx % 16 == 0 && table[idx / 16] == uint.MaxValue && udEdge < NUdEdges - 16) { udEdge += 16; idx += 16; continue; } //################################################################################################### if (get_corners_ud_edges_depth3(idx, table) == depth3) { var corner = CornerSymmetries.CornerRep[cClassIndex]; // only iterate phase 2 SpecialMoves foreach (var m in Phase2MoveEnums) { var udEdge1 = SpecialMoves.UdEdgesMove[18 * udEdge + (int)m]; var corner1 = SpecialMoves.CornersMove[18 * corner + (int)m]; var c1ClassIndex = CornerSymmetries.CornerClassidx[corner1]; var c1Sym = CornerSymmetries.CornerSym[corner1]; udEdge1 = UdEdges.GetUdEdgesConj(udEdge1, c1Sym);// Symmetries.UdEdgesConjugation.UdEdgesConj[(udEdge1 << 4) + c1Sym]; var idx1 = 40320 * c1ClassIndex + udEdge1; if (get_corners_ud_edges_depth3(idx1, table) == 3) { // entry not yet filled set_corners_ud_edges_depth3(idx1, (depth + 1) % 3, table); done += 1; // ######symmetric position has eventually more than one representation ############# var sym = cSym[c1ClassIndex]; if (sym != 1) { for (byte j = 1; j < 16; j++) { sym >>= 1; if (sym % 2 == 1) { var udEdge2 = UdEdges.GetUdEdgesConj(udEdge1, j); // c1_classidx does not change var idx2 = 40320 * c1ClassIndex + udEdge2; if (get_corners_ud_edges_depth3(idx2, table) == 3) { set_corners_ud_edges_depth3(idx2, (depth + 1) % 3, table); done += 1; //################################################################################### } } } } } } } udEdge += 1; idx += 1; } } } depth += 1; Console.WriteLine(); Console.WriteLine($"depth: {depth} done: {done}/{total}"); } return(table); }
public override uint[] Create() { const int total = NFlipsliceClass * NTwist; var table = new uint[total / 16 + 1]; Array.Fill(table, uint.MaxValue); // #################### create table with the symmetries of the flipslice classes ############################### var cc = SolvedCube.Instance.Clone(); var fsSym = new int[NFlipsliceClass]; for (var i = 0; i < NFlipsliceClass; i++) { if ((i + 1) % 1000 == 0) { Console.Write("."); } var rep = FlipSlice.FlipsliceRep[i]; var repModFlip = Convert.ToInt32(rep % NFlip); cc.set_slice(Convert.ToUInt16(rep / NFlip)); cc.set_flip(repModFlip); for (var s = 0; s < NSymD4H; s++) { var ss = Basic.Cubes[s].Clone(); ss.EdgeMultiply(cc); ss.EdgeMultiply(Inverse.GetCube(s)); if (ss.get_slice() == rep / NFlip && ss.get_flip() == repModFlip) { fsSym[i] |= 1 << s; } } } Console.WriteLine(); // ################################################################################################################## var twist = 0; set_flipslice_twist_depth3(NTwist * 0 + twist, 0, table); var done = 1; uint depth = 0; var backSearch = false; Console.WriteLine($"depth: {depth} done: {done}/{total}"); while (done < total) { var depth3 = depth % 3; if (depth == 9) { // backwards search is faster for depth >= 9 Console.WriteLine("flipping to backwards search..."); backSearch = true; } var mult = depth < 8 ? 5 : 1; var idx = 0; for (var fsClassidx = 0; fsClassidx < NFlipsliceClass; fsClassidx++) { if ((fsClassidx + 1) % (200 * mult) == 0) { Console.Write("."); } if ((fsClassidx + 1) % (16000 * mult) == 0) { Console.WriteLine(""); } twist = 0; while (twist < NTwist) { // ########## if table entries are not populated, this is very fast: ################################ if (!backSearch && idx % 16 == 0 && table[idx / 16] == uint.MaxValue && twist < NTwist - 16) { twist += 16; idx += 16; continue; } //################################################################################################### bool match; if (backSearch) { match = get_flipslice_twist_depth3(idx, table) == 3; } else { match = get_flipslice_twist_depth3(idx, table) == depth3; } if (match) { var flipslice = FlipSlice.FlipsliceRep[fsClassidx]; var flip = Convert.ToInt32(flipslice % 2048); var slice = Convert.ToInt32(flipslice >> 11); foreach (var m in Extensions.GetEnumValues <Move>()) { var twist1 = SpecialMoves.TwistMove[18 * twist + (int)m]; var flip1 = SpecialMoves.FlipMove[18 * flip + (int)m]; var slice1 = SpecialMoves.SliceSortedMove[432 * slice + (int)m] / 24; var flipslice1 = (slice1 << 11) + flip1; var fs1Classidx = FlipSlice.FlipsliceClassidx[flipslice1]; var fs1Sym = FlipSlice.FlipsliceSym[flipslice1]; twist1 = ConjTwist.GetTwistConj(twist1, fs1Sym); var idx1 = Convert.ToInt32(2187 * fs1Classidx + twist1); if (!backSearch) { if (get_flipslice_twist_depth3(idx1, table) == 3) { // entry not yet filled set_flipslice_twist_depth3(idx1, (depth + 1) % 3, table); done += 1; // ####symmetric position has eventually more than one representation ############### var sym = fsSym[fs1Classidx]; if (sym != 1) { for (byte j = 1; j < 16; j++) { sym >>= 1; if (sym % 2 == 1) { var twist2 = ConjTwist.GetTwistConj(twist1, j); // fs2_classidx = fs1_classidx due to symmetry var idx2 = Convert.ToInt32(2187 * fs1Classidx + twist2); if (get_flipslice_twist_depth3(idx2, table) == 3) { set_flipslice_twist_depth3(idx2, (depth + 1) % 3, table); done += 1; } } } } } } else { // backwards search if (get_flipslice_twist_depth3(idx1, table) == depth3) { set_flipslice_twist_depth3(idx, (depth + 1) % 3, table); done += 1; //this doesn't seem to be working break; } } } } twist += 1; idx += 1; } } depth += 1; Console.WriteLine(); Console.WriteLine($"depth: {depth} done: {done}/{total}"); } return(table); }