// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. // // --------------------------------------------------- // Rubik Miniapp: Model of the Rubik's Cube_TM Puzzle // --------------------------------------------------- // // This miniapp provides a light-hearted example of mesh manipulation and // GLVis integration. // // Compile with: make rubik // // Sample runs: rubik // echo "x21 y21 x23 y23 q\n" | ./rubik // echo "x22 z21 x22 z23 q\n" | ./rubik // echo "x22 y22 z22 q\n" | ./rubik // // Other interesting patterns: // "x13 x31 y13 y31 x13 x31 y13 y31 x13 x31 y13 y31" // "y13 z11 y11 x31 z13 y11 x33 z13 x31 z13 x11 y13 x13 z13 x33 y13 z11" // "y13 y33 z31 y13 z31 y13 z31 x13 y31 x12 y33 z31 y11 x13 z31 x11 y31" // "y13 x11 z13 y11 z33 y31 z31 y13 z33 y13 x33 y12 x13 z33 x33 z12" // // Interactive commands: // [xyz][1,2,3][0-3] // Rotate the specified tier (first integer) of the cube // about the given axis (initial character) in the clockwise // direction (looking from the tip of the axis vector towards // the origin) by so many increments (final integer). // r[0-9]+ // Initiate a random sequence of moves. The integer // following 'r' is the number of desired moves. // p // Print the current state of the cube. // c // Swap the corners in the 0th and 1st positions. // t[0,1] // Twist the corners of the bottom tier in the clockwise '1' // or counter-clockwise '0' direction leaving the 3rd corner // unchanged. // e[0,1] // Permute the edges of the bottom tier in the clockwise '1' // or counter-clockwise '0' direction leaving the 3rd edge // unchanged. // f[2,4] // Flip the edges of the bottom tier while keeping them in // place. The integer '2' indicates flipping the 0th and 2nd // edges while '4' indicates flipping all four edges. // R // Resets (or Repaints) the cube to its original configuration. // T // Solve the top tier only. // M // Solve the middle tier only (assumes the top tier has already // been solved.) // B // Solve the bottom tier only (assumes the top two tiers have already // been solved.) // s or S // Solve the cube starting from the top tier and working down. // q or Q // Quit // #include "mfem.hpp" #include "../common/mesh_extras.hpp" #include #include #include #include using namespace std; using namespace mfem; using namespace mfem::common; static int step_ = 0; static int nstep_ = 6; static int count_ = 0; static int logging_ = 0; static double cosa_ = cos(0.5 * M_PI / nstep_); static double sina_ = sin(0.5 * M_PI / nstep_); struct RubikState { // Centers are indexed by the local face indices of Geometry::Type CUBE // {Bottom, Front, Right, Back, Left, Top} int cent_[6]; // Corners are sorted according to the local vertex index of // Geometry::Type CUBE. Each corner piece is identified by the // three colors it contains. The orientation is determined by the // sequence of colors which corresponds to the x-directed, y-directed, // and then z-directed face. int corn_[24]; // Edges are sorted according to the local edge indices of // Geometry::Type CUBE. Each edge piece is identified by the two face // colors it contains. The edge piece orientations are determined by a // right-hand-rule with the thumb directed along the edge and the fingers // curling from the first face color to the second. int edge_[24]; }; static RubikState rubik; static int edge_colors_[24] = { 0,1, 0,2, 3,0, 4,0, 1,5, 2,5, 5,3, 5,4, 1,4, 2,1, 3,2, 4,3 }; static int corn_colors_[24] = { 4,1,0, 2,1,0, 2,3,0, 4,3,0, 4,1,5, 2,1,5, 2,3,5, 4,3,5 }; struct Move { char axis; int tier; int incr; }; void interactive_help(); void init_hex_mesh(Mesh & mesh); void init_state(); void print_state(ostream & out); void repaint_cube(Mesh & mesh, GridFunction & color, socketstream & sock); bool validate_centers(const int max_ind = 6); bool validate_edges(const int max_ind = 12); bool validate_corners(const int max_ind = 8); void anim_move(char axis, int tier, int increment, Mesh & mesh, GridFunction & color, socketstream & sock); void anim_move(const Move & move, Mesh & mesh, GridFunction & color, socketstream & sock) { anim_move(move.axis, move.tier, move.incr, mesh, color, sock); } void determine_random_moves(Array & moves); void swap_corners(Mesh & mesh, GridFunction & color, socketstream & sock, int * c0 = NULL, int * c1 = NULL); void twist_corners(Mesh & mesh, GridFunction & color, socketstream & sock, bool cw, int * c0 = NULL, int * c1 = NULL, int * c2 = NULL); void permute_edges(Mesh & mesh, GridFunction & color, socketstream & sock, int * e0, int * e1, int * e2); void permute_edges(Mesh & mesh, GridFunction & color, socketstream & sock, bool cw); void flip_edges(Mesh & mesh, GridFunction & color, socketstream & sock, int n, int * e0 = NULL, int * e1 = NULL, int * e2 = NULL, int * e3 = NULL); void solve_top(Mesh & mesh, GridFunction & color, socketstream & sock); void solve_mid(Mesh & mesh, GridFunction & color, socketstream & sock); void solve_bot(Mesh & mesh, GridFunction & color, socketstream & sock); void solve(Mesh & mesh, GridFunction & color, socketstream & sock); int main(int argc, char *argv[]) { bool anim = true; bool visualization = true; OptionsParser args(argc, argv); args.AddOption(&anim, "-anim", "--animation", "-no-anim", "--no-animation", "Enable or disable GLVis animation."); args.AddOption(&logging_, "-l", "--log-level", "Control the amount of logging information."); args.AddOption(&visualization, "-vis", "--visualization", "-no-vis", "--no-visualization", "Enable or disable GLVis visualization."); args.Parse(); if (!args.Good()) { args.PrintUsage(cout); return 1; } args.PrintOptions(cout); interactive_help(); if (!visualization) { anim = false; } init_state(); // Define an empty mesh Mesh mesh(3, 16 * 27, 27 * 6); // Hexagonal mesh init_hex_mesh(mesh); L2_FECollection fec(0, 3, 1); FiniteElementSpace fespace(&mesh, &fec); GridFunction color(&fespace); color = 0.0; PWConstCoefficient pwCoef(7); for (int i=1; i<=7; i++) { pwCoef(i) = (double)(i-1)/6.0; } color.ProjectCoefficient(pwCoef); // Output the initial mesh to a file { ostringstream oss; oss << "rubik-init.mesh"; ofstream ofs(oss.str().c_str()); ofs.precision(8); mesh.Print(ofs); ofs.close(); } // Output the resulting mesh to GLVis if (visualization) { char vishost[] = "localhost"; int visport = 19916; socketstream sock(vishost, visport); sock.precision(8); sock << "solution\n" << mesh << color << "keys Amaa\n" << "palette 25\n" << "autoscale off\n" << flush; while (true) { char axis; int tier, incr; cout << "Enter axis (x, y, z), tier index (1, 2, 3), " << "and rotation (0, 1, 2, 3) with no spaces: "; cin >> axis; if ( axis == 'x' || axis == 'y' || axis == 'z' ) { cin >> tier; incr = tier % 10; tier = tier / 10; if (tier >= 1 && tier <= 3) { anim_move(axis, tier, incr, mesh, color, sock); } else { cout << "tier index must be 1, 2, or 3." << endl; } } else if ( axis == 'r' ) { // Execute a sequence of random moves // Input the number of moves int num; cin >> num; Array moves(num); determine_random_moves(moves); for (int i=0; i> cw; twist_corners(mesh, color, sock, cw); } else if ( axis == 'e' ) { bool cw; cin >> cw; permute_edges(mesh, color, sock, cw); } else if ( axis == 'f' ) { int n = -1; cin >> n; if (n == 2 || n == 4) { flip_edges(mesh, color, sock, n); } else { cout << "Can only flip 2 or 4 edges at a time." << endl; } } else if ( axis == 'R' ) { repaint_cube(mesh, color, sock); } else if ( axis == 'T' ) { solve_top(mesh, color, sock); } else if ( axis == 'M' ) { solve_mid(mesh, color, sock); } else if ( axis == 'B' ) { solve_bot(mesh, color, sock); } else if ( axis == 's' || axis == 'S') { solve(mesh, color, sock); } else if ( axis == 'h' || axis == 'H') { interactive_help(); } else if ( axis == 'q' || axis == 'Q') { break; } else { cout << endl << "Unrecognized command. " "Enter 'x', 'y', 'z' followed by '1', '2', or '3' to proceed " "or enter 'q' to quit: "; } } } print_state(std::cout); // Clean up and exit return 0; } void interactive_help() { cout << "\nInteractive Commands\n" << " [xyz][1,2,3][0-3]\n" << "\tRotate the specified tier (first integer) of the cube\n" << "\tabout the given axis (initial character) in the clockwise\n" << "\tdirection (looking from the tip of the axis vector towards\n" << "\tthe origin) by so many increments (final integer).\n" << " r[0-9]+\n" << "\tInitiate a random sequence of moves. The integer\n" << "\tfollowing 'r' is the number of desired moves.\n" << " p\n" << "\tPrint the current state of the cube.\n" << " c\n" << "\tSwap the corners in the 0th and 1st positions.\n" << " t[0,1]\n" << "\tTwist the corners of the bottom tier in the clockwise '1'\n" << "\tor counter-clockwise '0' direction leaving the 3rd corner\n" << "\tunchanged.\n" << " e[0,1]\n" << "\tPermute the edges of the bottom tier in the clockwise '1'\n" << "\tor counter-clockwise '0' direction leaving the 3rd edge\n" << "\tunchanged.\n" << " f[2,4]\n" << "\tFlip the edges of the bottom tier while keeping them in\n" << "\tplace. The integer '2' indicates flipping the 0th and 2nd\n" << "\tedges while '4' indicates flipping all four edges.\n" << " R\n" << "\tResets (or Repaints) the cube to its original configuration.\n" << " T\n" << "\tSolve the top tier only.\n" << " M\n" << "\tSolve the middle tier only (assumes the top tier has already\n" << "\tbeen solved.)\n" << " B\n" << "\tSolve the bottom tier only (assumes the top two tiers have\n" << "\talready been solved.)\n" << " s or S\n" << "\tSolve the cube starting from the top tier and working down.\n" << " h or H\n" << "\tPrint this message.\n" << " q or Q\n" << "\tQuit\n\n"; } void init_hex_mesh(Mesh & mesh) { // Add vertices and hexahedra for 27 cubes double c[3]; int v[16]; int vh[8]; int l = 0; for (int k=0; k<3; k++) { for (int j=0; j<3; j++) { for (int i=0; i<3; i++) { c[0] = -1.5 + i; c[1] = -1.5 + j; c[2] = -1.5 + k; mesh.AddVertex(c); v[0] = l; l++; c[0] = -1.5 + i + 1; c[1] = -1.5 + j; c[2] = -1.5 + k; mesh.AddVertex(c); v[1] = l; l++; c[0] = -1.5 + i + 1; c[1] = -1.5 + j + 1; c[2] = -1.5 + k; mesh.AddVertex(c); v[2] = l; l++; c[0] = -1.5 + i; c[1] = -1.5 + j + 1; c[2] = -1.5 + k; mesh.AddVertex(c); v[3] = l; l++; c[0] = -1.5 + i; c[1] = -1.5 + j; c[2] = -1.5 + k + 1; mesh.AddVertex(c); v[4] = l; l++; c[0] = -1.5 + i + 1; c[1] = -1.5 + j; c[2] = -1.5 + k + 1; mesh.AddVertex(c); v[5] = l; l++; c[0] = -1.5 + i + 1; c[1] = -1.5 + j + 1; c[2] = -1.5 + k + 1; mesh.AddVertex(c); v[6] = l; l++; c[0] = -1.5 + i; c[1] = -1.5 + j + 1; c[2] = -1.5 + k + 1; mesh.AddVertex(c); v[7] = l; l++; c[0] = -1.5 + i + 0.25; c[1] = -1.5 + j + 0.25; c[2] = -1.5 + k + 0.25; mesh.AddVertex(c); v[8] = l; l++; c[0] = -1.5 + i + 0.75; c[1] = -1.5 + j + 0.25; c[2] = -1.5 + k + 0.25; mesh.AddVertex(c); v[9] = l; l++; c[0] = -1.5 + i + 0.75; c[1] = -1.5 + j + 0.75; c[2] = -1.5 + k + 0.25; mesh.AddVertex(c); v[10] = l; l++; c[0] = -1.5 + i + 0.25; c[1] = -1.5 + j + 0.75; c[2] = -1.5 + k + 0.25; mesh.AddVertex(c); v[11] = l; l++; c[0] = -1.5 + i + 0.25; c[1] = -1.5 + j + 0.25; c[2] = -1.5 + k + 0.75; mesh.AddVertex(c); v[12] = l; l++; c[0] = -1.5 + i + 0.75; c[1] = -1.5 + j + 0.25; c[2] = -1.5 + k + 0.75; mesh.AddVertex(c); v[13] = l; l++; c[0] = -1.5 + i + 0.75; c[1] = -1.5 + j + 0.75; c[2] = -1.5 + k + 0.75; mesh.AddVertex(c); v[14] = l; l++; c[0] = -1.5 + i + 0.25; c[1] = -1.5 + j + 0.75; c[2] = -1.5 + k + 0.75; mesh.AddVertex(c); v[15] = l; l++; // Bottom vh[0] = v[ 0]; vh[1] = v[ 1]; vh[2] = v[ 2]; vh[3] = v[ 3]; vh[4] = v[ 8]; vh[5] = v[ 9]; vh[6] = v[10]; vh[7] = v[11]; mesh.AddHex(vh, k==0 ? 6 : 1); // Top vh[0] = v[12]; vh[1] = v[13]; vh[2] = v[14]; vh[3] = v[15]; vh[4] = v[ 4]; vh[5] = v[ 5]; vh[6] = v[ 6]; vh[7] = v[ 7]; mesh.AddHex(vh, k==2 ? 7 : 1); // Front vh[0] = v[ 0]; vh[1] = v[ 4]; vh[2] = v[ 5]; vh[3] = v[ 1]; vh[4] = v[ 8]; vh[5] = v[12]; vh[6] = v[13]; vh[7] = v[ 9]; mesh.AddHex(vh, j==0 ? 4 : 1); // Back vh[0] = v[11]; vh[1] = v[15]; vh[2] = v[14]; vh[3] = v[10]; vh[4] = v[ 3]; vh[5] = v[ 7]; vh[6] = v[ 6]; vh[7] = v[ 2]; mesh.AddHex(vh, j==2 ? 5 : 1); // Left vh[0] = v[ 0]; vh[1] = v[ 3]; vh[2] = v[ 7]; vh[3] = v[ 4]; vh[4] = v[ 8]; vh[5] = v[11]; vh[6] = v[15]; vh[7] = v[12]; mesh.AddHex(vh, i==0 ? 3 : 1); // Right vh[0] = v[ 9]; vh[1] = v[10]; vh[2] = v[14]; vh[3] = v[13]; vh[4] = v[ 1]; vh[5] = v[ 2]; vh[6] = v[ 6]; vh[7] = v[ 5]; mesh.AddHex(vh, i==2 ? 2 : 1); } } } mesh.FinalizeTopology(); } void init_state() { for (int i=0; i<6; i++) { rubik.cent_[i] = i; } for (int i=0; i<24; i++) { rubik.edge_[i] = edge_colors_[i]; } for (int i=0; i<24; i++) { rubik.corn_[i] = corn_colors_[i]; } } void update_centers(char axis, int incr) { int i = (axis == 'x') ? 0 : ((axis == 'y') ? 1 : 2); int i0 = 0 + i * (i - 1) / 2; int i1 = 1 + i * (i + 1) / 2; int i3 = 3 - i * (3 * i - 5) / 2; int i5 = 5 - i * (i - 1); switch (incr) { case 1: std::swap(rubik.cent_[i3], rubik.cent_[i0]); std::swap(rubik.cent_[i5], rubik.cent_[i3]); std::swap(rubik.cent_[i1], rubik.cent_[i5]); break; case 2: std::swap(rubik.cent_[i0], rubik.cent_[i5]); std::swap(rubik.cent_[i1], rubik.cent_[i3]); break; case 3: std::swap(rubik.cent_[i1], rubik.cent_[i0]); std::swap(rubik.cent_[i5], rubik.cent_[i1]); std::swap(rubik.cent_[i3], rubik.cent_[i5]); break; } } void update_corners(char axis, int tier, int incr) { if (tier == 2) { return; } int i = (axis == 'x') ? 0 : ((axis == 'y') ? 1 : 2); if (tier == 1) { // 00:01:02 09:10:11 21:22:23 12:13:14 // 01:02:00 13:14:12 16:17:15 04:05:03 // 02:00:01 05:03:04 08:06:07 11:09:10 int i00 = i; int i09 = 9 - i * ( 6 * i - 10); int i21 = 21 - i * ( 3 * i + 7) / 2; int i12 = 12 + i * (15 * i - 31) / 2; int i01 = 1 - i * ( 3 * i - 5) / 2; int i10 = 10 - i * (15 * i - 23) / 2; int i22 = 22 - i * ( 3 * i + 2); int i13 = 13 + i * ( 6 * i - 14); int i02 = 2 + i * ( 3 * i - 7) / 2; int i11 = 11 - i * ( 9 * i - 11) / 2; int i23 = 23 - 8 * i; int i14 = 14 + i * ( 9 * i - 20); switch (incr) { case 1: // 0->12->21->9->0 std::swap(rubik.corn_[i09], rubik.corn_[i00]); std::swap(rubik.corn_[i21], rubik.corn_[i09]); std::swap(rubik.corn_[i12], rubik.corn_[i21]); // 1->14->22->11->1 std::swap(rubik.corn_[i11], rubik.corn_[i01]); std::swap(rubik.corn_[i22], rubik.corn_[i11]); std::swap(rubik.corn_[i14], rubik.corn_[i22]); // 2->13->23->10->2 std::swap(rubik.corn_[i10], rubik.corn_[i02]); std::swap(rubik.corn_[i23], rubik.corn_[i10]); std::swap(rubik.corn_[i13], rubik.corn_[i23]); break; case 2: // 0->21, 9->12, 1->22, 11->14, 2->23, 10->13 std::swap(rubik.corn_[i00], rubik.corn_[i21]); std::swap(rubik.corn_[i09], rubik.corn_[i12]); std::swap(rubik.corn_[i01], rubik.corn_[i22]); std::swap(rubik.corn_[i11], rubik.corn_[i14]); std::swap(rubik.corn_[i02], rubik.corn_[i23]); std::swap(rubik.corn_[i10], rubik.corn_[i13]); break; case 3: // 0->9->21->12->0 std::swap(rubik.corn_[i12], rubik.corn_[i00]); std::swap(rubik.corn_[i21], rubik.corn_[i12]); std::swap(rubik.corn_[i09], rubik.corn_[i21]); // 1->11->22->14->1 std::swap(rubik.corn_[i14], rubik.corn_[i01]); std::swap(rubik.corn_[i22], rubik.corn_[i14]); std::swap(rubik.corn_[i11], rubik.corn_[i22]); // 2->10->23->13->2 std::swap(rubik.corn_[i13], rubik.corn_[i02]); std::swap(rubik.corn_[i23], rubik.corn_[i13]); std::swap(rubik.corn_[i10], rubik.corn_[i23]); break; } } else { // 03:04:05 06:07:08 18:19:20 15:16:17 // 10:11:09 22:23:21 19:20:18 07:08:06 // 14:12:13 17:15:16 20:18:19 23:21:22 int i03 = 3 - i * ( 3 * i - 17) / 2; int i06 = 6 - i * (21 * i - 53) / 2; int i18 = 18 + i; int i15 = 15 + i * (12 * i - 20); int i04 = 4 - i * ( 3 * i - 10); int i07 = 7 - i * (12 * i - 28); int i19 = 19 - i * ( 3 * i - 5) / 2; int i16 = 16 + i * (21 * i - 37) / 2; int i05 = 5 + 4 * i; int i08 = 8 - i * ( 9 * i - 22); int i20 = 20 + i * ( 3 * i - 7) / 2; int i17 = 17 + i * (27 * i - 49) / 2; switch (incr) { case 1: // 3->15->18->6->3 std::swap(rubik.corn_[i06], rubik.corn_[i03]); std::swap(rubik.corn_[i18], rubik.corn_[i06]); std::swap(rubik.corn_[i15], rubik.corn_[i18]); // 4->17->19->8->4 std::swap(rubik.corn_[i08], rubik.corn_[i04]); std::swap(rubik.corn_[i19], rubik.corn_[i08]); std::swap(rubik.corn_[i17], rubik.corn_[i19]); // 5->16->20->7->5 std::swap(rubik.corn_[i07], rubik.corn_[i05]); std::swap(rubik.corn_[i20], rubik.corn_[i07]); std::swap(rubik.corn_[i16], rubik.corn_[i20]); break; case 2: // 3->18, 15->6, 4->19, 17->8, 5->20, 16->7 std::swap(rubik.corn_[i03], rubik.corn_[i18]); std::swap(rubik.corn_[i15], rubik.corn_[i06]); std::swap(rubik.corn_[i04], rubik.corn_[i19]); std::swap(rubik.corn_[i17], rubik.corn_[i08]); std::swap(rubik.corn_[i05], rubik.corn_[i20]); std::swap(rubik.corn_[i16], rubik.corn_[i07]); break; case 3: // 3->6->18->15->3 std::swap(rubik.corn_[i15], rubik.corn_[i03]); std::swap(rubik.corn_[i18], rubik.corn_[i15]); std::swap(rubik.corn_[i06], rubik.corn_[i18]); // 4->8->19->17->4 std::swap(rubik.corn_[i17], rubik.corn_[i04]); std::swap(rubik.corn_[i19], rubik.corn_[i17]); std::swap(rubik.corn_[i08], rubik.corn_[i19]); // 5->7->20->16->5 std::swap(rubik.corn_[i16], rubik.corn_[i05]); std::swap(rubik.corn_[i20], rubik.corn_[i16]); std::swap(rubik.corn_[i07], rubik.corn_[i20]); break; } } } void update_edges(char axis, int tier, int incr) { int i = (axis == 'x') ? 0 : ((axis == 'y') ? 1 : 2); if (tier == 1) { int i06 = 6 - i * (13 * i - 23); int i14 = 14 - i * ( 9 * i - 13); int i16 = 16 + i * (11 * i - 27); int i22 = 22 + i * ( 4 * i - 18); switch (incr) { case 1: // 6->17->15->22->6, 7->16->14->23->7 std::swap(rubik.edge_[i22], rubik.edge_[i06]); std::swap(rubik.edge_[i14+1], rubik.edge_[i22]); std::swap(rubik.edge_[i16+1], rubik.edge_[i14+1]); std::swap(rubik.edge_[i22+1], rubik.edge_[i06+1]); std::swap(rubik.edge_[i14], rubik.edge_[i22+1]); std::swap(rubik.edge_[i16], rubik.edge_[i14]); break; case 2: // 6->15, 7->14, 16->23, 17->22 std::swap(rubik.edge_[i06], rubik.edge_[i14+1]); std::swap(rubik.edge_[i06+1], rubik.edge_[i14]); std::swap(rubik.edge_[i16], rubik.edge_[i22+1]); std::swap(rubik.edge_[i16+1], rubik.edge_[i22]); break; case 3: // 6->22->15->17->6, 7->23->14->16->7 std::swap(rubik.edge_[i16+1], rubik.edge_[i06]); std::swap(rubik.edge_[i14+1], rubik.edge_[i16+1]); std::swap(rubik.edge_[i22], rubik.edge_[i14+1]); std::swap(rubik.edge_[i16], rubik.edge_[i06+1]); std::swap(rubik.edge_[i14], rubik.edge_[i16]); std::swap(rubik.edge_[i22+1], rubik.edge_[i14]); break; } } else if (tier == 2) { // 00:01 04:05 12:13 08:09 // 06:07 14:15 10:11 02:03 // 16:17 18:19 20:21 22:23 int i00 = 0 + i * ( 2 * i + 4); int i04 = 4 - i * ( 3 * i - 13); int i08 = 8 + i * (13 * i - 19); int i12 = 12 + i * ( 6 * i - 8); switch (incr) { case 1: // 0->8->12->4->0, 1->9->13->5->1 std::swap(rubik.edge_[i04], rubik.edge_[i00]); std::swap(rubik.edge_[i12], rubik.edge_[i04]); std::swap(rubik.edge_[i08], rubik.edge_[i12]); std::swap(rubik.edge_[i04+1], rubik.edge_[i00+1]); std::swap(rubik.edge_[i12+1], rubik.edge_[i04+1]); std::swap(rubik.edge_[i08+1], rubik.edge_[i12+1]); break; case 2: // 0->12, 1->13, 4->8, 5->9 std::swap(rubik.edge_[i00], rubik.edge_[i12]); std::swap(rubik.edge_[i00+1], rubik.edge_[i12+1]); std::swap(rubik.edge_[i04], rubik.edge_[i08]); std::swap(rubik.edge_[i04+1], rubik.edge_[i08+1]); break; case 3: // 0->4->12->8->0, 1->5->13->9->1 std::swap(rubik.edge_[i08], rubik.edge_[i00]); std::swap(rubik.edge_[i12], rubik.edge_[i08]); std::swap(rubik.edge_[i04], rubik.edge_[i12]); std::swap(rubik.edge_[i08+1], rubik.edge_[i00+1]); std::swap(rubik.edge_[i12+1], rubik.edge_[i08+1]); std::swap(rubik.edge_[i04+1], rubik.edge_[i12+1]); break; } } else { // 02:03 20:21 10:11 18:19 // 22:23 12:13 20:21 04:05 // 08:09 10:11 12:13 14:15 int i02 = 2 - i * (17 * i - 37); int i10 = 10 - i * ( 9 * i - 19); int i18 = 18 + i * (12 * i - 26); int i20 = 20 + i * ( 3 * i - 11); switch (incr) { case 1: // 2->19->11->20->2, 3->18->10->21->3 std::swap(rubik.edge_[i20], rubik.edge_[i02]); std::swap(rubik.edge_[i10+1], rubik.edge_[i20]); std::swap(rubik.edge_[i18+1], rubik.edge_[i10+1]); std::swap(rubik.edge_[i20+1], rubik.edge_[i02+1]); std::swap(rubik.edge_[i10], rubik.edge_[i20+1]); std::swap(rubik.edge_[i18], rubik.edge_[i10]); break; case 2: // 2->11, 19->20, 3->10, 18->21 std::swap(rubik.edge_[i02], rubik.edge_[i10+1]); std::swap(rubik.edge_[i02+1], rubik.edge_[i10]); std::swap(rubik.edge_[i18], rubik.edge_[i20+1]); std::swap(rubik.edge_[i18+1], rubik.edge_[i20]); break; case 3: // 2->20->11->19->2, 3->21->10->18->3 std::swap(rubik.edge_[i18+1], rubik.edge_[i02]); std::swap(rubik.edge_[i10+1], rubik.edge_[i18+1]); std::swap(rubik.edge_[i20], rubik.edge_[i10+1]); std::swap(rubik.edge_[i18], rubik.edge_[i02+1]); std::swap(rubik.edge_[i10], rubik.edge_[i18]); std::swap(rubik.edge_[i20+1], rubik.edge_[i10]); break; } } } void update_state(char axis, int tier, int incr) { if (incr == 0) { return; } // Centers only change if tier == 2 if (tier == 2) { update_centers(axis, incr); } else { // Corners only change if tier != 2 update_corners(axis, tier, incr); } // Edges always change update_edges(axis, tier, incr); } void print_state(ostream & out_stream) { out_stream << "Rubik's Cube State:\n"; out_stream << " Centers: "; for (int i=0; i<6; i++) { out_stream << " " << rubik.cent_[i]; } out_stream << "\n"; out_stream << " Edges: "; for (int i=0; i<12; i++) { out_stream << " " << rubik.edge_[2 * i + 0] << ":" << rubik.edge_[2 * i + 1]; } out_stream << "\n"; out_stream << " Corners: "; for (int i=0; i<8; i++) { out_stream << " " << rubik.corn_[3 * i + 0] << ":" << rubik.corn_[3 * i + 1] << ":" << rubik.corn_[3 * i + 2]; } out_stream << "\n"; } void repaint_cube(Mesh & mesh, GridFunction & color, socketstream & sock) { double xData[3]; Vector x(xData,3); double eps = 0.1; Array v; for (int i=0; i 1.5 - eps) { color[elem] = 1.0 / 6.0; } else if (x[0] < -1.5 + eps) { color[elem] = 2.0 / 6.0; } else if (x[1] < -1.5 + eps) { color[elem] = 3.0 / 6.0; } else if (x[1] > 1.5 - eps) { color[elem] = 4.0 / 6.0; } else if (x[2] < -1.5 + eps) { color[elem] = 5.0 / 6.0; } else if (x[2] > 1.5 - eps) { color[elem] = 1.0; } } sock << "solution\n" << mesh << color << flush; init_state(); } bool validate_centers(const int min_ind, const int max_ind) { MFEM_ASSERT(0 <= min_ind && max_ind <= 6, "Maximum center index of " << max_ind << " is out of range."); for (int i=min_ind; i verts; Array v; for (int i=0; i::iterator sit = verts.begin(); sit!=verts.end(); sit++) { rotate_step(axis, incr, mesh.GetVertex(*sit)); } step_++; return true; } void mark_elements(Mesh & mesh, char axis, int tier) { double xData[3]; Vector x(xData,3); Array v; for (int i=0; i -2.5 + tier && x[0] < -1.5 + tier ) { mesh.SetAttribute(i, 2); } else { mesh.SetAttribute(i, 1); } break; case 'y': if ( x[1] > -2.5 + tier && x[1] < -1.5 + tier ) { mesh.SetAttribute(i, 2); } else { mesh.SetAttribute(i, 1); } break; case 'z': if ( x[2] > -2.5 + tier && x[2] < -1.5 + tier ) { mesh.SetAttribute(i, 2); } else { mesh.SetAttribute(i, 1); } break; } } } void anim_move(char axis, int tier, int incr, Mesh & mesh, GridFunction & color, socketstream & sock) { update_state(axis, tier, incr); mark_elements(mesh, axis, tier); while (anim_step(axis, incr, mesh)) { sock << "solution\n" << mesh << color << flush; } count_++; } void determine_random_moves(Array & moves) { for (int i=0; i 1) { cout << "Entering solve_top_corners" << endl; } if (logging_ > 2) { print_state(cout); } // Locate first incorrectly filled corner location in the top tier int l4 = locate_corner(4); int i4 = l4 % 8; int o4 = l4 / 8; if (logging_ > 1) { cout << "Location of 4-th corner: " << i4 << " with orientation " << o4 << endl; } if (i4 >= 0) { move_to_c4(i4, o4, mesh, color, sock); } // Locate second incorrectly filled corner location in the top tier int l5 = locate_corner(5); int i5 = l5 % 8; int o5 = l5 / 8; if (logging_ > 1) { cout << "Location of 5-th corner: " << i5 << " with orientation " << o5 << endl; } if (i5 >= 0) { move_to_c5(i5, o5, mesh, color, sock); } // Locate third incorrectly filled corner location in the top tier int l6 = locate_corner(6); int i6 = l6 % 8; int o6 = l6 / 8; if (logging_ > 1) { cout << "Location of 6-th corner: " << i6 << " with orientation " << o6 << endl; } if (i6 >= 0) { move_to_c6(i6, o6, mesh, color, sock); } // Locate fourth incorrectly filled corner location in the top tier int l7 = locate_corner(7); int i7 = l7 % 8; int o7 = l7 / 8; if (logging_ > 1) { cout << "Location of 7-th corner: " << i7 << " with orientation " << o7 << endl; } if (i7 >= 0) { move_to_c7(i7, o7, mesh, color, sock); } } int locate_edge(int ind) { for (int i=0; i<12; i++) { if ((rubik.edge_[2 * i + 0] == edge_colors_[2 * ind + 0] && rubik.edge_[2 * i + 1] == edge_colors_[2 * ind + 1])) { return i; } if ((rubik.edge_[2 * i + 0] == edge_colors_[2 * ind + 1] && rubik.edge_[2 * i + 1] == edge_colors_[2 * ind + 0])) { return -i - 1; } } return -99; } void move_to_e4(int i4, int o4, Mesh & mesh, GridFunction & color, socketstream & sock) { if (o4 == 0) { switch (i4) { case 0: anim_move('y', 2, 1, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('y', 2, 3, mesh, color, sock); break; case 1: anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); break; case 2: anim_move('y', 3, 2, mesh, color, sock); anim_move('z', 3, 2, mesh, color, sock); break; case 3: anim_move('x', 1, 2, mesh, color, sock); anim_move('z', 3, 3, mesh, color, sock); break; case 5: anim_move('z', 3, 1, mesh, color, sock); break; case 6: anim_move('y', 2, 1, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); anim_move('y', 2, 3, mesh, color, sock); break; case 7: anim_move('y', 2, 3, mesh, color, sock); anim_move('z', 3, 1, mesh, color, sock); anim_move('y', 2, 1, mesh, color, sock); break; case 8: anim_move('y', 1, 3, mesh, color, sock); break; case 9: anim_move('z', 2, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); break; case 10: anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 3, 2, mesh, color, sock); break; case 11: anim_move('x', 1, 3, mesh, color, sock); anim_move('z', 3, 3, mesh, color, sock); break; } } else { switch (i4) { case 0: anim_move('y', 1, 2, mesh, color, sock); break; case 1: anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 2, mesh, color, sock); break; case 2: anim_move('x', 2, 3, mesh, color, sock); anim_move('z', 3, 1, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 3, 1, mesh, color, sock); break; case 3: anim_move('y', 2, 3, mesh, color, sock); anim_move('z', 3, 3, mesh, color, sock); anim_move('y', 2, 1, mesh, color, sock); break; case 4: anim_move('y', 1, 3, mesh, color, sock); anim_move('z', 2, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); break; case 5: anim_move('y', 2, 1, mesh, color, sock); anim_move('z', 3, 3, mesh, color, sock); anim_move('y', 2, 3, mesh, color, sock); break; case 6: anim_move('z', 3, 2, mesh, color, sock); break; case 7: anim_move('z', 3, 3, mesh, color, sock); break; case 8: anim_move('z', 2, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); break; case 9: anim_move('y', 1, 1, mesh, color, sock); break; case 10: anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 3, 1, mesh, color, sock); break; case 11: anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 3, 2, mesh, color, sock); break; } } } void move_to_e5(int i5, int o5, Mesh & mesh, GridFunction & color, socketstream & sock) { if (o5 == 0) { switch (i5) { case 0: anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); break; case 1: anim_move('x', 2, 3, mesh, color, sock); anim_move('y', 2, 1, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); break; case 2: anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 2, mesh, color, sock); break; case 3: anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 3, 2, mesh, color, sock); break; case 6: anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; case 7: anim_move('x', 2, 1, mesh, color, sock); anim_move('y', 2, 3, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); break; case 8: anim_move('z', 2, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); break; case 9: anim_move('x', 3, 1, mesh, color, sock); break; case 10: anim_move('z', 2, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); break; case 11: anim_move('y', 3, 2, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; } } else { switch (i5) { case 0: anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 2, mesh, color, sock); break; case 1: anim_move('x', 3, 2, mesh, color, sock); break; case 2: anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; case 3: anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); anim_move('y', 2, 1, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); break; case 5: anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 2, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); break; case 6: anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 3, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); break; case 7: anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 3, 2, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); break; case 8: anim_move('z', 2, 2, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; case 9: anim_move('z', 2, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; case 10: anim_move('x', 3, 3, mesh, color, sock); break; case 11: anim_move('z', 2, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; } } } void move_to_e6(int i6, int o6, Mesh & mesh, GridFunction & color, socketstream & sock) { if (o6 == 0) { switch (i6) { case 0: anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 3, 2, mesh, color, sock); break; case 1: anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 2, mesh, color, sock); break; case 2: anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 2, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 3: anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 7: anim_move('z', 3, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 8: anim_move('z', 2, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 9: anim_move('z', 2, 2, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 10: anim_move('z', 2, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 11: anim_move('y', 3, 3, mesh, color, sock); break; } } else { switch (i6) { case 0: anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 1: anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); break; case 2: anim_move('y', 3, 2, mesh, color, sock); break; case 3: anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 2, mesh, color, sock); break; case 6: anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 2, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; case 7: anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 8: anim_move('z', 2, 2, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; case 9: anim_move('z', 2, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; case 10: anim_move('y', 3, 1, mesh, color, sock); break; case 11: anim_move('z', 2, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; } } } void move_to_e7(int i7, int o7, Mesh & mesh, GridFunction & color, socketstream & sock) { if (o7 == 0) { switch (i7) { case 0: anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 1, 2, mesh, color, sock); break; case 1: anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 1, 2, mesh, color, sock); break; case 2: anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; case 3: anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 2, 1, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); break; case 8: anim_move('x', 1, 1, mesh, color, sock); break; case 9: anim_move('z', 2, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 10: anim_move('z', 2, 2, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 11: anim_move('z', 2, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; } } else { switch (i7) { case 0: anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); break; case 1: anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; case 2: anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 2, mesh, color, sock); break; case 3: anim_move('x', 1, 2, mesh, color, sock); break; case 7: anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 2, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 8: anim_move('z', 2, 1, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); break; case 9: anim_move('z', 2, 2, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); break; case 10: anim_move('z', 2, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); break; case 11: anim_move('x', 1, 3, mesh, color, sock); break; } } } void move_to_e8(int i8, int o8, Mesh & mesh, GridFunction & color, socketstream & sock) { if (o8 == 0) { switch (i8) { case 0: // Verified anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); break; case 1: // Verified anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); break; case 2: // Verified anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); break; case 3: // Verified anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); break; case 9: // Verified anim_move('x', 3, 3, mesh, color, sock); permute_edges(mesh, color, sock, false); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); permute_edges(mesh, color, sock, true); anim_move('y', 1, 3, mesh, color, sock); break; case 10: // Verified anim_move('z', 2, 1, mesh, color, sock); anim_move('y', 1, 2, mesh, color, sock); anim_move('z', 2, 3, mesh, color, sock); anim_move('y', 1, 2, mesh, color, sock); break; case 11: // Verified anim_move('y', 3, 1, mesh, color, sock); permute_edges(mesh, color, sock, true); anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); permute_edges(mesh, color, sock, false); anim_move('y', 1, 3, mesh, color, sock); break; } } else { switch (i8) { case 0: // Verified anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); break; case 1: // Verified anim_move('x', 1, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); break; case 2: // Verified anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); break; case 3: // Verified anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); break; case 8: // Verified anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); break; case 9: // Verified anim_move('y', 1, 2, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 1, 2, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 1, 2, mesh, color, sock); break; case 10: // Verified anim_move('y', 3, 3, mesh, color, sock); permute_edges(mesh, color, sock, false); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); permute_edges(mesh, color, sock, true); anim_move('y', 1, 3, mesh, color, sock); break; case 11: // Verified anim_move('z', 2, 1, mesh, color, sock); anim_move('x', 1, 2, mesh, color, sock); anim_move('z', 2, 3, mesh, color, sock); anim_move('x', 1, 2, mesh, color, sock); break; } } } void move_to_e9(int i9, int o9, Mesh & mesh, GridFunction & color, socketstream & sock) { if (o9 == 0) { switch (i9) { case 0: // Verified anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; case 1: // Verified anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; case 2: // Verified anim_move('y', 1, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); break; case 3: // Verified anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); break; case 10: // Verified anim_move('y', 3, 3, mesh, color, sock); permute_edges(mesh, color, sock, true); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); permute_edges(mesh, color, sock, false); anim_move('y', 1, 1, mesh, color, sock); break; case 11: // Verified anim_move('z', 2, 1, mesh, color, sock); anim_move('x', 3, 2, mesh, color, sock); anim_move('z', 2, 3, mesh, color, sock); anim_move('x', 3, 2, mesh, color, sock); break; } } else { switch (i9) { case 0: // Verified anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); break; case 1: // Verified anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); break; case 2: // Verified anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; case 3: // Verified anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; case 9: // Verified anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); break; case 10: // Verified anim_move('x', 3, 2, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 3, 2, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 3, 2, mesh, color, sock); break; case 11: // Verified anim_move('y', 3, 1, mesh, color, sock); permute_edges(mesh, color, sock, true); anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); permute_edges(mesh, color, sock, false); anim_move('y', 1, 1, mesh, color, sock); break; } } } void move_to_e10(int i10, int o10, Mesh & mesh, GridFunction & color, socketstream & sock) { if (o10 == 0) { switch (i10) { case 0: // Verified anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 1: // Verified anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 2: // Verified anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); break; case 3: // Verified anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); break; case 11: // Verified anim_move('y', 3, 1, mesh, color, sock); permute_edges(mesh, color, sock, true); anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); permute_edges(mesh, color, sock, true); anim_move('y', 3, 1, mesh, color, sock); break; } } else { switch (i10) { case 0: // Verified anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); break; case 1: // Verified anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); break; case 2: // Verified anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 3: // Verified anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 10: // Verified anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); break; case 11: // Verified anim_move('y', 3, 2, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 3, 2, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 3, 2, mesh, color, sock); break; } } } void move_to_e11(int i11, int o11, Mesh & mesh, GridFunction & color, socketstream & sock) { if (o11 == 0) { switch (i11) { case 0: // Verified anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 1: // Verified anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 2: // Verified anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; case 3: // Verified anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; } } else { switch (i11) { case 0: // Verified anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; case 1: // Verified anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); break; case 2: // Verified anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 3: // Verified anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 11: // Verified anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; } } } void solve_top_edges(Mesh & mesh, GridFunction & color, socketstream & sock) { if (logging_ > 1) { cout << "Entering solve_top_edges" << endl; } if (logging_ > 2) { print_state(cout); } // Locate fourth edge in the top tier { int l4 = locate_edge(4); int i4 = max(l4,-1-l4); int o4 = (l4 >= 0) ? 0 : 1; if (logging_ > 1) { cout << "Location of 4-th edge: " << i4 << " with orientation " << o4 << endl; } if (i4 < 12 && ((i4 < 4) || (i4 > 4 && o4 == 0) || (o4 == 1) )) { move_to_e4(i4, o4, mesh, color, sock); } } // Locate fifth edge in the top tier { int l5 = locate_edge(5); int i5 = max(l5,-1-l5); int o5 = (l5 >= 0) ? 0 : 1; if (logging_ > 1) { cout << "Location of 5-th edge: " << i5 << " with orientation " << o5 << endl; } if (i5 < 12 && ((i5 < 4) || (i5 > 5 && o5 == 0) || (i5 > 4 && o5 == 1) )) { move_to_e5(i5, o5, mesh, color, sock); } } // Locate sixth edge in the top tier { int l6 = locate_edge(6); int i6 = max(l6,-1-l6); int o6 = (l6 >= 0) ? 0 : 1; if (logging_ > 1) { cout << "Location of 6-th edge: " << i6 << " with orientation " << o6 << endl; } if (i6 < 12 && ((i6 < 4) || (i6 > 6 && o6 == 0) || (i6 > 5 && o6 == 1) )) { move_to_e6(i6, o6, mesh, color, sock); } } // Locate seventh edge in the top tier { int l7 = locate_edge(7); int i7 = max(l7,-1-l7); int o7 = (l7 >= 0) ? 0 : 1; if (logging_ > 1) { cout << "Location of 7-th edge: " << i7 << " with orientation " << o7 << endl; } if (i7 < 12 && ((i7 < 4) || (i7 > 7 && o7 == 0) || (i7 > 6 && o7 == 1) )) { move_to_e7(i7, o7, mesh, color, sock); } } } void solve_mid_edges(Mesh & mesh, GridFunction & color, socketstream & sock) { if (logging_ > 1) { cout << "Entering solve_mid_edges" << endl; } if (logging_ > 2) { print_state(cout); } // Locate eighth edge { int l8 = locate_edge(8); int i8 = max(l8,-1-l8); int o8 = (l8 >= 0) ? 0 : 1; if (logging_ > 1) { cout << "Location of 8-th edge: " << i8 << " with orientation " << o8 << endl; } if (i8 >= 4 && i8 < 8) { cout << "Moving edges from top tier to middle tier is not supported." << endl; } else if (i8 < 12 && ((i8 < 4) || (i8 > 8 && o8 == 0) || (i8 > 7 && o8 == 1) )) { move_to_e8(i8, o8, mesh, color, sock); } } // Locate ninth edge { int l9 = locate_edge(9); int i9 = max(l9,-1-l9); int o9 = (l9 >= 0) ? 0 : 1; if (logging_ > 1) { cout << "Location of 9-th edge: " << i9 << " with orientation " << o9 << endl; } if (i9 >= 4 && i9 < 8) { cout << "Moving edges from top tier to middle tier is not supported." << endl; } else if (i9 < 12 && ((i9 < 4) || (i9 > 9 && o9 == 0) || (i9 > 8 && o9 == 1) )) { move_to_e9(i9, o9, mesh, color, sock); } } // Locate tenth edge { int l10 = locate_edge(10); int i10 = max(l10,-1-l10); int o10 = (l10 >= 0) ? 0 : 1; if (logging_ > 1) { cout << "Location of 10-th edge: " << i10 << " with orientation " << o10 << endl; } if (i10 >= 4 && i10 < 8) { cout << "Moving edges from top tier to middle tier is not supported." << endl; } else if (i10 < 12 && ((i10 < 4) || (i10 > 10 && o10 == 0) || (i10 > 9 && o10 == 1) )) { move_to_e10(i10, o10, mesh, color, sock); } } // Locate eleventh edge { int l11 = locate_edge(11); int i11 = max(l11,-1-l11); int o11 = (l11 >= 0) ? 0 : 1; if (logging_ > 1) { cout << "Location of 11-th edge: " << i11 << " with orientation " << o11 << endl; } if (i11 >= 4 && i11 < 8) { cout << "Moving edges from top tier to middle tier is not supported." << endl; } else if (i11 < 12 && ((i11 < 4) || (i11 > 11 && o11 == 0) || (i11 > 10 && o11 == 1) )) { move_to_e11(i11, o11, mesh, color, sock); } } } void swap_corners(Mesh & mesh, GridFunction & color, socketstream & sock, int * c0, int * c1) { if (logging_ > 1) { cout << "Entering swap_corners" << endl; } if (c0 != NULL) { // Locate first incorrectly filled corner location int i0 = -1; for (int i=0; i<8; i++) { if ((rubik.corn_[3 * i] == c0[0] && rubik.corn_[3 * i + 1] == c0[1] && rubik.corn_[3 * i + 2] == c0[2]) || (rubik.corn_[3 * i] == c0[1] && rubik.corn_[3 * i + 1] == c0[2] && rubik.corn_[3 * i + 2] == c0[0]) || (rubik.corn_[3 * i] == c0[2] && rubik.corn_[3 * i + 1] == c0[0] && rubik.corn_[3 * i + 2] == c0[1]) || (rubik.corn_[3 * i] == c0[2] && rubik.corn_[3 * i + 1] == c0[1] && rubik.corn_[3 * i + 2] == c0[0]) || (rubik.corn_[3 * i] == c0[1] && rubik.corn_[3 * i + 1] == c0[0] && rubik.corn_[3 * i + 2] == c0[2]) || (rubik.corn_[3 * i] == c0[0] && rubik.corn_[3 * i + 1] == c0[2] && rubik.corn_[3 * i + 2] == c0[1])) { i0 = i; break; } } if (logging_ > 1) { cout << "Location of c0 = {"< 1) { cout << "Location of piece belonging at " << 0 << " (c1) is " << i1 << endl; } switch (i1) { case 1: swap_corners(mesh, color, sock, NULL, NULL); break; case 2: anim_move('x', 3, 1, mesh, color, sock); swap_corners(mesh, color, sock, NULL, NULL); anim_move('x', 3, 3, mesh, color, sock); break; case 3: anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); swap_corners(mesh, color, sock, NULL, NULL); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 4: anim_move('z', 3, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); swap_corners(mesh, color, sock, NULL, NULL); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 3, 1, mesh, color, sock); break; case 5: anim_move('x', 3, 3, mesh, color, sock); swap_corners(mesh, color, sock, NULL, NULL); anim_move('x', 3, 1, mesh, color, sock); break; case 6: anim_move('x', 3, 2, mesh, color, sock); swap_corners(mesh, color, sock, NULL, NULL); anim_move('x', 3, 2, mesh, color, sock); break; case 7: anim_move('z', 3, 2, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); swap_corners(mesh, color, sock, NULL, NULL); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 3, 2, mesh, color, sock); break; } } else { anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); } } void solve_corner_locations(Mesh & mesh, GridFunction & color, socketstream & sock) { if (logging_ > 1) { cout << "Entering solve_corner_locations" << endl; } if (logging_ > 2) { print_state(cout); } // Locate first incorrectly filled corner location int i0 = -1; for (int i=0; i<8; i++) { if (!((rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 0] && rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 1] && rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 2]) || (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 1] && rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 2] && rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 0]) || (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 2] && rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 0] && rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 1]) || (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 2] && rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 1] && rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 0]) || (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 1] && rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 0] && rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 2]) || (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 0] && rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 2] && rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 1]))) { i0 = i; break; } } if (logging_ > 1) { cout << "First incorrectly filled corner location: " << i0 << endl; } if (i0 < 0) { return; } // Locate corner piece which belongs at i0 int l1 = locate_corner(i0); int i1 = l1 % 8; if (logging_ > 1) { cout << "Location of piece belonging at " << i0 << " is " << i1 << endl; } if (i1 < 0) { cout << "Invalid configuration of corners" << endl; return; } int c0[3] = {rubik.corn_[3 * i0], rubik.corn_[3 * i0 + 1], rubik.corn_[3 * i0 + 2] }; int c1[3] = {rubik.corn_[3 * i1], rubik.corn_[3 * i1 + 1], rubik.corn_[3 * i1 + 2] }; swap_corners(mesh, color, sock, c0, c1); solve_corner_locations(mesh, color, sock); } void solve_bot_corner_locations(Mesh & mesh, GridFunction & color, socketstream & sock) { if (logging_ > 1) { cout << "Entering solve_bot_corner_locations" << endl; } if (logging_ > 2) { print_state(cout); } // Locate first corner in the bottom tier { int l0 = locate_corner(0); int i0 = l0 % 8; if (logging_ > 1) { cout << "Location of piece belonging at 0 is " << i0 << endl; } if (i0 != 0) { anim_move('z', 1, i0, mesh, color, sock); } } // Locate second corner in bottom tier { int l1 = locate_corner(1); int i1 = l1 % 8; if (logging_ > 1) { cout << "Location of piece belonging at 1 is " << i1 << endl; } if (i1 < 0) { cout << "Invalid configuration of corners" << endl; } switch (i1) { case 2: anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); break; case 3: anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); break; } } // Locate second corner in bottom tier { int l2 = locate_corner(2); int i2 = l2 % 8; if (logging_ > 1) { cout << "Location of piece belonging at 2 is " << i2 << endl; } if (i2 < 0) { cout << "Invalid configuration of corners" << endl; } if (i2 == 3) { anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); } } } void twist_corners(Mesh & mesh, GridFunction & color, socketstream & sock, bool cw, int * c0, int * c1, int * c2) { if (c0 != NULL) { // Locate corner corresponding to c0 int i0 = -1; for (int i=0; i<8; i++) { if ((rubik.corn_[3 * i] == c0[0] && rubik.corn_[3 * i + 1] == c0[1] && rubik.corn_[3 * i + 2] == c0[2]) || (rubik.corn_[3 * i] == c0[1] && rubik.corn_[3 * i + 1] == c0[2] && rubik.corn_[3 * i + 2] == c0[0]) || (rubik.corn_[3 * i] == c0[2] && rubik.corn_[3 * i + 1] == c0[0] && rubik.corn_[3 * i + 2] == c0[1]) || (rubik.corn_[3 * i] == c0[2] && rubik.corn_[3 * i + 1] == c0[1] && rubik.corn_[3 * i + 2] == c0[0]) || (rubik.corn_[3 * i] == c0[1] && rubik.corn_[3 * i + 1] == c0[0] && rubik.corn_[3 * i + 2] == c0[2]) || (rubik.corn_[3 * i] == c0[0] && rubik.corn_[3 * i + 1] == c0[2] && rubik.corn_[3 * i + 2] == c0[1])) { i0 = i; break; } } if (logging_ > 1) { cout << "Location of c0 = {"< 1) { cout << "Location of c1 = {"< 1) { cout << "Location of c2 = {"< 1) { cout << "twist_corners performing clockwise twist" << endl; } anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); } else { if (logging_ > 1) { cout << "twist_corners performing counter-clockwise twist" << endl; } anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); } } } void solve_corner_orientations(Mesh & mesh, GridFunction & color, socketstream & sock) { if (logging_ > 1) { cout << "Entering solve_corner_orientations" << endl; } if (logging_ > 2) { print_state(cout); } // Locate first incorrectly oriented corner int i0 = -1; bool cw = true; for (int i=0; i<8; i++) { if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0]) { i0 = i; switch (i0) { case 0: case 2: case 5: case 7: cw = rubik.corn_[3 * i0 + 0] == corn_colors_[3 * i0 + 1]; break; case 1: case 3: case 4: case 6: cw = rubik.corn_[3 * i0 + 0] == corn_colors_[3 * i0 + 2]; break; } break; } } if (i0 < 0) { return; } if (logging_ > 1) { cout << "First incorrectly oriented corner: " << i0 << endl; } // Locate second incorrectly oriented corner int i1 = -1; for (int i=i0+1; i<8; i++) { if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0]) { i1 = i; break; } } if (logging_ > 1) { cout << "Second incorrectly oriented corner: " << i1 << endl; } // Locate third incorrectly oriented corner (if such exists) int i2 = -1; // int i3 = -1; for (int i=i1+1; i<8; i++) { if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0]) { i2 = i; break; } } if (i2 > 0) { if (logging_ > 1) { cout << "Third incorrectly oriented corner: " << i2 << endl; } // Three incorrectly oriented corners were found int c0[3] = {rubik.corn_[3 * i0], rubik.corn_[3 * i0 + 1], rubik.corn_[3 * i0 + 2] }; int c1[3] = {rubik.corn_[3 * i1], rubik.corn_[3 * i1 + 1], rubik.corn_[3 * i1 + 2] }; int c2[3] = {rubik.corn_[3 * i2], rubik.corn_[3 * i2 + 1], rubik.corn_[3 * i2 + 2] }; twist_corners(mesh, color, sock, cw, c0, c1, c2); } else { // Two incorrectly oriented corners were found int c0[3] = {rubik.corn_[3 * i0], rubik.corn_[3 * i0 + 1], rubik.corn_[3 * i0 + 2] }; int c1[3] = {rubik.corn_[3 * i1], rubik.corn_[3 * i1 + 1], rubik.corn_[3 * i1 + 2] }; twist_corners(mesh, color, sock, cw, c0, c1); } solve_corner_orientations(mesh, color, sock); } void permute_edges(Mesh & mesh, GridFunction & color, socketstream & sock, int * e0, int * e1, int * e2) { if (logging_ > 1) { cout << "Entering permute_edges" << endl; } if (e0 != NULL) { // Locate first incorrectly filled edge location int i0 = -1; for (int i=0; i<12; i++) { if ((rubik.edge_[2 * i] == e0[0] && rubik.edge_[2 * i + 1] == e0[1]) || (rubik.edge_[2 * i] == e0[1] && rubik.edge_[2 * i + 1] == e0[0])) { i0 = i; break; } } if (logging_ > 1) { cout << "Location of e0 = {"< 1) { cout << "Location of piece belonging at " << 0 << " (e1) is " << i1 << endl; } switch (i1) { case 1: permute_edges(mesh, color, sock, NULL, NULL, e2); break; case 2: case 3: anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, i1-1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); permute_edges(mesh, color, sock, NULL, NULL, e2); anim_move('y', 1, 1, mesh, color, sock); anim_move('z', 1, 5-i1, mesh, color, sock); anim_move('y', 1, 3, mesh, color, sock); break; case 4: case 5: case 6: case 7: anim_move('z', 3, (i1-1)%4, mesh, color, sock); anim_move('x', 3, 2, mesh, color, sock); permute_edges(mesh, color, sock, NULL, NULL, e2); anim_move('x', 3, 2, mesh, color, sock); anim_move('z', 3, (9-i1)%4, mesh, color, sock); break; case 8: case 9: case 10: case 11: anim_move('z', 2, (i1-5)%4, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); permute_edges(mesh, color, sock, NULL, NULL, e2); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 2, (13-i1)%4, mesh, color, sock); break; } } else if (e2 != NULL) { // Locate a third incorrect edge int i2 = -1; for (int i=2; i<12; i++) { if ((rubik.edge_[2 * i] == e2[0] && rubik.edge_[2 * i + 1] == e2[1]) || (rubik.edge_[2 * i] == e2[1] && rubik.edge_[2 * i + 1] == e2[0])) { i2 = i; break; } } if (logging_ > 1) { cout << "Location of e2: " << i2 << endl; } switch (i2) { case 2: permute_edges(mesh, color, sock, NULL, NULL, NULL); break; case 3: anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); permute_edges(mesh, color, sock, NULL, NULL, NULL); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 4: case 5: case 6: case 7: anim_move('z', 3, (i2-2)%4, mesh, color, sock); anim_move('y', 3, 2, mesh, color, sock); permute_edges(mesh, color, sock, NULL, NULL, NULL); anim_move('y', 3, 2, mesh, color, sock); anim_move('z', 3, (10-i2)%4, mesh, color, sock); break; case 8: case 9: case 10: case 11: anim_move('z', 2, (i2-6)%4, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); permute_edges(mesh, color, sock, NULL, NULL, NULL); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 2, (14-i2)%4, mesh, color, sock); break; } } else { permute_edges(mesh, color, sock, true); } } void permute_edges(Mesh & mesh, GridFunction & color, socketstream & sock, bool cw) { if (cw) { anim_move('y', 2, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 2, 3, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 2, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); anim_move('y', 2, 3, mesh, color, sock); } else { anim_move('y', 2, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 2, 3, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('y', 2, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('y', 2, 3, mesh, color, sock); } } void solve_edge_locations(Mesh & mesh, GridFunction & color, socketstream & sock) { if (logging_ > 1) { cout << "Entering solve_edge_locations" << endl; } if (logging_ > 2) { print_state(cout); } // Locate first incorrectly filled edge location int i0 = -1; for (int i=0; i<12; i++) { if (!((rubik.edge_[2 * i] == edge_colors_[2 * i] && rubik.edge_[2 * i + 1] == edge_colors_[2 * i + 1]) || (rubik.edge_[2 * i] == edge_colors_[2 * i + 1] && rubik.edge_[2 * i + 1] == edge_colors_[2 * i]))) { i0 = i; break; } } if (logging_ > 1) { cout << "First incorrectly filled edge location: " << i0 << endl; } if (i0 < 0) { return; } // Locate edge piece which belongs at e0 int i1 = locate_edge(i0); if (i1 < 0 ) { i1 = -1 - i1; } if (logging_ > 1) { cout << "Location of piece belonging at " << i0 << " is " << i1 << endl; } // Locate a third incorrect edge int i2 = -1; for (int i=i0+1; i<12; i++) { if (i == i1) { continue; } if (!((rubik.edge_[2 * i + 0] == edge_colors_[2 * i + 0] && rubik.edge_[2 * i + 1] == edge_colors_[2 * i + 1]) || (rubik.edge_[2 * i + 0] == edge_colors_[2 * i + 1] && rubik.edge_[2 * i + 1] == edge_colors_[2 * i + 0]))) { i2 = i; break; } } if (logging_ > 1) { cout << "Another incorrectly filled edge location: " << i2 << endl; } if (i1 < 0 || i2 <0) { cout << "Invalid configuration of edges" << endl; return; } int e0[2] = {rubik.edge_[2 * i0], rubik.edge_[2 * i0 + 1]}; int e1[2] = {rubik.edge_[2 * i1], rubik.edge_[2 * i1 + 1]}; int e2[2] = {rubik.edge_[2 * i2], rubik.edge_[2 * i2 + 1]}; permute_edges(mesh, color, sock, e0, e1, e2); solve_edge_locations(mesh, color, sock); } void flip_edges(Mesh & mesh, GridFunction & color, socketstream & sock, int n, int * e0, int * e1, int * e2, int * e3) { if (n == 2) { if (e0 != NULL) { // Locate first incorrectly oriented edge int i0 = -1; for (int i=0; i<12; i++) { if ((rubik.edge_[2 * i] == e0[0] && rubik.edge_[2 * i + 1] == e0[1]) || (rubik.edge_[2 * i] == e0[1] && rubik.edge_[2 * i + 1] == e0[0])) { i0 = i; break; } } if (logging_ > 1) { cout << "Location of e0 = {"< 1) { cout << "Location of e1: " << i1 << endl; } switch (i1) { case 1: anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); flip_edges(mesh, color, sock, 2, NULL, NULL); anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); break; case 2: flip_edges(mesh, color, sock, 2, NULL, NULL); break; case 3: anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); flip_edges(mesh, color, sock, 2, NULL, NULL); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 4: case 5: case 6: case 7: anim_move('z', 3, (i1-2)%4, mesh, color, sock); anim_move('y', 3, 2, mesh, color, sock); flip_edges(mesh, color, sock, 2, NULL, NULL); anim_move('y', 3, 2, mesh, color, sock); anim_move('z', 3, (10-i1)%4, mesh, color, sock); break; case 8: case 9: case 10: case 11: anim_move('z', 2, (i1-6)%4, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); flip_edges(mesh, color, sock, 2, NULL, NULL); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 2, (14-i1)%4, mesh, color, sock); break; } } else { anim_move('x', 2, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); } } else if (n == 4) { if (e0 != NULL) { // Locate first incorrectly oriented edge int i0 = -1; for (int i=0; i<12; i++) { if ((rubik.edge_[2 * i] == e0[0] && rubik.edge_[2 * i + 1] == e0[1]) || (rubik.edge_[2 * i] == e0[1] && rubik.edge_[2 * i + 1] == e0[0])) { i0 = i; break; } } if (logging_ > 1) { cout << "Location of e0 = {"< 1) { cout << "Location of e1: " << i1 << endl; } switch (i1) { case 1: flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3); break; case 2: anim_move('y', 3, 1, mesh, color, sock); anim_move('x', 3, 1, mesh, color, sock); flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3); anim_move('x', 3, 3, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); break; case 3: anim_move('y', 2, 1, mesh, color, sock); flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3); anim_move('y', 2, 3, mesh, color, sock); break; case 4: case 5: case 6: case 7: anim_move('z', 3, (i1-1)%4, mesh, color, sock); anim_move('x', 3, 2, mesh, color, sock); flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3); anim_move('x', 3, 2, mesh, color, sock); anim_move('z', 3, (9-i1)%4, mesh, color, sock); break; case 8: case 9: case 10: case 11: anim_move('z', 2, (i1-5)%4, mesh, color, sock); anim_move('x', 3, 3, mesh, color, sock); flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3); anim_move('x', 3, 1, mesh, color, sock); anim_move('z', 2, (13-i1)%4, mesh, color, sock); break; } } else if (e2 != NULL) { // Locate third incorrectly oriented edge int i2 = -1; for (int i=2; i<12; i++) { if ((rubik.edge_[2 * i] == e2[0] && rubik.edge_[2 * i + 1] == e2[1]) || (rubik.edge_[2 * i] == e2[1] && rubik.edge_[2 * i + 1] == e2[0])) { i2 = i; break; } } if (logging_ > 1) { cout << "Location of e2: " << i2 << endl; } switch (i2) { case 2: flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3); break; case 3: anim_move('x', 1, 3, mesh, color, sock); anim_move('y', 3, 1, mesh, color, sock); flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3); anim_move('y', 3, 3, mesh, color, sock); anim_move('x', 1, 1, mesh, color, sock); break; case 4: case 5: case 6: case 7: anim_move('z', 3, (i2-2)%4, mesh, color, sock); anim_move('y', 3, 2, mesh, color, sock); flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3); anim_move('y', 3, 2, mesh, color, sock); anim_move('z', 3, (10-i2)%4, mesh, color, sock); break; case 8: case 9: case 10: case 11: anim_move('z', 2, (i2-6)%4, mesh, color, sock); anim_move('y', 3, 3, mesh, color, sock); flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3); anim_move('y', 3, 1, mesh, color, sock); anim_move('z', 2, (14-i2)%4, mesh, color, sock); break; } } else if (e3 != NULL) { // Locate fourth incorrectly oriented edge int i3 = -1; for (int i=3; i<12; i++) { if ((rubik.edge_[2 * i] == e3[0] && rubik.edge_[2 * i + 1] == e3[1]) || (rubik.edge_[2 * i] == e3[1] && rubik.edge_[2 * i + 1] == e3[0])) { i3 = i; break; } } if (logging_ > 1) { cout << "Location of e3: " << i3 << endl; } switch (i3) { case 3: flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, NULL); break; case 4: case 5: case 6: case 7: anim_move('z', 3, (i3-3)%4, mesh, color, sock); anim_move('x', 1, 2, mesh, color, sock); flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, NULL); anim_move('x', 1, 2, mesh, color, sock); anim_move('z', 3, (7-i3)%4, mesh, color, sock); break; case 8: case 9: case 10: case 11: anim_move('z', 2, (i3-4)%4, mesh, color, sock); anim_move('x', 1, 3, mesh, color, sock); flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, NULL); anim_move('x', 1, 1, mesh, color, sock); anim_move('z', 2, (12-i3)%4, mesh, color, sock); break; } } else { anim_move('x', 2, 3, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); anim_move('z', 1, 3, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 2, 3, mesh, color, sock); anim_move('z', 1, 2, mesh, color, sock); anim_move('x', 2, 1, mesh, color, sock); anim_move('z', 1, 1, mesh, color, sock); } } } void solve_edge_orientations(Mesh & mesh, GridFunction & color, socketstream & sock) { if (logging_ > 1) { cout << "Entering solve_edge_orientations" << endl; } if (logging_ > 2) { print_state(cout); } // Locate first incorrectly oriented edge int i0 = -1; for (int i=0; i<12; i++) { if (rubik.edge_[2 * i] != edge_colors_[2 * i]) { i0 = i; break; } } if (logging_ > 1) { cout << "First incorrectly oriented edge location: " << i0 << endl; } if (i0 < 0) { return; } // Locate second incorrectly oriented edge int i1 = -1; for (int i=i0+1; i<12; i++) { if (rubik.edge_[2 * i] != edge_colors_[2 * i]) { i1 = i; break; } } if (logging_ > 1) { cout << "Second incorrectly oriented edge location: " << i1 << endl; } // Locate third incorrectly oriented edge (if such exists) int i2 = -1; int i3 = -1; for (int i=i1+1; i<12; i++) { if (rubik.edge_[2 * i] != edge_colors_[2 * i]) { i2 = i; break; } } if (i2 > 0) { if (logging_ > 1) { cout << "Third incorrectly oriented edge location: " << i2 << endl; } // Locate fourth incorrectly oriented edge (if such exists) for (int i=i2+1; i<12; i++) { if (rubik.edge_[2 * i] != edge_colors_[2 * i]) { i3 = i; break; } } if (logging_ > 1) { cout << "Fourth incorrectly oriented edge location: " << i3 << endl; } } int e0[2] = {rubik.edge_[2 * i0], rubik.edge_[2 * i0 + 1]}; int e1[2] = {rubik.edge_[2 * i1], rubik.edge_[2 * i1 + 1]}; int e2[2] = {rubik.edge_[2 * max(i2,0)], rubik.edge_[2 * max(i2,0) + 1]}; int e3[2] = {rubik.edge_[2 * max(i3,0)], rubik.edge_[2 * max(i3,0) + 1]}; if (i2 == -1) { flip_edges(mesh, color, sock, 2, e0, e1); } else { flip_edges(mesh, color, sock, 4, e0, e1, e2, e3); } solve_edge_orientations(mesh, color, sock); } void solve_top(Mesh & mesh, GridFunction & color, socketstream & sock) { count_ = 0; if (logging_ > 0) { cout << "Solving top center block..." << endl; } solve_top_center(mesh, color, sock); if (logging_ > 0) { cout << "Solving top tier edges..." << endl; } solve_top_edges(mesh, color, sock); if (logging_ > 0) { cout << "Solving center blocks..." << endl; } if (logging_ > 0) { cout << "Solving top tier corners..." << endl; } solve_top_corners(mesh, color, sock); cout << "Move count: " << count_ << endl; } void solve_mid(Mesh & mesh, GridFunction & color, socketstream & sock) { count_ = 0; if (logging_ > 0) { cout << "Solving center blocks in the middle tier..." << endl; } solve_centers(mesh, color, sock); if (logging_ > 0) { cout << "Solving edge blocks in the middle tier..." << endl; } solve_mid_edges(mesh, color, sock); cout << "Move count: " << count_ << endl; } void solve_bot(Mesh & mesh, GridFunction & color, socketstream & sock) { if (logging_ > 0) { cout << "Solving corner block locations in the bottom tier..." << endl; } solve_bot_corner_locations(mesh, color, sock); if (logging_ > 0) { cout << "Solving corner block orientations..." << endl; } solve_corner_orientations(mesh, color, sock); if (logging_ > 0) { cout << "Solving edge block locations..." << endl; } solve_edge_locations(mesh, color, sock); if (logging_ > 0) { cout << "Solving edge block orientations..." << endl; } solve_edge_orientations(mesh, color, sock); } void solve(Mesh & mesh, GridFunction & color, socketstream & sock) { count_ = 0; if (logging_ > 0) { cout << "Solving top center block..." << endl; } solve_top_center(mesh, color, sock); if (logging_ > 0) { cout << "Solving top tier edges..." << endl; } solve_top_edges(mesh, color, sock); if (logging_ > 0) { cout << "Solving top tier corners..." << endl; } solve_top_corners(mesh, color, sock); if (logging_ > 0) { cout << "Solving center blocks in the middle tier..." << endl; } solve_centers(mesh, color, sock); if (logging_ > 0) { cout << "Solving edge blocks in the middle tier..." << endl; } solve_mid_edges(mesh, color, sock); if (logging_ > 0) { cout << "Solving corner block locations in the bottom tier..." << endl; } solve_bot_corner_locations(mesh, color, sock); if (logging_ > 0) { cout << "Solving corner block orientations..." << endl; } solve_corner_orientations(mesh, color, sock); if (logging_ > 0) { cout << "Solving edge block locations..." << endl; } solve_edge_locations(mesh, color, sock); if (logging_ > 0) { cout << "Solving edge block orientations..." << endl; } solve_edge_orientations(mesh, color, sock); cout << "Move count: " << count_ << endl; }