MFEM  v4.5.1
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
rubik.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 //
12 // ---------------------------------------------------
13 // Rubik Miniapp: Model of the Rubik's Cube_TM Puzzle
14 // ---------------------------------------------------
15 //
16 // This miniapp provides a light-hearted example of mesh manipulation and
17 // GLVis integration.
18 //
19 // Compile with: make rubik
20 //
21 // Sample runs: rubik
22 // echo "x21 y21 x23 y23 q\n" | ./rubik
23 // echo "x22 z21 x22 z23 q\n" | ./rubik
24 // echo "x22 y22 z22 q\n" | ./rubik
25 //
26 // Other interesting patterns:
27 // "x13 x31 y13 y31 x13 x31 y13 y31 x13 x31 y13 y31"
28 // "y13 z11 y11 x31 z13 y11 x33 z13 x31 z13 x11 y13 x13 z13 x33 y13 z11"
29 // "y13 y33 z31 y13 z31 y13 z31 x13 y31 x12 y33 z31 y11 x13 z31 x11 y31"
30 // "y13 x11 z13 y11 z33 y31 z31 y13 z33 y13 x33 y12 x13 z33 x33 z12"
31 //
32 // Interactive commands:
33 // [xyz][1,2,3][0-3]
34 // Rotate the specified tier (first integer) of the cube
35 // about the given axis (initial character) in the clockwise
36 // direction (looking from the tip of the axis vector towards
37 // the origin) by so many increments (final integer).
38 // r[0-9]+
39 // Initiate a random sequence of moves. The integer
40 // following 'r' is the number of desired moves.
41 // p
42 // Print the current state of the cube.
43 // c
44 // Swap the corners in the 0th and 1st positions.
45 // t[0,1]
46 // Twist the corners of the bottom tier in the clockwise '1'
47 // or counter-clockwise '0' direction leaving the 3rd corner
48 // unchanged.
49 // e[0,1]
50 // Permute the edges of the bottom tier in the clockwise '1'
51 // or counter-clockwise '0' direction leaving the 3rd edge
52 // unchanged.
53 // f[2,4]
54 // Flip the edges of the bottom tier while keeping them in
55 // place. The integer '2' indicates flipping the 0th and 2nd
56 // edges while '4' indicates flipping all four edges.
57 // R
58 // Resets (or Repaints) the cube to its original configuration.
59 // T
60 // Solve the top tier only.
61 // M
62 // Solve the middle tier only (assumes the top tier has already
63 // been solved.)
64 // B
65 // Solve the bottom tier only (assumes the top two tiers have already
66 // been solved.)
67 // s or S
68 // Solve the cube starting from the top tier and working down.
69 // q or Q
70 // Quit
71 //
72 #include "mfem.hpp"
73 #include "../common/mesh_extras.hpp"
74 #include <cstdlib>
75 #include <fstream>
76 #include <iostream>
77 #include <set>
78 
79 using namespace std;
80 using namespace mfem;
81 using namespace mfem::common;
82 
83 static int step_ = 0;
84 static int nstep_ = 6;
85 static int count_ = 0;
86 static int logging_ = 0;
87 
88 static double cosa_ = cos(0.5 * M_PI / nstep_);
89 static double sina_ = sin(0.5 * M_PI / nstep_);
90 
91 struct RubikState
92 {
93  // Centers are indexed by the local face indices of Geometry::Type CUBE
94  // {Bottom, Front, Right, Back, Left, Top}
95  int cent_[6];
96 
97  // Corners are sorted according to the local vertex index of
98  // Geometry::Type CUBE. Each corner piece is identified by the
99  // three colors it contains. The orientation is determined by the
100  // sequence of colors which corresponds to the x-directed, y-directed,
101  // and then z-directed face.
102  int corn_[24];
103 
104  // Edges are sorted according to the local edge indices of
105  // Geometry::Type CUBE. Each edge piece is identified by the two face
106  // colors it contains. The edge piece orientations are determined by a
107  // right-hand-rule with the thumb directed along the edge and the fingers
108  // curling from the first face color to the second.
109  int edge_[24];
110 };
111 
112 static RubikState rubik;
113 
114 static int edge_colors_[24] =
115 {
116  0,1, 0,2, 3,0, 4,0,
117  1,5, 2,5, 5,3, 5,4,
118  1,4, 2,1, 3,2, 4,3
119 };
120 
121 static int corn_colors_[24] =
122 {
123  4,1,0, 2,1,0, 2,3,0, 4,3,0,
124  4,1,5, 2,1,5, 2,3,5, 4,3,5
125 };
126 
127 struct Move
128 {
129  char axis;
130  int tier;
131  int incr;
132 };
133 
134 void interactive_help();
135 
136 void init_hex_mesh(Mesh & mesh);
137 
138 void init_state();
139 
140 void print_state(ostream & out);
141 
142 void repaint_cube(Mesh & mesh, GridFunction & color, socketstream & sock);
143 
144 bool validate_centers(const int max_ind = 6);
145 
146 bool validate_edges(const int max_ind = 12);
147 
148 bool validate_corners(const int max_ind = 8);
149 
150 void anim_move(char axis, int tier, int increment,
151  Mesh & mesh, GridFunction & color,
152  socketstream & sock);
153 
154 void anim_move(const Move & move,
155  Mesh & mesh, GridFunction & color,
156  socketstream & sock)
157 {
158  anim_move(move.axis, move.tier, move.incr, mesh, color, sock);
159 }
160 
161 void determine_random_moves(Array<Move> & moves);
162 
163 void swap_corners(Mesh & mesh, GridFunction & color, socketstream & sock,
164  int * c0 = NULL, int * c1 = NULL);
165 
166 void twist_corners(Mesh & mesh, GridFunction & color, socketstream & sock,
167  bool cw, int * c0 = NULL, int * c1 = NULL, int * c2 = NULL);
168 
169 void permute_edges(Mesh & mesh, GridFunction & color, socketstream & sock,
170  int * e0, int * e1, int * e2);
171 
172 void permute_edges(Mesh & mesh, GridFunction & color, socketstream & sock,
173  bool cw);
174 
175 void flip_edges(Mesh & mesh, GridFunction & color, socketstream & sock,
176  int n, int * e0 = NULL, int * e1 = NULL,
177  int * e2 = NULL, int * e3 = NULL);
178 
179 void solve_top(Mesh & mesh, GridFunction & color, socketstream & sock);
180 
181 void solve_mid(Mesh & mesh, GridFunction & color, socketstream & sock);
182 
183 void solve_bot(Mesh & mesh, GridFunction & color, socketstream & sock);
184 
185 void solve(Mesh & mesh, GridFunction & color, socketstream & sock);
186 
187 int main(int argc, char *argv[])
188 {
189  bool anim = true;
190  bool visualization = true;
191 
192  OptionsParser args(argc, argv);
193  args.AddOption(&anim, "-anim", "--animation", "-no-anim",
194  "--no-animation",
195  "Enable or disable GLVis animation.");
196  args.AddOption(&logging_, "-l", "--log-level",
197  "Control the amount of logging information.");
198  args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
199  "--no-visualization",
200  "Enable or disable GLVis visualization.");
201  args.Parse();
202  if (!args.Good())
203  {
204  args.PrintUsage(cout);
205  return 1;
206  }
207  args.PrintOptions(cout);
208 
210 
211  if (!visualization) { anim = false; }
212 
213  init_state();
214 
215  // Define an empty mesh
216  Mesh mesh(3, 16 * 27, 27 * 6); // Hexagonal mesh
217 
218  init_hex_mesh(mesh);
219 
220  L2_FECollection fec(0, 3, 1);
221  FiniteElementSpace fespace(&mesh, &fec);
222  GridFunction color(&fespace);
223  color = 0.0;
224 
225  PWConstCoefficient pwCoef(7);
226  for (int i=1; i<=7; i++) { pwCoef(i) = (double)(i-1)/6.0; }
227  color.ProjectCoefficient(pwCoef);
228 
229  // Output the initial mesh to a file
230  {
231  ostringstream oss;
232  oss << "rubik-init.mesh";
233  ofstream ofs(oss.str().c_str());
234  ofs.precision(8);
235  mesh.Print(ofs);
236  ofs.close();
237  }
238 
239  // Output the resulting mesh to GLVis
240  if (visualization)
241  {
242  char vishost[] = "localhost";
243  int visport = 19916;
244  socketstream sock(vishost, visport);
245  sock.precision(8);
246  sock << "solution\n" << mesh << color << "keys Amaa\n"
247  << "palette 25\n" << "autoscale off\n" << flush;
248 
249  while (true)
250  {
251  char axis;
252  int tier, incr;
253  cout << "Enter axis (x, y, z), tier index (1, 2, 3), "
254  << "and rotation (0, 1, 2, 3) with no spaces: ";
255  cin >> axis;
256  if ( axis == 'x' || axis == 'y' || axis == 'z' )
257  {
258  cin >> tier;
259  incr = tier % 10;
260  tier = tier / 10;
261  if (tier >= 1 && tier <= 3)
262  {
263  anim_move(axis, tier, incr, mesh, color, sock);
264  }
265  else
266  {
267  cout << "tier index must be 1, 2, or 3." << endl;
268  }
269  }
270  else if ( axis == 'r' )
271  {
272  // Execute a sequence of random moves
273  // Input the number of moves
274  int num;
275  cin >> num;
276  Array<Move> moves(num);
277  determine_random_moves(moves);
278  for (int i=0; i<num; i++)
279  {
280  anim_move(moves[i], mesh, color, sock);
281  }
282  }
283  else if ( axis == 'p' )
284  {
285  print_state(std::cout);
286  }
287  else if ( axis == 'c' )
288  {
289  swap_corners(mesh, color, sock);
290  }
291  else if ( axis == 't' )
292  {
293  bool cw;
294  cin >> cw;
295  twist_corners(mesh, color, sock, cw);
296  }
297  else if ( axis == 'e' )
298  {
299  bool cw;
300  cin >> cw;
301  permute_edges(mesh, color, sock, cw);
302  }
303  else if ( axis == 'f' )
304  {
305  int n = -1;
306  cin >> n;
307  if (n == 2 || n == 4)
308  {
309  flip_edges(mesh, color, sock, n);
310  }
311  else
312  {
313  cout << "Can only flip 2 or 4 edges at a time." << endl;
314  }
315  }
316  else if ( axis == 'R' )
317  {
318  repaint_cube(mesh, color, sock);
319  }
320  else if ( axis == 'T' )
321  {
322  solve_top(mesh, color, sock);
323  }
324  else if ( axis == 'M' )
325  {
326  solve_mid(mesh, color, sock);
327  }
328  else if ( axis == 'B' )
329  {
330  solve_bot(mesh, color, sock);
331  }
332  else if ( axis == 's' || axis == 'S')
333  {
334  solve(mesh, color, sock);
335  }
336  else if ( axis == 'h' || axis == 'H')
337  {
339  }
340  else if ( axis == 'q' || axis == 'Q')
341  {
342  break;
343  }
344  else
345  {
346  cout << endl << "Unrecognized command. "
347  "Enter 'x', 'y', 'z' followed by '1', '2', or '3' to proceed "
348  "or enter 'q' to quit: ";
349  }
350  }
351  }
352 
353  print_state(std::cout);
354 
355  // Clean up and exit
356  return 0;
357 }
358 
359 void
361 {
362  cout << "\nInteractive Commands\n"
363  << " [xyz][1,2,3][0-3]\n"
364  << "\tRotate the specified tier (first integer) of the cube\n"
365  << "\tabout the given axis (initial character) in the clockwise\n"
366  << "\tdirection (looking from the tip of the axis vector towards\n"
367  << "\tthe origin) by so many increments (final integer).\n"
368  << " r[0-9]+\n"
369  << "\tInitiate a random sequence of moves. The integer\n"
370  << "\tfollowing 'r' is the number of desired moves.\n"
371  << " p\n"
372  << "\tPrint the current state of the cube.\n"
373  << " c\n"
374  << "\tSwap the corners in the 0th and 1st positions.\n"
375  << " t[0,1]\n"
376  << "\tTwist the corners of the bottom tier in the clockwise '1'\n"
377  << "\tor counter-clockwise '0' direction leaving the 3rd corner\n"
378  << "\tunchanged.\n"
379  << " e[0,1]\n"
380  << "\tPermute the edges of the bottom tier in the clockwise '1'\n"
381  << "\tor counter-clockwise '0' direction leaving the 3rd edge\n"
382  << "\tunchanged.\n"
383  << " f[2,4]\n"
384  << "\tFlip the edges of the bottom tier while keeping them in\n"
385  << "\tplace. The integer '2' indicates flipping the 0th and 2nd\n"
386  << "\tedges while '4' indicates flipping all four edges.\n"
387  << " R\n"
388  << "\tResets (or Repaints) the cube to its original configuration.\n"
389  << " T\n"
390  << "\tSolve the top tier only.\n"
391  << " M\n"
392  << "\tSolve the middle tier only (assumes the top tier has already\n"
393  << "\tbeen solved.)\n"
394  << " B\n"
395  << "\tSolve the bottom tier only (assumes the top two tiers have\n"
396  << "\talready been solved.)\n"
397  << " s or S\n"
398  << "\tSolve the cube starting from the top tier and working down.\n"
399  << " h or H\n"
400  << "\tPrint this message.\n"
401  << " q or Q\n"
402  << "\tQuit\n\n";
403 }
404 
405 void
407 {
408  // Add vertices and hexahedra for 27 cubes
409  double c[3];
410  int v[16];
411  int vh[8];
412  int l = 0;
413  for (int k=0; k<3; k++)
414  {
415  for (int j=0; j<3; j++)
416  {
417  for (int i=0; i<3; i++)
418  {
419  c[0] = -1.5 + i;
420  c[1] = -1.5 + j;
421  c[2] = -1.5 + k;
422  mesh.AddVertex(c);
423  v[0] = l; l++;
424 
425  c[0] = -1.5 + i + 1;
426  c[1] = -1.5 + j;
427  c[2] = -1.5 + k;
428  mesh.AddVertex(c);
429  v[1] = l; l++;
430 
431  c[0] = -1.5 + i + 1;
432  c[1] = -1.5 + j + 1;
433  c[2] = -1.5 + k;
434  mesh.AddVertex(c);
435  v[2] = l; l++;
436 
437  c[0] = -1.5 + i;
438  c[1] = -1.5 + j + 1;
439  c[2] = -1.5 + k;
440  mesh.AddVertex(c);
441  v[3] = l; l++;
442 
443  c[0] = -1.5 + i;
444  c[1] = -1.5 + j;
445  c[2] = -1.5 + k + 1;
446  mesh.AddVertex(c);
447  v[4] = l; l++;
448 
449  c[0] = -1.5 + i + 1;
450  c[1] = -1.5 + j;
451  c[2] = -1.5 + k + 1;
452  mesh.AddVertex(c);
453  v[5] = l; l++;
454 
455  c[0] = -1.5 + i + 1;
456  c[1] = -1.5 + j + 1;
457  c[2] = -1.5 + k + 1;
458  mesh.AddVertex(c);
459  v[6] = l; l++;
460 
461  c[0] = -1.5 + i;
462  c[1] = -1.5 + j + 1;
463  c[2] = -1.5 + k + 1;
464  mesh.AddVertex(c);
465  v[7] = l; l++;
466 
467  c[0] = -1.5 + i + 0.25;
468  c[1] = -1.5 + j + 0.25;
469  c[2] = -1.5 + k + 0.25;
470  mesh.AddVertex(c);
471  v[8] = l; l++;
472 
473  c[0] = -1.5 + i + 0.75;
474  c[1] = -1.5 + j + 0.25;
475  c[2] = -1.5 + k + 0.25;
476  mesh.AddVertex(c);
477  v[9] = l; l++;
478 
479  c[0] = -1.5 + i + 0.75;
480  c[1] = -1.5 + j + 0.75;
481  c[2] = -1.5 + k + 0.25;
482  mesh.AddVertex(c);
483  v[10] = l; l++;
484 
485  c[0] = -1.5 + i + 0.25;
486  c[1] = -1.5 + j + 0.75;
487  c[2] = -1.5 + k + 0.25;
488  mesh.AddVertex(c);
489  v[11] = l; l++;
490 
491  c[0] = -1.5 + i + 0.25;
492  c[1] = -1.5 + j + 0.25;
493  c[2] = -1.5 + k + 0.75;
494  mesh.AddVertex(c);
495  v[12] = l; l++;
496 
497  c[0] = -1.5 + i + 0.75;
498  c[1] = -1.5 + j + 0.25;
499  c[2] = -1.5 + k + 0.75;
500  mesh.AddVertex(c);
501  v[13] = l; l++;
502 
503  c[0] = -1.5 + i + 0.75;
504  c[1] = -1.5 + j + 0.75;
505  c[2] = -1.5 + k + 0.75;
506  mesh.AddVertex(c);
507  v[14] = l; l++;
508 
509  c[0] = -1.5 + i + 0.25;
510  c[1] = -1.5 + j + 0.75;
511  c[2] = -1.5 + k + 0.75;
512  mesh.AddVertex(c);
513  v[15] = l; l++;
514 
515  // Bottom
516  vh[0] = v[ 0]; vh[1] = v[ 1]; vh[2] = v[ 2]; vh[3] = v[ 3];
517  vh[4] = v[ 8]; vh[5] = v[ 9]; vh[6] = v[10]; vh[7] = v[11];
518  mesh.AddHex(vh, k==0 ? 6 : 1);
519 
520  // Top
521  vh[0] = v[12]; vh[1] = v[13]; vh[2] = v[14]; vh[3] = v[15];
522  vh[4] = v[ 4]; vh[5] = v[ 5]; vh[6] = v[ 6]; vh[7] = v[ 7];
523  mesh.AddHex(vh, k==2 ? 7 : 1);
524 
525  // Front
526  vh[0] = v[ 0]; vh[1] = v[ 4]; vh[2] = v[ 5]; vh[3] = v[ 1];
527  vh[4] = v[ 8]; vh[5] = v[12]; vh[6] = v[13]; vh[7] = v[ 9];
528  mesh.AddHex(vh, j==0 ? 4 : 1);
529 
530  // Back
531  vh[0] = v[11]; vh[1] = v[15]; vh[2] = v[14]; vh[3] = v[10];
532  vh[4] = v[ 3]; vh[5] = v[ 7]; vh[6] = v[ 6]; vh[7] = v[ 2];
533  mesh.AddHex(vh, j==2 ? 5 : 1);
534 
535  // Left
536  vh[0] = v[ 0]; vh[1] = v[ 3]; vh[2] = v[ 7]; vh[3] = v[ 4];
537  vh[4] = v[ 8]; vh[5] = v[11]; vh[6] = v[15]; vh[7] = v[12];
538  mesh.AddHex(vh, i==0 ? 3 : 1);
539 
540  // Right
541  vh[0] = v[ 9]; vh[1] = v[10]; vh[2] = v[14]; vh[3] = v[13];
542  vh[4] = v[ 1]; vh[5] = v[ 2]; vh[6] = v[ 6]; vh[7] = v[ 5];
543  mesh.AddHex(vh, i==2 ? 2 : 1);
544  }
545  }
546  }
547 
548  mesh.FinalizeTopology();
549 }
550 
551 void
553 {
554  for (int i=0; i<6; i++) { rubik.cent_[i] = i; }
555  for (int i=0; i<24; i++) { rubik.edge_[i] = edge_colors_[i]; }
556  for (int i=0; i<24; i++) { rubik.corn_[i] = corn_colors_[i]; }
557 }
558 
559 void
560 update_centers(char axis, int incr)
561 {
562  int i = (axis == 'x') ? 0 : ((axis == 'y') ? 1 : 2);
563  int i0 = 0 + i * (i - 1) / 2;
564  int i1 = 1 + i * (i + 1) / 2;
565  int i3 = 3 - i * (3 * i - 5) / 2;
566  int i5 = 5 - i * (i - 1);
567 
568  switch (incr)
569  {
570  case 1:
571  std::swap(rubik.cent_[i3], rubik.cent_[i0]);
572  std::swap(rubik.cent_[i5], rubik.cent_[i3]);
573  std::swap(rubik.cent_[i1], rubik.cent_[i5]);
574  break;
575  case 2:
576  std::swap(rubik.cent_[i0], rubik.cent_[i5]);
577  std::swap(rubik.cent_[i1], rubik.cent_[i3]);
578  break;
579  case 3:
580  std::swap(rubik.cent_[i1], rubik.cent_[i0]);
581  std::swap(rubik.cent_[i5], rubik.cent_[i1]);
582  std::swap(rubik.cent_[i3], rubik.cent_[i5]);
583  break;
584  }
585 }
586 
587 void
588 update_corners(char axis, int tier, int incr)
589 {
590  if (tier == 2) { return; }
591 
592  int i = (axis == 'x') ? 0 : ((axis == 'y') ? 1 : 2);
593 
594  if (tier == 1)
595  {
596  // 00:01:02 09:10:11 21:22:23 12:13:14
597  // 01:02:00 13:14:12 16:17:15 04:05:03
598  // 02:00:01 05:03:04 08:06:07 11:09:10
599 
600  int i00 = i;
601  int i09 = 9 - i * ( 6 * i - 10);
602  int i21 = 21 - i * ( 3 * i + 7) / 2;
603  int i12 = 12 + i * (15 * i - 31) / 2;
604 
605  int i01 = 1 - i * ( 3 * i - 5) / 2;
606  int i10 = 10 - i * (15 * i - 23) / 2;
607  int i22 = 22 - i * ( 3 * i + 2);
608  int i13 = 13 + i * ( 6 * i - 14);
609 
610  int i02 = 2 + i * ( 3 * i - 7) / 2;
611  int i11 = 11 - i * ( 9 * i - 11) / 2;
612  int i23 = 23 - 8 * i;
613  int i14 = 14 + i * ( 9 * i - 20);
614 
615  switch (incr)
616  {
617  case 1:
618  // 0->12->21->9->0
619  std::swap(rubik.corn_[i09], rubik.corn_[i00]);
620  std::swap(rubik.corn_[i21], rubik.corn_[i09]);
621  std::swap(rubik.corn_[i12], rubik.corn_[i21]);
622 
623  // 1->14->22->11->1
624  std::swap(rubik.corn_[i11], rubik.corn_[i01]);
625  std::swap(rubik.corn_[i22], rubik.corn_[i11]);
626  std::swap(rubik.corn_[i14], rubik.corn_[i22]);
627 
628  // 2->13->23->10->2
629  std::swap(rubik.corn_[i10], rubik.corn_[i02]);
630  std::swap(rubik.corn_[i23], rubik.corn_[i10]);
631  std::swap(rubik.corn_[i13], rubik.corn_[i23]);
632  break;
633  case 2:
634  // 0->21, 9->12, 1->22, 11->14, 2->23, 10->13
635  std::swap(rubik.corn_[i00], rubik.corn_[i21]);
636  std::swap(rubik.corn_[i09], rubik.corn_[i12]);
637  std::swap(rubik.corn_[i01], rubik.corn_[i22]);
638  std::swap(rubik.corn_[i11], rubik.corn_[i14]);
639  std::swap(rubik.corn_[i02], rubik.corn_[i23]);
640  std::swap(rubik.corn_[i10], rubik.corn_[i13]);
641  break;
642  case 3:
643  // 0->9->21->12->0
644  std::swap(rubik.corn_[i12], rubik.corn_[i00]);
645  std::swap(rubik.corn_[i21], rubik.corn_[i12]);
646  std::swap(rubik.corn_[i09], rubik.corn_[i21]);
647 
648  // 1->11->22->14->1
649  std::swap(rubik.corn_[i14], rubik.corn_[i01]);
650  std::swap(rubik.corn_[i22], rubik.corn_[i14]);
651  std::swap(rubik.corn_[i11], rubik.corn_[i22]);
652 
653  // 2->10->23->13->2
654  std::swap(rubik.corn_[i13], rubik.corn_[i02]);
655  std::swap(rubik.corn_[i23], rubik.corn_[i13]);
656  std::swap(rubik.corn_[i10], rubik.corn_[i23]);
657  break;
658  }
659  }
660  else
661  {
662  // 03:04:05 06:07:08 18:19:20 15:16:17
663  // 10:11:09 22:23:21 19:20:18 07:08:06
664  // 14:12:13 17:15:16 20:18:19 23:21:22
665 
666  int i03 = 3 - i * ( 3 * i - 17) / 2;
667  int i06 = 6 - i * (21 * i - 53) / 2;
668  int i18 = 18 + i;
669  int i15 = 15 + i * (12 * i - 20);
670 
671  int i04 = 4 - i * ( 3 * i - 10);
672  int i07 = 7 - i * (12 * i - 28);
673  int i19 = 19 - i * ( 3 * i - 5) / 2;
674  int i16 = 16 + i * (21 * i - 37) / 2;
675 
676  int i05 = 5 + 4 * i;
677  int i08 = 8 - i * ( 9 * i - 22);
678  int i20 = 20 + i * ( 3 * i - 7) / 2;
679  int i17 = 17 + i * (27 * i - 49) / 2;
680 
681  switch (incr)
682  {
683  case 1:
684  // 3->15->18->6->3
685  std::swap(rubik.corn_[i06], rubik.corn_[i03]);
686  std::swap(rubik.corn_[i18], rubik.corn_[i06]);
687  std::swap(rubik.corn_[i15], rubik.corn_[i18]);
688 
689  // 4->17->19->8->4
690  std::swap(rubik.corn_[i08], rubik.corn_[i04]);
691  std::swap(rubik.corn_[i19], rubik.corn_[i08]);
692  std::swap(rubik.corn_[i17], rubik.corn_[i19]);
693 
694  // 5->16->20->7->5
695  std::swap(rubik.corn_[i07], rubik.corn_[i05]);
696  std::swap(rubik.corn_[i20], rubik.corn_[i07]);
697  std::swap(rubik.corn_[i16], rubik.corn_[i20]);
698  break;
699  case 2:
700  // 3->18, 15->6, 4->19, 17->8, 5->20, 16->7
701  std::swap(rubik.corn_[i03], rubik.corn_[i18]);
702  std::swap(rubik.corn_[i15], rubik.corn_[i06]);
703  std::swap(rubik.corn_[i04], rubik.corn_[i19]);
704  std::swap(rubik.corn_[i17], rubik.corn_[i08]);
705  std::swap(rubik.corn_[i05], rubik.corn_[i20]);
706  std::swap(rubik.corn_[i16], rubik.corn_[i07]);
707  break;
708  case 3:
709  // 3->6->18->15->3
710  std::swap(rubik.corn_[i15], rubik.corn_[i03]);
711  std::swap(rubik.corn_[i18], rubik.corn_[i15]);
712  std::swap(rubik.corn_[i06], rubik.corn_[i18]);
713 
714  // 4->8->19->17->4
715  std::swap(rubik.corn_[i17], rubik.corn_[i04]);
716  std::swap(rubik.corn_[i19], rubik.corn_[i17]);
717  std::swap(rubik.corn_[i08], rubik.corn_[i19]);
718 
719  // 5->7->20->16->5
720  std::swap(rubik.corn_[i16], rubik.corn_[i05]);
721  std::swap(rubik.corn_[i20], rubik.corn_[i16]);
722  std::swap(rubik.corn_[i07], rubik.corn_[i20]);
723  break;
724  }
725  }
726 }
727 
728 void
729 update_edges(char axis, int tier, int incr)
730 {
731  int i = (axis == 'x') ? 0 : ((axis == 'y') ? 1 : 2);
732 
733  if (tier == 1)
734  {
735  int i06 = 6 - i * (13 * i - 23);
736  int i14 = 14 - i * ( 9 * i - 13);
737  int i16 = 16 + i * (11 * i - 27);
738  int i22 = 22 + i * ( 4 * i - 18);
739 
740  switch (incr)
741  {
742  case 1:
743  // 6->17->15->22->6, 7->16->14->23->7
744  std::swap(rubik.edge_[i22], rubik.edge_[i06]);
745  std::swap(rubik.edge_[i14+1], rubik.edge_[i22]);
746  std::swap(rubik.edge_[i16+1], rubik.edge_[i14+1]);
747 
748  std::swap(rubik.edge_[i22+1], rubik.edge_[i06+1]);
749  std::swap(rubik.edge_[i14], rubik.edge_[i22+1]);
750  std::swap(rubik.edge_[i16], rubik.edge_[i14]);
751  break;
752  case 2:
753  // 6->15, 7->14, 16->23, 17->22
754  std::swap(rubik.edge_[i06], rubik.edge_[i14+1]);
755  std::swap(rubik.edge_[i06+1], rubik.edge_[i14]);
756  std::swap(rubik.edge_[i16], rubik.edge_[i22+1]);
757  std::swap(rubik.edge_[i16+1], rubik.edge_[i22]);
758  break;
759  case 3:
760  // 6->22->15->17->6, 7->23->14->16->7
761  std::swap(rubik.edge_[i16+1], rubik.edge_[i06]);
762  std::swap(rubik.edge_[i14+1], rubik.edge_[i16+1]);
763  std::swap(rubik.edge_[i22], rubik.edge_[i14+1]);
764 
765  std::swap(rubik.edge_[i16], rubik.edge_[i06+1]);
766  std::swap(rubik.edge_[i14], rubik.edge_[i16]);
767  std::swap(rubik.edge_[i22+1], rubik.edge_[i14]);
768  break;
769  }
770  }
771  else if (tier == 2)
772  {
773  // 00:01 04:05 12:13 08:09
774  // 06:07 14:15 10:11 02:03
775  // 16:17 18:19 20:21 22:23
776  int i00 = 0 + i * ( 2 * i + 4);
777  int i04 = 4 - i * ( 3 * i - 13);
778  int i08 = 8 + i * (13 * i - 19);
779  int i12 = 12 + i * ( 6 * i - 8);
780 
781  switch (incr)
782  {
783  case 1:
784  // 0->8->12->4->0, 1->9->13->5->1
785  std::swap(rubik.edge_[i04], rubik.edge_[i00]);
786  std::swap(rubik.edge_[i12], rubik.edge_[i04]);
787  std::swap(rubik.edge_[i08], rubik.edge_[i12]);
788 
789  std::swap(rubik.edge_[i04+1], rubik.edge_[i00+1]);
790  std::swap(rubik.edge_[i12+1], rubik.edge_[i04+1]);
791  std::swap(rubik.edge_[i08+1], rubik.edge_[i12+1]);
792  break;
793  case 2:
794  // 0->12, 1->13, 4->8, 5->9
795  std::swap(rubik.edge_[i00], rubik.edge_[i12]);
796  std::swap(rubik.edge_[i00+1], rubik.edge_[i12+1]);
797  std::swap(rubik.edge_[i04], rubik.edge_[i08]);
798  std::swap(rubik.edge_[i04+1], rubik.edge_[i08+1]);
799  break;
800  case 3:
801  // 0->4->12->8->0, 1->5->13->9->1
802  std::swap(rubik.edge_[i08], rubik.edge_[i00]);
803  std::swap(rubik.edge_[i12], rubik.edge_[i08]);
804  std::swap(rubik.edge_[i04], rubik.edge_[i12]);
805 
806  std::swap(rubik.edge_[i08+1], rubik.edge_[i00+1]);
807  std::swap(rubik.edge_[i12+1], rubik.edge_[i08+1]);
808  std::swap(rubik.edge_[i04+1], rubik.edge_[i12+1]);
809  break;
810  }
811  }
812  else
813  {
814  // 02:03 20:21 10:11 18:19
815  // 22:23 12:13 20:21 04:05
816  // 08:09 10:11 12:13 14:15
817  int i02 = 2 - i * (17 * i - 37);
818  int i10 = 10 - i * ( 9 * i - 19);
819  int i18 = 18 + i * (12 * i - 26);
820  int i20 = 20 + i * ( 3 * i - 11);
821 
822  switch (incr)
823  {
824  case 1:
825  // 2->19->11->20->2, 3->18->10->21->3
826  std::swap(rubik.edge_[i20], rubik.edge_[i02]);
827  std::swap(rubik.edge_[i10+1], rubik.edge_[i20]);
828  std::swap(rubik.edge_[i18+1], rubik.edge_[i10+1]);
829 
830  std::swap(rubik.edge_[i20+1], rubik.edge_[i02+1]);
831  std::swap(rubik.edge_[i10], rubik.edge_[i20+1]);
832  std::swap(rubik.edge_[i18], rubik.edge_[i10]);
833  break;
834  case 2:
835  // 2->11, 19->20, 3->10, 18->21
836  std::swap(rubik.edge_[i02], rubik.edge_[i10+1]);
837  std::swap(rubik.edge_[i02+1], rubik.edge_[i10]);
838  std::swap(rubik.edge_[i18], rubik.edge_[i20+1]);
839  std::swap(rubik.edge_[i18+1], rubik.edge_[i20]);
840  break;
841  case 3:
842  // 2->20->11->19->2, 3->21->10->18->3
843  std::swap(rubik.edge_[i18+1], rubik.edge_[i02]);
844  std::swap(rubik.edge_[i10+1], rubik.edge_[i18+1]);
845  std::swap(rubik.edge_[i20], rubik.edge_[i10+1]);
846 
847  std::swap(rubik.edge_[i18], rubik.edge_[i02+1]);
848  std::swap(rubik.edge_[i10], rubik.edge_[i18]);
849  std::swap(rubik.edge_[i20+1], rubik.edge_[i10]);
850  break;
851  }
852  }
853 }
854 
855 void
856 update_state(char axis, int tier, int incr)
857 {
858  if (incr == 0) { return; }
859 
860  // Centers only change if tier == 2
861  if (tier == 2)
862  {
863  update_centers(axis, incr);
864  }
865  else
866  {
867  // Corners only change if tier != 2
868  update_corners(axis, tier, incr);
869  }
870 
871  // Edges always change
872  update_edges(axis, tier, incr);
873 }
874 
875 void
876 print_state(ostream & out_stream)
877 {
878  out_stream << "Rubik's Cube State:\n";
879  out_stream << " Centers: ";
880  for (int i=0; i<6; i++)
881  {
882  out_stream << " " << rubik.cent_[i];
883  }
884  out_stream << "\n";
885  out_stream << " Edges: ";
886  for (int i=0; i<12; i++)
887  {
888  out_stream << " " << rubik.edge_[2 * i + 0]
889  << ":" << rubik.edge_[2 * i + 1];
890  }
891  out_stream << "\n";
892  out_stream << " Corners: ";
893  for (int i=0; i<8; i++)
894  {
895  out_stream << " " << rubik.corn_[3 * i + 0]
896  << ":" << rubik.corn_[3 * i + 1]
897  << ":" << rubik.corn_[3 * i + 2];
898  }
899  out_stream << "\n";
900 }
901 
902 void repaint_cube(Mesh & mesh, GridFunction & color, socketstream & sock)
903 {
904  double xData[3];
905  Vector x(xData,3);
906 
907  double eps = 0.1;
908 
909  Array<int> v;
910  for (int i=0; i<mesh.GetNBE(); i++)
911  {
912  mesh.GetBdrElementVertices(i, v);
913 
914  x = 0.0;
915  for (int j=0; j<v.Size(); j++)
916  {
917  Vector vx(mesh.GetVertex(v[j]), 3);
918  x += vx;
919  }
920  x /= v.Size();
921 
922  int elem = -1;
923  int info = -1;
924 
925  mesh.GetBdrElementAdjacentElement(i, elem, info);
926 
927  if (x[0] > 1.5 - eps)
928  {
929  color[elem] = 1.0 / 6.0;
930  }
931  else if (x[0] < -1.5 + eps)
932  {
933  color[elem] = 2.0 / 6.0;
934  }
935  else if (x[1] < -1.5 + eps)
936  {
937  color[elem] = 3.0 / 6.0;
938  }
939  else if (x[1] > 1.5 - eps)
940  {
941  color[elem] = 4.0 / 6.0;
942  }
943  else if (x[2] < -1.5 + eps)
944  {
945  color[elem] = 5.0 / 6.0;
946  }
947  else if (x[2] > 1.5 - eps)
948  {
949  color[elem] = 1.0;
950  }
951  }
952  sock << "solution\n" << mesh << color << flush;
953 
954  init_state();
955 }
956 
957 bool validate_centers(const int min_ind, const int max_ind)
958 {
959  MFEM_ASSERT(0 <= min_ind && max_ind <= 6, "Maximum center index of "
960  << max_ind << " is out of range.");
961 
962  for (int i=min_ind; i<max_ind; i++)
963  {
964  if (rubik.cent_[i] != i) { return false; }
965  }
966  return true;
967 }
968 
969 bool validate_edges(const int min_ind, const int max_ind)
970 {
971  MFEM_ASSERT(0 <= min_ind && max_ind <= 12, "Maximum edge index of "
972  << max_ind << " is out of range.");
973 
974  for (int i=min_ind; i<max_ind; i++)
975  {
976  if (rubik.edge_[2 * i + 0] != edge_colors_[2 * i + 0] ||
977  rubik.edge_[2 * i + 1] != edge_colors_[2 * i + 1])
978  {
979  return false;
980  }
981  }
982  return true;
983 }
984 
985 bool validate_corners(const int min_ind, const int max_ind)
986 {
987  MFEM_ASSERT(0 <= min_ind && max_ind <= 8, "Maximum corner index of "
988  << max_ind << " is out of range.");
989 
990  for (int i=min_ind; i<max_ind; i++)
991  {
992  if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0] ||
993  rubik.corn_[3 * i + 1] != corn_colors_[3 * i + 1] ||
994  rubik.corn_[3 * i + 2] != corn_colors_[3 * i + 2])
995  {
996  return false;
997  }
998  }
999  return true;
1000 }
1001 
1002 void
1003 rotate_step(char axis, int incr, double * x)
1004 {
1005  if (incr == 0) { return; }
1006 
1007  double y[3];
1008  Vector xVec(x,3);
1009  Vector yVec(y,3);
1010 
1011  yVec = xVec;
1012 
1013  switch (axis)
1014  {
1015  case 'x':
1016  {
1017  switch (incr)
1018  {
1019  case 1:
1020  xVec[1] = cosa_ * yVec[1] + sina_ * yVec[2];
1021  xVec[2] = -sina_ * yVec[1] + cosa_ * yVec[2];
1022  break;
1023  case 2:
1024  xVec[1] = cosa_ * yVec[1] + sina_ * yVec[2];
1025  xVec[2] = -sina_ * yVec[1] + cosa_ * yVec[2];
1026  break;
1027  case 3:
1028  xVec[1] = cosa_ * yVec[1] - sina_ * yVec[2];
1029  xVec[2] = sina_ * yVec[1] + cosa_ * yVec[2];
1030  break;
1031  }
1032  }
1033  break;
1034  case 'y':
1035  {
1036  switch (incr)
1037  {
1038  case 1:
1039  xVec[2] = cosa_ * yVec[2] + sina_ * yVec[0];
1040  xVec[0] = -sina_ * yVec[2] + cosa_ * yVec[0];
1041  break;
1042  case 2:
1043  xVec[2] = cosa_ * yVec[2] + sina_ * yVec[0];
1044  xVec[0] = -sina_ * yVec[2] + cosa_ * yVec[0];
1045  break;
1046  case 3:
1047  xVec[2] = cosa_ * yVec[2] - sina_ * yVec[0];
1048  xVec[0] = sina_ * yVec[2] + cosa_ * yVec[0];
1049  break;
1050  }
1051  }
1052  break;
1053  case 'z':
1054  {
1055  switch (incr)
1056  {
1057  case 1:
1058  xVec[0] = cosa_ * yVec[0] + sina_ * yVec[1];
1059  xVec[1] = -sina_ * yVec[0] + cosa_ * yVec[1];
1060  break;
1061  case 2:
1062  xVec[0] = cosa_ * yVec[0] + sina_ * yVec[1];
1063  xVec[1] = -sina_ * yVec[0] + cosa_ * yVec[1];
1064  break;
1065  case 3:
1066  xVec[0] = cosa_ * yVec[0] - sina_ * yVec[1];
1067  xVec[1] = sina_ * yVec[0] + cosa_ * yVec[1];
1068  break;
1069  }
1070  }
1071  break;
1072  }
1073 }
1074 
1075 bool
1076 anim_step(char axis, int incr, Mesh & mesh)
1077 {
1078  if (incr == 0) { step_ = 0; return false; }
1079  if (incr != 2 && step_ == nstep_) { step_ = 0; return false; }
1080  if (incr == 2 && step_ == 2 * nstep_) { step_ = 0; return false; }
1081 
1082  std::set<int> verts;
1083  Array<int> v;
1084  for (int i=0; i<mesh.GetNE(); i++)
1085  {
1086  if (mesh.GetAttribute(i) == 1) { continue; }
1087 
1088  mesh.GetElementVertices(i, v);
1089 
1090  for (int j=0; j<v.Size(); j++)
1091  {
1092  verts.insert(v[j]);
1093  }
1094  }
1095  for (std::set<int>::iterator sit = verts.begin(); sit!=verts.end(); sit++)
1096  {
1097  rotate_step(axis, incr, mesh.GetVertex(*sit));
1098  }
1099 
1100  step_++;
1101  return true;
1102 }
1103 
1104 void mark_elements(Mesh & mesh, char axis, int tier)
1105 {
1106  double xData[3];
1107  Vector x(xData,3);
1108 
1109  int count = 0;
1110 
1111  Array<int> v;
1112  for (int i=0; i<mesh.GetNE(); i++)
1113  {
1114  mesh.GetElementVertices(i, v);
1115 
1116  x = 0.0;
1117  for (int j=0; j<v.Size(); j++)
1118  {
1119  Vector vx(mesh.GetVertex(v[j]), 3);
1120  x += vx;
1121  }
1122  x /= v.Size();
1123 
1124  switch (axis)
1125  {
1126  case 'x':
1127  if ( x[0] > -2.5 + tier && x[0] < -1.5 + tier )
1128  {
1129  mesh.SetAttribute(i, 2);
1130  count++;
1131  }
1132  else
1133  {
1134  mesh.SetAttribute(i, 1);
1135  }
1136  break;
1137  case 'y':
1138  if ( x[1] > -2.5 + tier && x[1] < -1.5 + tier )
1139  {
1140  mesh.SetAttribute(i, 2);
1141  count++;
1142  }
1143  else
1144  {
1145  mesh.SetAttribute(i, 1);
1146  }
1147  break;
1148  case 'z':
1149  if ( x[2] > -2.5 + tier && x[2] < -1.5 + tier )
1150  {
1151  mesh.SetAttribute(i, 2);
1152  count++;
1153  }
1154  else
1155  {
1156  mesh.SetAttribute(i, 1);
1157  }
1158  break;
1159  }
1160  }
1161 }
1162 
1163 void
1164 anim_move(char axis, int tier, int incr,
1165  Mesh & mesh, GridFunction & color, socketstream & sock)
1166 {
1167  update_state(axis, tier, incr);
1168  mark_elements(mesh, axis, tier);
1169  while (anim_step(axis, incr, mesh))
1170  {
1171  sock << "solution\n" << mesh << color << flush;
1172  }
1173  count_++;
1174 }
1175 
1177 {
1178  for (int i=0; i<moves.Size(); i++)
1179  {
1180  double ran = double(rand()) / RAND_MAX;
1181  int ir = (int)(26 * ran);
1182  int incr = (ir % 3) + 1; ir /= 3;
1183  int tier = (ir % 3) + 1; ir /= 3;
1184  char axis = (ir == 0)? 'x' : ((ir == 1) ? 'y' : 'z');
1185 
1186  if (i == 0)
1187  {
1188  moves[i].axis = axis;
1189  moves[i].tier = tier;
1190  moves[i].incr = incr;
1191  }
1192  else if (axis == moves[i-1].axis)
1193  {
1194  if (tier == moves[i-1].tier)
1195  {
1196  int new_incr = (moves[i-1].incr + incr) % 4;
1197  if (new_incr != 0)
1198  {
1199  moves[i-1].incr = new_incr;
1200  }
1201  i--;
1202  }
1203  else if (incr == moves[i-1].incr)
1204  {
1205  moves[i-1].tier = 6 - moves[i-1].tier - tier;
1206  moves[i-1].incr = 4 - incr;
1207  i--;
1208  }
1209  }
1210  else
1211  {
1212  moves[i].axis = axis;
1213  moves[i].tier = tier;
1214  moves[i].incr = incr;
1215  }
1216  }
1217 }
1218 
1219 void
1221 {
1222  int i5 = -1;
1223  for (int i=0; i<6; i++)
1224  {
1225  if (rubik.cent_[i] == 5)
1226  {
1227  i5 = i;
1228  break;
1229  }
1230  }
1231  switch (i5)
1232  {
1233  case 0:
1234  anim_move('x', 2, 2, mesh, color, sock);
1235  break;
1236  case 1:
1237  anim_move('x', 2, 1, mesh, color, sock);
1238  break;
1239  case 2:
1240  anim_move('y', 2, 1, mesh, color, sock);
1241  break;
1242  case 3:
1243  anim_move('x', 2, 3, mesh, color, sock);
1244  break;
1245  case 4:
1246  anim_move('y', 2, 3, mesh, color, sock);
1247  break;
1248  case 5:
1249  // Do nothing
1250  break;
1251  }
1252 }
1253 
1254 void
1256 {
1257  // Centers are either all correct, all wrong, or two are correct.
1258  // Check for two being correct
1259  bool allWrong = true;
1260  bool allRight = true;
1261  for (int i=0; i<6; i++)
1262  {
1263  if (rubik.cent_[i] == i)
1264  {
1265  allWrong = false;
1266  }
1267  else
1268  {
1269  allRight = false;
1270  }
1271  }
1272 
1273  // If the centers are already correct then return.
1274  if (allRight) { return; }
1275 
1276  if (!allWrong)
1277  {
1278  // Two are correct. Determine which axis should be spun and by how much.
1279  char axis = ' ';
1280  int incr = 0;
1281 
1282  if (rubik.cent_[2] == 2)
1283  {
1284  axis = 'x';
1285 
1286  switch (rubik.cent_[0])
1287  {
1288  case 1:
1289  incr = 1;
1290  break;
1291  case 5:
1292  incr = 2;
1293  break;
1294  case 3:
1295  incr = 3;
1296  break;
1297  }
1298  }
1299  else if (rubik.cent_[1] == 1)
1300  {
1301  axis = 'y';
1302 
1303  switch (rubik.cent_[0])
1304  {
1305  case 2:
1306  incr = 1;
1307  break;
1308  case 5:
1309  incr = 2;
1310  break;
1311  case 4:
1312  incr = 3;
1313  break;
1314  }
1315  }
1316  else
1317  {
1318  axis = 'z';
1319 
1320  switch (rubik.cent_[1])
1321  {
1322  case 4:
1323  incr = 1;
1324  break;
1325  case 3:
1326  incr = 2;
1327  break;
1328  case 2:
1329  incr = 3;
1330  break;
1331  }
1332  }
1333  anim_move(axis, 2, incr, mesh, color, sock);
1334  }
1335  else
1336  {
1337  // They are all incorrect. Find the bottom center and move it into place.
1338  int i0 = -1;
1339  for (int i=1; i<6; i++)
1340  {
1341  if (rubik.cent_[i] == 0)
1342  {
1343  i0 = i;
1344  break;
1345  }
1346  }
1347 
1348  char axis = ' ';
1349  int incr = 0;
1350  switch (i0)
1351  {
1352  case 1:
1353  axis = 'x'; incr = 3;
1354  break;
1355  case 2:
1356  axis = 'y'; incr = 3;
1357  break;
1358  case 3:
1359  axis = 'x'; incr = 1;
1360  break;
1361  case 4:
1362  axis = 'y'; incr = 1;
1363  break;
1364  case 5:
1365  axis = 'x'; incr = 2;
1366  break;
1367  }
1368  anim_move(axis, 2, incr, mesh, color, sock);
1369 
1370  // Two centers should be correct now so recall this function.
1371  solve_centers(mesh, color, sock);
1372  }
1373 }
1374 
1375 int
1377 {
1378  for (int i=0; i<8; i++)
1379  {
1380  if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 0] &&
1381  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 1] &&
1382  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 2])
1383  {
1384  return i;
1385  }
1386  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 1] &&
1387  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 2] &&
1388  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 0])
1389  {
1390  return i + 8;
1391  }
1392  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 2] &&
1393  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 0] &&
1394  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 1])
1395  {
1396  return i + 16;
1397  }
1398  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 2] &&
1399  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 1] &&
1400  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 0])
1401  {
1402  return i + 24;
1403  }
1404  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 1] &&
1405  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 0] &&
1406  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 2])
1407  {
1408  return i + 32;
1409  }
1410  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 0] &&
1411  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 2] &&
1412  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 1])
1413  {
1414  return i + 40;
1415  }
1416  }
1417  return -1;
1418 }
1419 
1420 void
1421 move_to_c4(int i4, int o4,
1422  Mesh & mesh, GridFunction & color, socketstream & sock)
1423 {
1424  switch (i4)
1425  {
1426  case 0:
1427  switch (o4)
1428  {
1429  case 3:
1430  anim_move('x', 1, 3, mesh, color, sock);
1431  anim_move('z', 1, 3, mesh, color, sock);
1432  anim_move('x', 1, 1, mesh, color, sock);
1433  break;
1434  case 4:
1435  anim_move('y', 1, 1, mesh, color, sock);
1436  anim_move('z', 1, 3, mesh, color, sock);
1437  anim_move('y', 1, 3, mesh, color, sock);
1438  anim_move('x', 1, 3, mesh, color, sock);
1439  anim_move('z', 1, 2, mesh, color, sock);
1440  anim_move('x', 1, 1, mesh, color, sock);
1441  break;
1442  case 5:
1443  anim_move('y', 1, 1, mesh, color, sock);
1444  anim_move('z', 1, 1, mesh, color, sock);
1445  anim_move('y', 1, 3, mesh, color, sock);
1446  break;
1447  }
1448  break;
1449  case 1:
1450  switch (o4)
1451  {
1452  case 0:
1453  anim_move('x', 2, 1, mesh, color, sock);
1454  anim_move('y', 1, 2, mesh, color, sock);
1455  anim_move('x', 2, 3, mesh, color, sock);
1456  break;
1457  case 1:
1458  anim_move('z', 1, 1, mesh, color, sock);
1459  anim_move('x', 2, 1, mesh, color, sock);
1460  anim_move('y', 1, 3, mesh, color, sock);
1461  anim_move('x', 2, 3, mesh, color, sock);
1462  break;
1463  case 2:
1464  anim_move('x', 1, 3, mesh, color, sock);
1465  anim_move('z', 1, 1, mesh, color, sock);
1466  anim_move('x', 1, 1, mesh, color, sock);
1467  break;
1468  }
1469  break;
1470  case 2:
1471  switch (o4)
1472  {
1473  case 3:
1474  anim_move('y', 1, 1, mesh, color, sock);
1475  anim_move('z', 1, 2, mesh, color, sock);
1476  anim_move('y', 1, 3, mesh, color, sock);
1477  break;
1478  case 4:
1479  anim_move('x', 3, 1, mesh, color, sock);
1480  anim_move('z', 1, 1, mesh, color, sock);
1481  anim_move('x', 3, 3, mesh, color, sock);
1482  anim_move('x', 2, 1, mesh, color, sock);
1483  anim_move('y', 1, 3, mesh, color, sock);
1484  anim_move('x', 2, 3, mesh, color, sock);
1485  break;
1486  case 5:
1487  anim_move('x', 1, 3, mesh, color, sock);
1488  anim_move('z', 1, 2, mesh, color, sock);
1489  anim_move('x', 1, 1, mesh, color, sock);
1490  break;
1491  }
1492  break;
1493  case 3:
1494  switch (o4)
1495  {
1496  case 0:
1497  anim_move('y', 2, 3, mesh, color, sock);
1498  anim_move('x', 1, 2, mesh, color, sock);
1499  anim_move('y', 2, 1, mesh, color, sock);
1500  break;
1501  case 1:
1502  anim_move('y', 1, 1, mesh, color, sock);
1503  anim_move('z', 1, 3, mesh, color, sock);
1504  anim_move('y', 1, 3, mesh, color, sock);
1505  break;
1506  case 2:
1507  anim_move('z', 1, 3, mesh, color, sock);
1508  anim_move('y', 1, 1, mesh, color, sock);
1509  anim_move('z', 1, 1, mesh, color, sock);
1510  anim_move('y', 1, 3, mesh, color, sock);
1511  break;
1512  }
1513  break;
1514  case 4:
1515  switch (o4)
1516  {
1517  case 1:
1518  anim_move('y', 1, 1, mesh, color, sock);
1519  anim_move('z', 1, 1, mesh, color, sock);
1520  anim_move('y', 1, 3, mesh, color, sock);
1521  anim_move('z', 1, 3, mesh, color, sock);
1522  anim_move('y', 1, 1, mesh, color, sock);
1523  anim_move('z', 1, 1, mesh, color, sock);
1524  anim_move('y', 1, 3, mesh, color, sock);
1525  break;
1526  case 2:
1527  anim_move('x', 1, 3, mesh, color, sock);
1528  anim_move('z', 1, 3, mesh, color, sock);
1529  anim_move('x', 1, 1, mesh, color, sock);
1530  anim_move('z', 1, 1, mesh, color, sock);
1531  anim_move('x', 1, 3, mesh, color, sock);
1532  anim_move('z', 1, 3, mesh, color, sock);
1533  anim_move('x', 1, 1, mesh, color, sock);
1534  break;
1535  }
1536  break;
1537  case 5:
1538  switch (o4)
1539  {
1540  case 3:
1541  anim_move('x', 2, 1, mesh, color, sock);
1542  anim_move('y', 1, 1, mesh, color, sock);
1543  anim_move('x', 2, 3, mesh, color, sock);
1544  break;
1545  case 4:
1546  anim_move('x', 3, 3, mesh, color, sock);
1547  anim_move('z', 1, 1, mesh, color, sock);
1548  anim_move('x', 3, 1, mesh, color, sock);
1549  anim_move('x', 1, 3, mesh, color, sock);
1550  anim_move('z', 1, 3, mesh, color, sock);
1551  anim_move('x', 1, 1, mesh, color, sock);
1552  break;
1553  case 5:
1554  anim_move('y', 1, 3, mesh, color, sock);
1555  anim_move('z', 1, 3, mesh, color, sock);
1556  anim_move('y', 1, 2, mesh, color, sock);
1557  anim_move('z', 1, 2, mesh, color, sock);
1558  anim_move('y', 1, 3, mesh, color, sock);
1559  break;
1560  }
1561  break;
1562  case 6:
1563  switch (o4)
1564  {
1565  case 0:
1566  anim_move('y', 1, 1, mesh, color, sock);
1567  anim_move('y', 3, 3, mesh, color, sock);
1568  anim_move('z', 1, 2, mesh, color, sock);
1569  anim_move('y', 3, 1, mesh, color, sock);
1570  anim_move('y', 1, 3, mesh, color, sock);
1571  break;
1572  case 1:
1573  anim_move('x', 3, 1, mesh, color, sock);
1574  anim_move('z', 1, 1, mesh, color, sock);
1575  anim_move('x', 3, 3, mesh, color, sock);
1576  anim_move('x', 1, 3, mesh, color, sock);
1577  anim_move('z', 1, 2, mesh, color, sock);
1578  anim_move('x', 1, 1, mesh, color, sock);
1579  break;
1580  case 2:
1581  anim_move('y', 3, 3, mesh, color, sock);
1582  anim_move('z', 1, 3, mesh, color, sock);
1583  anim_move('y', 3, 1, mesh, color, sock);
1584  anim_move('y', 1, 1, mesh, color, sock);
1585  anim_move('z', 1, 2, mesh, color, sock);
1586  anim_move('y', 1, 3, mesh, color, sock);
1587  break;
1588  }
1589  break;
1590  case 7:
1591  switch (o4)
1592  {
1593  case 3:
1594  anim_move('x', 1, 1, mesh, color, sock);
1595  anim_move('z', 1, 1, mesh, color, sock);
1596  anim_move('x', 1, 2, mesh, color, sock);
1597  anim_move('z', 1, 2, mesh, color, sock);
1598  anim_move('x', 1, 1, mesh, color, sock);
1599  break;
1600  case 4:
1601  anim_move('y', 3, 1, mesh, color, sock);
1602  anim_move('z', 1, 3, mesh, color, sock);
1603  anim_move('y', 3, 3, mesh, color, sock);
1604  anim_move('y', 1, 1, mesh, color, sock);
1605  anim_move('z', 1, 1, mesh, color, sock);
1606  anim_move('y', 1, 3, mesh, color, sock);
1607  break;
1608  case 5:
1609  anim_move('y', 2, 3, mesh, color, sock);
1610  anim_move('x', 1, 3, mesh, color, sock);
1611  anim_move('y', 2, 1, mesh, color, sock);
1612  break;
1613  }
1614  break;
1615  }
1616 }
1617 
1618 void
1619 move_to_c5(int i5, int o5,
1620  Mesh & mesh, GridFunction & color, socketstream & sock)
1621 {
1622  switch (i5)
1623  {
1624  case 0:
1625  switch (o5)
1626  {
1627  case 0:
1628  anim_move('z', 1, 2, mesh, color, sock);
1629  anim_move('y', 2, 1, mesh, color, sock);
1630  anim_move('x', 3, 2, mesh, color, sock);
1631  anim_move('y', 2, 3, mesh, color, sock);
1632  break;
1633  case 1:
1634  anim_move('z', 1, 3, mesh, color, sock);
1635  anim_move('x', 3, 3, mesh, color, sock);
1636  anim_move('z', 1, 1, mesh, color, sock);
1637  anim_move('x', 3, 1, mesh, color, sock);
1638  break;
1639  case 2:
1640  anim_move('x', 3, 3, mesh, color, sock);
1641  anim_move('z', 1, 3, mesh, color, sock);
1642  anim_move('x', 3, 1, mesh, color, sock);
1643  break;
1644  }
1645  break;
1646  case 1:
1647  switch (o5)
1648  {
1649  case 3:
1650  anim_move('x', 3, 3, mesh, color, sock);
1651  anim_move('z', 1, 1, mesh, color, sock);
1652  anim_move('x', 3, 1, mesh, color, sock);
1653  break;
1654  case 4:
1655  anim_move('y', 1, 3, mesh, color, sock);
1656  anim_move('z', 1, 1, mesh, color, sock);
1657  anim_move('y', 1, 1, mesh, color, sock);
1658  anim_move('x', 3, 3, mesh, color, sock);
1659  anim_move('z', 1, 2, mesh, color, sock);
1660  anim_move('x', 3, 1, mesh, color, sock);
1661  break;
1662  case 5:
1663  anim_move('y', 1, 3, mesh, color, sock);
1664  anim_move('z', 1, 3, mesh, color, sock);
1665  anim_move('y', 1, 1, mesh, color, sock);
1666  break;
1667  }
1668  break;
1669  case 2:
1670  switch (o5)
1671  {
1672  case 0:
1673  anim_move('y', 2, 1, mesh, color, sock);
1674  anim_move('x', 3, 2, mesh, color, sock);
1675  anim_move('y', 2, 3, mesh, color, sock);
1676  break;
1677  case 1:
1678  anim_move('y', 1, 3, mesh, color, sock);
1679  anim_move('z', 1, 1, mesh, color, sock);
1680  anim_move('y', 1, 1, mesh, color, sock);
1681  break;
1682  case 2:
1683  anim_move('z', 1, 1, mesh, color, sock);
1684  anim_move('y', 2, 1, mesh, color, sock);
1685  anim_move('x', 3, 1, mesh, color, sock);
1686  anim_move('y', 2, 3, mesh, color, sock);
1687  break;
1688  }
1689  break;
1690  case 3:
1691  switch (o5)
1692  {
1693  case 3:
1694  anim_move('y', 1, 3, mesh, color, sock);
1695  anim_move('z', 1, 2, mesh, color, sock);
1696  anim_move('y', 1, 1, mesh, color, sock);
1697  break;
1698  case 4:
1699  anim_move('z', 1, 1, mesh, color, sock);
1700  anim_move('y', 2, 1, mesh, color, sock);
1701  anim_move('x', 3, 2, mesh, color, sock);
1702  anim_move('y', 2, 3, mesh, color, sock);
1703  break;
1704  case 5:
1705  anim_move('x', 3, 3, mesh, color, sock);
1706  anim_move('z', 1, 2, mesh, color, sock);
1707  anim_move('x', 3, 1, mesh, color, sock);
1708  break;
1709  }
1710  break;
1711  case 5:
1712  switch (o5)
1713  {
1714  case 1:
1715  anim_move('y', 1, 3, mesh, color, sock);
1716  anim_move('z', 1, 3, mesh, color, sock);
1717  anim_move('y', 1, 1, mesh, color, sock);
1718  anim_move('z', 1, 1, mesh, color, sock);
1719  anim_move('y', 1, 3, mesh, color, sock);
1720  anim_move('z', 1, 3, mesh, color, sock);
1721  anim_move('y', 1, 1, mesh, color, sock);
1722  break;
1723  case 2:
1724  anim_move('x', 3, 3, mesh, color, sock);
1725  anim_move('z', 1, 1, mesh, color, sock);
1726  anim_move('x', 3, 1, mesh, color, sock);
1727  anim_move('z', 1, 3, mesh, color, sock);
1728  anim_move('x', 3, 3, mesh, color, sock);
1729  anim_move('z', 1, 1, mesh, color, sock);
1730  anim_move('x', 3, 1, mesh, color, sock);
1731  break;
1732  }
1733  break;
1734  case 6:
1735  switch (o5)
1736  {
1737  case 3:
1738  anim_move('x', 3, 1, mesh, color, sock);
1739  anim_move('z', 1, 3, mesh, color, sock);
1740  anim_move('x', 3, 2, mesh, color, sock);
1741  anim_move('z', 1, 2, mesh, color, sock);
1742  anim_move('x', 3, 1, mesh, color, sock);
1743  break;
1744  case 4:
1745  anim_move('y', 3, 3, mesh, color, sock);
1746  anim_move('z', 1, 1, mesh, color, sock);
1747  anim_move('y', 3, 1, mesh, color, sock);
1748  anim_move('y', 1, 3, mesh, color, sock);
1749  anim_move('z', 1, 3, mesh, color, sock);
1750  anim_move('y', 1, 1, mesh, color, sock);
1751  break;
1752  case 5:
1753  anim_move('y', 2, 1, mesh, color, sock);
1754  anim_move('x', 3, 3, mesh, color, sock);
1755  anim_move('y', 2, 3, mesh, color, sock);
1756  break;
1757  }
1758  break;
1759  case 7:
1760  switch (o5)
1761  {
1762  case 0:
1763  anim_move('y', 1, 3, mesh, color, sock);
1764  anim_move('y', 3, 1, mesh, color, sock);
1765  anim_move('z', 1, 2, mesh, color, sock);
1766  anim_move('y', 3, 3, mesh, color, sock);
1767  anim_move('y', 1, 1, mesh, color, sock);
1768  break;
1769  case 1:
1770  anim_move('x', 1, 1, mesh, color, sock);
1771  anim_move('z', 1, 3, mesh, color, sock);
1772  anim_move('x', 1, 3, mesh, color, sock);
1773  anim_move('x', 3, 3, mesh, color, sock);
1774  anim_move('z', 1, 2, mesh, color, sock);
1775  anim_move('x', 3, 1, mesh, color, sock);
1776  break;
1777  case 2:
1778  anim_move('y', 3, 1, mesh, color, sock);
1779  anim_move('z', 1, 1, mesh, color, sock);
1780  anim_move('y', 3, 3, mesh, color, sock);
1781  anim_move('y', 1, 3, mesh, color, sock);
1782  anim_move('z', 1, 2, mesh, color, sock);
1783  anim_move('y', 1, 1, mesh, color, sock);
1784  break;
1785  }
1786  break;
1787  }
1788 }
1789 
1790 void
1791 move_to_c6(int i6, int o6,
1792  Mesh & mesh, GridFunction & color, socketstream & sock)
1793 {
1794  switch (i6)
1795  {
1796  case 0:
1797  switch (o6)
1798  {
1799  case 3:
1800  anim_move('y', 3, 3, mesh, color, sock);
1801  anim_move('z', 1, 2, mesh, color, sock);
1802  anim_move('y', 3, 1, mesh, color, sock);
1803  break;
1804  case 4:
1805  anim_move('z', 1, 1, mesh, color, sock);
1806  anim_move('x', 2, 3, mesh, color, sock);
1807  anim_move('y', 3, 2, mesh, color, sock);
1808  anim_move('x', 2, 1, mesh, color, sock);
1809  break;
1810  case 5:
1811  anim_move('x', 3, 1, mesh, color, sock);
1812  anim_move('z', 1, 2, mesh, color, sock);
1813  anim_move('x', 3, 3, mesh, color, sock);
1814  break;
1815  }
1816  break;
1817  case 1:
1818  switch (o6)
1819  {
1820  case 0:
1821  anim_move('z', 1, 2, mesh, color, sock);
1822  anim_move('x', 2, 3, mesh, color, sock);
1823  anim_move('y', 3, 2, mesh, color, sock);
1824  anim_move('x', 2, 1, mesh, color, sock);
1825  break;
1826  case 1:
1827  anim_move('y', 3, 3, mesh, color, sock);
1828  anim_move('z', 1, 3, mesh, color, sock);
1829  anim_move('y', 3, 1, mesh, color, sock);
1830  break;
1831  case 2:
1832  anim_move('z', 1, 1, mesh, color, sock);
1833  anim_move('x', 3, 1, mesh, color, sock);
1834  anim_move('z', 1, 2, mesh, color, sock);
1835  anim_move('x', 3, 3, mesh, color, sock);
1836  break;
1837  }
1838  break;
1839  case 2:
1840  switch (o6)
1841  {
1842  case 3:
1843  anim_move('x', 3, 1, mesh, color, sock);
1844  anim_move('z', 1, 3, mesh, color, sock);
1845  anim_move('x', 3, 3, mesh, color, sock);
1846  break;
1847  case 4:
1848  anim_move('x', 3, 1, mesh, color, sock);
1849  anim_move('z', 1, 1, mesh, color, sock);
1850  anim_move('x', 3, 3, mesh, color, sock);
1851  anim_move('y', 3, 3, mesh, color, sock);
1852  anim_move('z', 1, 2, mesh, color, sock);
1853  anim_move('y', 3, 1, mesh, color, sock);
1854  break;
1855  case 5:
1856  anim_move('y', 3, 3, mesh, color, sock);
1857  anim_move('z', 1, 1, mesh, color, sock);
1858  anim_move('y', 3, 1, mesh, color, sock);
1859  break;
1860  }
1861  break;
1862  case 3:
1863  switch (o6)
1864  {
1865  case 0:
1866  anim_move('x', 2, 3, mesh, color, sock);
1867  anim_move('y', 3, 2, mesh, color, sock);
1868  anim_move('x', 2, 1, mesh, color, sock);
1869  break;
1870  case 1:
1871  anim_move('z', 1, 1, mesh, color, sock);
1872  anim_move('x', 2, 3, mesh, color, sock);
1873  anim_move('y', 3, 1, mesh, color, sock);
1874  anim_move('x', 2, 1, mesh, color, sock);
1875  break;
1876  case 2:
1877  anim_move('x', 3, 1, mesh, color, sock);
1878  anim_move('z', 1, 1, mesh, color, sock);
1879  anim_move('x', 3, 3, mesh, color, sock);
1880  break;
1881  }
1882  break;
1883  case 6:
1884  switch (o6)
1885  {
1886  case 1:
1887  anim_move('y', 3, 3, mesh, color, sock);
1888  anim_move('z', 1, 1, mesh, color, sock);
1889  anim_move('y', 3, 1, mesh, color, sock);
1890  anim_move('z', 1, 3, mesh, color, sock);
1891  anim_move('y', 3, 3, mesh, color, sock);
1892  anim_move('z', 1, 1, mesh, color, sock);
1893  anim_move('y', 3, 1, mesh, color, sock);
1894  break;
1895  case 2:
1896  anim_move('x', 3, 1, mesh, color, sock);
1897  anim_move('z', 1, 3, mesh, color, sock);
1898  anim_move('x', 3, 3, mesh, color, sock);
1899  anim_move('z', 1, 1, mesh, color, sock);
1900  anim_move('x', 3, 1, mesh, color, sock);
1901  anim_move('z', 1, 3, mesh, color, sock);
1902  anim_move('x', 3, 3, mesh, color, sock);
1903  break;
1904  }
1905  break;
1906  case 7:
1907  switch (o6)
1908  {
1909  case 3:
1910  anim_move('x', 2, 3, mesh, color, sock);
1911  anim_move('y', 3, 3, mesh, color, sock);
1912  anim_move('x', 2, 1, mesh, color, sock);
1913  break;
1914  case 4:
1915  anim_move('x', 1, 1, mesh, color, sock);
1916  anim_move('z', 1, 1, mesh, color, sock);
1917  anim_move('x', 1, 3, mesh, color, sock);
1918  anim_move('x', 3, 1, mesh, color, sock);
1919  anim_move('z', 1, 3, mesh, color, sock);
1920  anim_move('x', 3, 3, mesh, color, sock);
1921  break;
1922  case 5:
1923  anim_move('y', 3, 1, mesh, color, sock);
1924  anim_move('z', 1, 3, mesh, color, sock);
1925  anim_move('y', 3, 2, mesh, color, sock);
1926  anim_move('z', 1, 2, mesh, color, sock);
1927  anim_move('y', 3, 1, mesh, color, sock);
1928  break;
1929  }
1930  break;
1931  }
1932 }
1933 
1934 void
1935 move_to_c7(int i7, int o7,
1936  Mesh & mesh, GridFunction & color, socketstream & sock)
1937 {
1938  switch (i7)
1939  {
1940  case 0:
1941  switch (o7)
1942  {
1943  case 0:
1944  anim_move('z', 1, 1, mesh, color, sock);
1945  anim_move('y', 3, 1, mesh, color, sock);
1946  anim_move('z', 1, 1, mesh, color, sock);
1947  anim_move('y', 3, 3, mesh, color, sock);
1948  anim_move('x', 1, 1, mesh, color, sock);
1949  anim_move('z', 1, 2, mesh, color, sock);
1950  anim_move('x', 1, 3, mesh, color, sock);
1951  break;
1952  case 1:
1953  anim_move('y', 3, 1, mesh, color, sock);
1954  anim_move('z', 1, 1, mesh, color, sock);
1955  anim_move('y', 3, 3, mesh, color, sock);
1956  break;
1957  case 2:
1958  anim_move('z', 1, 3, mesh, color, sock);
1959  anim_move('x', 1, 1, mesh, color, sock);
1960  anim_move('z', 1, 2, mesh, color, sock);
1961  anim_move('x', 1, 3, mesh, color, sock);
1962  break;
1963  }
1964  break;
1965  case 1:
1966  switch (o7)
1967  {
1968  case 3:
1969  anim_move('y', 3, 1, mesh, color, sock);
1970  anim_move('z', 1, 2, mesh, color, sock);
1971  anim_move('y', 3, 3, mesh, color, sock);
1972  break;
1973  case 4:
1974  anim_move('z', 1, 2, mesh, color, sock);
1975  anim_move('x', 1, 1, mesh, color, sock);
1976  anim_move('z', 1, 3, mesh, color, sock);
1977  anim_move('x', 1, 3, mesh, color, sock);
1978  anim_move('y', 3, 1, mesh, color, sock);
1979  anim_move('z', 1, 2, mesh, color, sock);
1980  anim_move('y', 3, 3, mesh, color, sock);
1981  break;
1982  case 5:
1983  anim_move('x', 1, 1, mesh, color, sock);
1984  anim_move('z', 1, 2, mesh, color, sock);
1985  anim_move('x', 1, 3, mesh, color, sock);
1986  break;
1987  }
1988  break;
1989  case 2:
1990  switch (o7)
1991  {
1992  case 0:
1993  anim_move('z', 1, 3, mesh, color, sock);
1994  anim_move('x', 1, 1, mesh, color, sock);
1995  anim_move('z', 1, 3, mesh, color, sock);
1996  anim_move('x', 1, 3, mesh, color, sock);
1997  anim_move('y', 3, 1, mesh, color, sock);
1998  anim_move('z', 1, 2, mesh, color, sock);
1999  anim_move('y', 3, 3, mesh, color, sock);
2000  break;
2001  case 1:
2002  anim_move('z', 1, 1, mesh, color, sock);
2003  anim_move('y', 3, 1, mesh, color, sock);
2004  anim_move('z', 1, 2, mesh, color, sock);
2005  anim_move('y', 3, 3, mesh, color, sock);
2006  break;
2007  case 2:
2008  anim_move('x', 1, 1, mesh, color, sock);
2009  anim_move('z', 1, 3, mesh, color, sock);
2010  anim_move('x', 1, 3, mesh, color, sock);
2011  break;
2012  }
2013  break;
2014  case 3:
2015  switch (o7)
2016  {
2017  case 3:
2018  anim_move('x', 1, 1, mesh, color, sock);
2019  anim_move('z', 1, 1, mesh, color, sock);
2020  anim_move('x', 1, 3, mesh, color, sock);
2021  break;
2022  case 4:
2023  anim_move('y', 3, 1, mesh, color, sock);
2024  anim_move('z', 1, 1, mesh, color, sock);
2025  anim_move('y', 3, 3, mesh, color, sock);
2026  anim_move('x', 1, 1, mesh, color, sock);
2027  anim_move('z', 1, 2, mesh, color, sock);
2028  anim_move('x', 1, 3, mesh, color, sock);
2029  break;
2030  case 5:
2031  anim_move('y', 3, 1, mesh, color, sock);
2032  anim_move('z', 1, 3, mesh, color, sock);
2033  anim_move('y', 3, 3, mesh, color, sock);
2034  break;
2035  }
2036  break;
2037  case 7:
2038  switch (o7)
2039  {
2040  case 1:
2041  anim_move('y', 3, 1, mesh, color, sock);
2042  anim_move('z', 1, 3, mesh, color, sock);
2043  anim_move('y', 3, 3, mesh, color, sock);
2044  anim_move('z', 1, 1, mesh, color, sock);
2045  anim_move('y', 3, 1, mesh, color, sock);
2046  anim_move('z', 1, 3, mesh, color, sock);
2047  anim_move('y', 3, 3, mesh, color, sock);
2048  break;
2049  case 2:
2050  anim_move('x', 1, 1, mesh, color, sock);
2051  anim_move('z', 1, 1, mesh, color, sock);
2052  anim_move('x', 1, 3, mesh, color, sock);
2053  anim_move('z', 1, 3, mesh, color, sock);
2054  anim_move('x', 1, 1, mesh, color, sock);
2055  anim_move('z', 1, 1, mesh, color, sock);
2056  anim_move('x', 1, 3, mesh, color, sock);
2057  break;
2058  }
2059  break;
2060  }
2061 }
2062 
2063 void
2065 {
2066  if (logging_ > 1)
2067  {
2068  cout << "Entering solve_top_corners" << endl;
2069  }
2070  if (logging_ > 2)
2071  {
2072  print_state(cout);
2073  }
2074 
2075  // Locate first incorrectly filled corner location in the top tier
2076  int l4 = locate_corner(4);
2077  int i4 = l4 % 8;
2078  int o4 = l4 / 8;
2079  if (logging_ > 1)
2080  {
2081  cout << "Location of 4-th corner: " << i4
2082  << " with orientation " << o4 << endl;
2083  }
2084  if (i4 >= 0)
2085  {
2086  move_to_c4(i4, o4, mesh, color, sock);
2087  }
2088 
2089  // Locate second incorrectly filled corner location in the top tier
2090  int l5 = locate_corner(5);
2091  int i5 = l5 % 8;
2092  int o5 = l5 / 8;
2093  if (logging_ > 1)
2094  {
2095  cout << "Location of 5-th corner: " << i5
2096  << " with orientation " << o5 << endl;
2097  }
2098  if (i5 >= 0)
2099  {
2100  move_to_c5(i5, o5, mesh, color, sock);
2101  }
2102 
2103  // Locate third incorrectly filled corner location in the top tier
2104  int l6 = locate_corner(6);
2105  int i6 = l6 % 8;
2106  int o6 = l6 / 8;
2107  if (logging_ > 1)
2108  {
2109  cout << "Location of 6-th corner: " << i6
2110  << " with orientation " << o6 << endl;
2111  }
2112  if (i6 >= 0)
2113  {
2114  move_to_c6(i6, o6, mesh, color, sock);
2115  }
2116 
2117  // Locate fourth incorrectly filled corner location in the top tier
2118  int l7 = locate_corner(7);
2119  int i7 = l7 % 8;
2120  int o7 = l7 / 8;
2121  if (logging_ > 1)
2122  {
2123  cout << "Location of 7-th corner: " << i7
2124  << " with orientation " << o7 << endl;
2125  }
2126  if (i7 >= 0)
2127  {
2128  move_to_c7(i7, o7, mesh, color, sock);
2129  }
2130 }
2131 
2132 int
2133 locate_edge(int ind)
2134 {
2135  for (int i=0; i<12; i++)
2136  {
2137  if ((rubik.edge_[2 * i + 0] == edge_colors_[2 * ind + 0] &&
2138  rubik.edge_[2 * i + 1] == edge_colors_[2 * ind + 1]))
2139  {
2140  return i;
2141  }
2142  if ((rubik.edge_[2 * i + 0] == edge_colors_[2 * ind + 1] &&
2143  rubik.edge_[2 * i + 1] == edge_colors_[2 * ind + 0]))
2144  {
2145  return -i - 1;
2146  }
2147  }
2148  return -99;
2149 }
2150 
2151 void
2152 move_to_e4(int i4, int o4,
2153  Mesh & mesh, GridFunction & color, socketstream & sock)
2154 {
2155  if (o4 == 0)
2156  {
2157  switch (i4)
2158  {
2159  case 0:
2160  anim_move('y', 2, 1, mesh, color, sock);
2161  anim_move('x', 2, 1, mesh, color, sock);
2162  anim_move('y', 2, 3, mesh, color, sock);
2163  break;
2164  case 1:
2165  anim_move('x', 3, 1, mesh, color, sock);
2166  anim_move('y', 1, 1, mesh, color, sock);
2167  break;
2168  case 2:
2169  anim_move('y', 3, 2, mesh, color, sock);
2170  anim_move('z', 3, 2, mesh, color, sock);
2171  break;
2172  case 3:
2173  anim_move('x', 1, 2, mesh, color, sock);
2174  anim_move('z', 3, 3, mesh, color, sock);
2175  break;
2176  case 5:
2177  anim_move('z', 3, 1, mesh, color, sock);
2178  break;
2179  case 6:
2180  anim_move('y', 2, 1, mesh, color, sock);
2181  anim_move('x', 2, 3, mesh, color, sock);
2182  anim_move('y', 2, 3, mesh, color, sock);
2183  break;
2184  case 7:
2185  anim_move('y', 2, 3, mesh, color, sock);
2186  anim_move('z', 3, 1, mesh, color, sock);
2187  anim_move('y', 2, 1, mesh, color, sock);
2188  break;
2189  case 8:
2190  anim_move('y', 1, 3, mesh, color, sock);
2191  break;
2192  case 9:
2193  anim_move('z', 2, 1, mesh, color, sock);
2194  anim_move('y', 1, 3, mesh, color, sock);
2195  break;
2196  case 10:
2197  anim_move('y', 3, 1, mesh, color, sock);
2198  anim_move('z', 3, 2, mesh, color, sock);
2199  break;
2200  case 11:
2201  anim_move('x', 1, 3, mesh, color, sock);
2202  anim_move('z', 3, 3, mesh, color, sock);
2203  break;
2204  }
2205  }
2206  else
2207  {
2208  switch (i4)
2209  {
2210  case 0:
2211  anim_move('y', 1, 2, mesh, color, sock);
2212  break;
2213  case 1:
2214  anim_move('z', 1, 3, mesh, color, sock);
2215  anim_move('y', 1, 2, mesh, color, sock);
2216  break;
2217  case 2:
2218  anim_move('x', 2, 3, mesh, color, sock);
2219  anim_move('z', 3, 1, mesh, color, sock);
2220  anim_move('x', 2, 1, mesh, color, sock);
2221  anim_move('z', 3, 1, mesh, color, sock);
2222  break;
2223  case 3:
2224  anim_move('y', 2, 3, mesh, color, sock);
2225  anim_move('z', 3, 3, mesh, color, sock);
2226  anim_move('y', 2, 1, mesh, color, sock);
2227  break;
2228  case 4:
2229  anim_move('y', 1, 3, mesh, color, sock);
2230  anim_move('z', 2, 1, mesh, color, sock);
2231  anim_move('y', 1, 3, mesh, color, sock);
2232  break;
2233  case 5:
2234  anim_move('y', 2, 1, mesh, color, sock);
2235  anim_move('z', 3, 3, mesh, color, sock);
2236  anim_move('y', 2, 3, mesh, color, sock);
2237  break;
2238  case 6:
2239  anim_move('z', 3, 2, mesh, color, sock);
2240  break;
2241  case 7:
2242  anim_move('z', 3, 3, mesh, color, sock);
2243  break;
2244  case 8:
2245  anim_move('z', 2, 3, mesh, color, sock);
2246  anim_move('y', 1, 1, mesh, color, sock);
2247  break;
2248  case 9:
2249  anim_move('y', 1, 1, mesh, color, sock);
2250  break;
2251  case 10:
2252  anim_move('x', 3, 3, mesh, color, sock);
2253  anim_move('z', 3, 1, mesh, color, sock);
2254  break;
2255  case 11:
2256  anim_move('y', 3, 3, mesh, color, sock);
2257  anim_move('z', 3, 2, mesh, color, sock);
2258  break;
2259  }
2260  }
2261 }
2262 
2263 void
2264 move_to_e5(int i5, int o5,
2265  Mesh & mesh, GridFunction & color, socketstream & sock)
2266 {
2267  if (o5 == 0)
2268  {
2269  switch (i5)
2270  {
2271  case 0:
2272  anim_move('y', 1, 3, mesh, color, sock);
2273  anim_move('x', 3, 1, mesh, color, sock);
2274  anim_move('y', 1, 1, mesh, color, sock);
2275  break;
2276  case 1:
2277  anim_move('x', 2, 3, mesh, color, sock);
2278  anim_move('y', 2, 1, mesh, color, sock);
2279  anim_move('x', 2, 1, mesh, color, sock);
2280  break;
2281  case 2:
2282  anim_move('z', 1, 1, mesh, color, sock);
2283  anim_move('x', 3, 2, mesh, color, sock);
2284  break;
2285  case 3:
2286  anim_move('z', 1, 2, mesh, color, sock);
2287  anim_move('x', 3, 2, mesh, color, sock);
2288  break;
2289  case 6:
2290  anim_move('y', 3, 3, mesh, color, sock);
2291  anim_move('x', 3, 3, mesh, color, sock);
2292  break;
2293  case 7:
2294  anim_move('x', 2, 1, mesh, color, sock);
2295  anim_move('y', 2, 3, mesh, color, sock);
2296  anim_move('x', 2, 3, mesh, color, sock);
2297  break;
2298  case 8:
2299  anim_move('z', 2, 3, mesh, color, sock);
2300  anim_move('x', 3, 1, mesh, color, sock);
2301  break;
2302  case 9:
2303  anim_move('x', 3, 1, mesh, color, sock);
2304  break;
2305  case 10:
2306  anim_move('z', 2, 1, mesh, color, sock);
2307  anim_move('x', 3, 1, mesh, color, sock);
2308  break;
2309  case 11:
2310  anim_move('y', 3, 2, mesh, color, sock);
2311  anim_move('x', 3, 3, mesh, color, sock);
2312  break;
2313  }
2314  }
2315  else
2316  {
2317  switch (i5)
2318  {
2319  case 0:
2320  anim_move('z', 1, 3, mesh, color, sock);
2321  anim_move('x', 3, 2, mesh, color, sock);
2322  break;
2323  case 1:
2324  anim_move('x', 3, 2, mesh, color, sock);
2325  break;
2326  case 2:
2327  anim_move('y', 3, 1, mesh, color, sock);
2328  anim_move('x', 3, 3, mesh, color, sock);
2329  break;
2330  case 3:
2331  anim_move('z', 1, 2, mesh, color, sock);
2332  anim_move('x', 2, 3, mesh, color, sock);
2333  anim_move('y', 2, 1, mesh, color, sock);
2334  anim_move('x', 2, 1, mesh, color, sock);
2335  break;
2336  case 5:
2337  anim_move('x', 3, 1, mesh, color, sock);
2338  anim_move('z', 2, 1, mesh, color, sock);
2339  anim_move('x', 3, 1, mesh, color, sock);
2340  break;
2341  case 6:
2342  anim_move('y', 1, 1, mesh, color, sock);
2343  anim_move('z', 3, 1, mesh, color, sock);
2344  anim_move('y', 1, 3, mesh, color, sock);
2345  break;
2346  case 7:
2347  anim_move('y', 1, 1, mesh, color, sock);
2348  anim_move('z', 3, 2, mesh, color, sock);
2349  anim_move('y', 1, 3, mesh, color, sock);
2350  break;
2351  case 8:
2352  anim_move('z', 2, 2, mesh, color, sock);
2353  anim_move('x', 3, 3, mesh, color, sock);
2354  break;
2355  case 9:
2356  anim_move('z', 2, 3, mesh, color, sock);
2357  anim_move('x', 3, 3, mesh, color, sock);
2358  break;
2359  case 10:
2360  anim_move('x', 3, 3, mesh, color, sock);
2361  break;
2362  case 11:
2363  anim_move('z', 2, 1, mesh, color, sock);
2364  anim_move('x', 3, 3, mesh, color, sock);
2365  break;
2366  }
2367  }
2368 }
2369 
2370 void
2371 move_to_e6(int i6, int o6,
2372  Mesh & mesh, GridFunction & color, socketstream & sock)
2373 {
2374  if (o6 == 0)
2375  {
2376  switch (i6)
2377  {
2378  case 0:
2379  anim_move('z', 1, 2, mesh, color, sock);
2380  anim_move('y', 3, 2, mesh, color, sock);
2381  break;
2382  case 1:
2383  anim_move('z', 1, 3, mesh, color, sock);
2384  anim_move('y', 3, 2, mesh, color, sock);
2385  break;
2386  case 2:
2387  anim_move('y', 3, 1, mesh, color, sock);
2388  anim_move('z', 2, 3, mesh, color, sock);
2389  anim_move('y', 3, 3, mesh, color, sock);
2390  break;
2391  case 3:
2392  anim_move('x', 1, 3, mesh, color, sock);
2393  anim_move('y', 3, 3, mesh, color, sock);
2394  break;
2395  case 7:
2396  anim_move('z', 3, 1, mesh, color, sock);
2397  anim_move('y', 3, 1, mesh, color, sock);
2398  anim_move('z', 3, 3, mesh, color, sock);
2399  anim_move('y', 3, 3, mesh, color, sock);
2400  break;
2401  case 8:
2402  anim_move('z', 2, 1, mesh, color, sock);
2403  anim_move('y', 3, 3, mesh, color, sock);
2404  break;
2405  case 9:
2406  anim_move('z', 2, 2, mesh, color, sock);
2407  anim_move('y', 3, 3, mesh, color, sock);
2408  break;
2409  case 10:
2410  anim_move('z', 2, 3, mesh, color, sock);
2411  anim_move('y', 3, 3, mesh, color, sock);
2412  break;
2413  case 11:
2414  anim_move('y', 3, 3, mesh, color, sock);
2415  break;
2416  }
2417  }
2418  else
2419  {
2420  switch (i6)
2421  {
2422  case 0:
2423  anim_move('z', 1, 1, mesh, color, sock);
2424  anim_move('x', 1, 3, mesh, color, sock);
2425  anim_move('y', 3, 3, mesh, color, sock);
2426  break;
2427  case 1:
2428  anim_move('x', 2, 1, mesh, color, sock);
2429  anim_move('z', 1, 3, mesh, color, sock);
2430  anim_move('x', 2, 3, mesh, color, sock);
2431  break;
2432  case 2:
2433  anim_move('y', 3, 2, mesh, color, sock);
2434  break;
2435  case 3:
2436  anim_move('z', 1, 1, mesh, color, sock);
2437  anim_move('y', 3, 2, mesh, color, sock);
2438  break;
2439  case 6:
2440  anim_move('y', 3, 1, mesh, color, sock);
2441  anim_move('z', 2, 1, mesh, color, sock);
2442  anim_move('y', 3, 1, mesh, color, sock);
2443  break;
2444  case 7:
2445  anim_move('x', 1, 1, mesh, color, sock);
2446  anim_move('y', 3, 3, mesh, color, sock);
2447  break;
2448  case 8:
2449  anim_move('z', 2, 2, mesh, color, sock);
2450  anim_move('y', 3, 1, mesh, color, sock);
2451  break;
2452  case 9:
2453  anim_move('z', 2, 3, mesh, color, sock);
2454  anim_move('y', 3, 1, mesh, color, sock);
2455  break;
2456  case 10:
2457  anim_move('y', 3, 1, mesh, color, sock);
2458  break;
2459  case 11:
2460  anim_move('z', 2, 1, mesh, color, sock);
2461  anim_move('y', 3, 1, mesh, color, sock);
2462  break;
2463  }
2464  }
2465 }
2466 
2467 void
2468 move_to_e7(int i7, int o7,
2469  Mesh & mesh, GridFunction & color, socketstream & sock)
2470 {
2471  if (o7 == 0)
2472  {
2473  switch (i7)
2474  {
2475  case 0:
2476  anim_move('z', 1, 1, mesh, color, sock);
2477  anim_move('x', 1, 2, mesh, color, sock);
2478  break;
2479  case 1:
2480  anim_move('z', 1, 2, mesh, color, sock);
2481  anim_move('x', 1, 2, mesh, color, sock);
2482  break;
2483  case 2:
2484  anim_move('y', 3, 3, mesh, color, sock);
2485  anim_move('x', 1, 3, mesh, color, sock);
2486  anim_move('y', 3, 1, mesh, color, sock);
2487  break;
2488  case 3:
2489  anim_move('x', 1, 1, mesh, color, sock);
2490  anim_move('z', 2, 1, mesh, color, sock);
2491  anim_move('x', 1, 3, mesh, color, sock);
2492  break;
2493  case 8:
2494  anim_move('x', 1, 1, mesh, color, sock);
2495  break;
2496  case 9:
2497  anim_move('z', 2, 1, mesh, color, sock);
2498  anim_move('x', 1, 1, mesh, color, sock);
2499  break;
2500  case 10:
2501  anim_move('z', 2, 2, mesh, color, sock);
2502  anim_move('x', 1, 1, mesh, color, sock);
2503  break;
2504  case 11:
2505  anim_move('z', 2, 3, mesh, color, sock);
2506  anim_move('x', 1, 1, mesh, color, sock);
2507  break;
2508  }
2509  }
2510  else
2511  {
2512  switch (i7)
2513  {
2514  case 0:
2515  anim_move('y', 1, 3, mesh, color, sock);
2516  anim_move('x', 1, 1, mesh, color, sock);
2517  anim_move('y', 1, 1, mesh, color, sock);
2518  break;
2519  case 1:
2520  anim_move('z', 1, 3, mesh, color, sock);
2521  anim_move('y', 3, 3, mesh, color, sock);
2522  anim_move('x', 1, 3, mesh, color, sock);
2523  anim_move('y', 3, 1, mesh, color, sock);
2524  break;
2525  case 2:
2526  anim_move('z', 1, 3, mesh, color, sock);
2527  anim_move('x', 1, 2, mesh, color, sock);
2528  break;
2529  case 3:
2530  anim_move('x', 1, 2, mesh, color, sock);
2531  break;
2532  case 7:
2533  anim_move('x', 1, 1, mesh, color, sock);
2534  anim_move('z', 2, 3, mesh, color, sock);
2535  anim_move('x', 1, 1, mesh, color, sock);
2536  break;
2537  case 8:
2538  anim_move('z', 2, 1, mesh, color, sock);
2539  anim_move('x', 1, 3, mesh, color, sock);
2540  break;
2541  case 9:
2542  anim_move('z', 2, 2, mesh, color, sock);
2543  anim_move('x', 1, 3, mesh, color, sock);
2544  break;
2545  case 10:
2546  anim_move('z', 2, 3, mesh, color, sock);
2547  anim_move('x', 1, 3, mesh, color, sock);
2548  break;
2549  case 11:
2550  anim_move('x', 1, 3, mesh, color, sock);
2551  break;
2552  }
2553  }
2554 }
2555 
2556 void
2557 move_to_e8(int i8, int o8,
2558  Mesh & mesh, GridFunction & color, socketstream & sock)
2559 {
2560  if (o8 == 0)
2561  {
2562  switch (i8)
2563  {
2564  case 0: // Verified
2565  anim_move('z', 1, 2, mesh, color, sock);
2566  anim_move('y', 1, 1, mesh, color, sock);
2567  anim_move('z', 1, 3, mesh, color, sock);
2568  anim_move('y', 1, 3, mesh, color, sock);
2569  anim_move('x', 1, 1, mesh, color, sock);
2570  anim_move('y', 1, 3, mesh, color, sock);
2571  anim_move('x', 1, 3, mesh, color, sock);
2572  anim_move('y', 1, 1, mesh, color, sock);
2573  break;
2574  case 1: // Verified
2575  anim_move('z', 1, 3, mesh, color, sock);
2576  anim_move('y', 1, 1, mesh, color, sock);
2577  anim_move('z', 1, 3, mesh, color, sock);
2578  anim_move('y', 1, 3, mesh, color, sock);
2579  anim_move('x', 1, 1, mesh, color, sock);
2580  anim_move('y', 1, 3, mesh, color, sock);
2581  anim_move('x', 1, 3, mesh, color, sock);
2582  anim_move('y', 1, 1, mesh, color, sock);
2583  break;
2584  case 2: // Verified
2585  anim_move('z', 1, 1, mesh, color, sock);
2586  anim_move('x', 1, 3, mesh, color, sock);
2587  anim_move('z', 1, 1, mesh, color, sock);
2588  anim_move('x', 1, 1, mesh, color, sock);
2589  anim_move('y', 1, 3, mesh, color, sock);
2590  anim_move('x', 1, 1, mesh, color, sock);
2591  anim_move('y', 1, 1, mesh, color, sock);
2592  anim_move('x', 1, 3, mesh, color, sock);
2593  break;
2594  case 3: // Verified
2595  anim_move('z', 1, 2, mesh, color, sock);
2596  anim_move('x', 1, 3, mesh, color, sock);
2597  anim_move('z', 1, 1, mesh, color, sock);
2598  anim_move('x', 1, 1, mesh, color, sock);
2599  anim_move('y', 1, 3, mesh, color, sock);
2600  anim_move('x', 1, 1, mesh, color, sock);
2601  anim_move('y', 1, 1, mesh, color, sock);
2602  anim_move('x', 1, 3, mesh, color, sock);
2603  break;
2604  case 9: // Verified
2605  anim_move('x', 3, 3, mesh, color, sock);
2606  permute_edges(mesh, color, sock, false);
2607  anim_move('x', 3, 1, mesh, color, sock);
2608  anim_move('z', 1, 1, mesh, color, sock);
2609  anim_move('y', 1, 1, mesh, color, sock);
2610  permute_edges(mesh, color, sock, true);
2611  anim_move('y', 1, 3, mesh, color, sock);
2612  break;
2613  case 10: // Verified
2614  anim_move('z', 2, 1, mesh, color, sock);
2615  anim_move('y', 1, 2, mesh, color, sock);
2616  anim_move('z', 2, 3, mesh, color, sock);
2617  anim_move('y', 1, 2, mesh, color, sock);
2618  break;
2619  case 11: // Verified
2620  anim_move('y', 3, 1, mesh, color, sock);
2621  permute_edges(mesh, color, sock, true);
2622  anim_move('y', 3, 3, mesh, color, sock);
2623  anim_move('z', 1, 3, mesh, color, sock);
2624  anim_move('y', 1, 1, mesh, color, sock);
2625  permute_edges(mesh, color, sock, false);
2626  anim_move('y', 1, 3, mesh, color, sock);
2627  break;
2628  }
2629  }
2630  else
2631  {
2632  switch (i8)
2633  {
2634  case 0: // Verified
2635  anim_move('z', 1, 3, mesh, color, sock);
2636  anim_move('x', 1, 3, mesh, color, sock);
2637  anim_move('z', 1, 1, mesh, color, sock);
2638  anim_move('x', 1, 1, mesh, color, sock);
2639  anim_move('y', 1, 3, mesh, color, sock);
2640  anim_move('x', 1, 1, mesh, color, sock);
2641  anim_move('y', 1, 1, mesh, color, sock);
2642  anim_move('x', 1, 3, mesh, color, sock);
2643  break;
2644  case 1: // Verified
2645  anim_move('x', 1, 3, mesh, color, sock);
2646  anim_move('z', 1, 1, mesh, color, sock);
2647  anim_move('x', 1, 1, mesh, color, sock);
2648  anim_move('y', 1, 3, mesh, color, sock);
2649  anim_move('x', 1, 1, mesh, color, sock);
2650  anim_move('y', 1, 1, mesh, color, sock);
2651  anim_move('x', 1, 3, mesh, color, sock);
2652  break;
2653  case 2: // Verified
2654  anim_move('y', 1, 1, mesh, color, sock);
2655  anim_move('z', 1, 3, mesh, color, sock);
2656  anim_move('y', 1, 3, mesh, color, sock);
2657  anim_move('x', 1, 1, mesh, color, sock);
2658  anim_move('y', 1, 3, mesh, color, sock);
2659  anim_move('x', 1, 3, mesh, color, sock);
2660  anim_move('y', 1, 1, mesh, color, sock);
2661  break;
2662  case 3: // Verified
2663  anim_move('z', 1, 1, mesh, color, sock);
2664  anim_move('y', 1, 1, mesh, color, sock);
2665  anim_move('z', 1, 3, mesh, color, sock);
2666  anim_move('y', 1, 3, mesh, color, sock);
2667  anim_move('x', 1, 1, mesh, color, sock);
2668  anim_move('y', 1, 3, mesh, color, sock);
2669  anim_move('x', 1, 3, mesh, color, sock);
2670  anim_move('y', 1, 1, mesh, color, sock);
2671  break;
2672  case 8: // Verified
2673  anim_move('y', 1, 1, mesh, color, sock);
2674  anim_move('z', 1, 3, mesh, color, sock);
2675  anim_move('y', 1, 3, mesh, color, sock);
2676  anim_move('x', 1, 1, mesh, color, sock);
2677  anim_move('y', 1, 3, mesh, color, sock);
2678  anim_move('x', 1, 3, mesh, color, sock);
2679  anim_move('y', 1, 1, mesh, color, sock);
2680  anim_move('z', 1, 3, mesh, color, sock);
2681  anim_move('y', 1, 1, mesh, color, sock);
2682  anim_move('z', 1, 3, mesh, color, sock);
2683  anim_move('y', 1, 3, mesh, color, sock);
2684  anim_move('x', 1, 1, mesh, color, sock);
2685  anim_move('y', 1, 3, mesh, color, sock);
2686  anim_move('x', 1, 3, mesh, color, sock);
2687  anim_move('y', 1, 1, mesh, color, sock);
2688  break;
2689  case 9: // Verified
2690  anim_move('y', 1, 2, mesh, color, sock);
2691  anim_move('z', 1, 2, mesh, color, sock);
2692  anim_move('y', 1, 2, mesh, color, sock);
2693  anim_move('z', 1, 2, mesh, color, sock);
2694  anim_move('y', 1, 2, mesh, color, sock);
2695  break;
2696  case 10: // Verified
2697  anim_move('y', 3, 3, mesh, color, sock);
2698  permute_edges(mesh, color, sock, false);
2699  anim_move('y', 3, 1, mesh, color, sock);
2700  anim_move('z', 1, 3, mesh, color, sock);
2701  anim_move('y', 1, 1, mesh, color, sock);
2702  permute_edges(mesh, color, sock, true);
2703  anim_move('y', 1, 3, mesh, color, sock);
2704  break;
2705  case 11: // Verified
2706  anim_move('z', 2, 1, mesh, color, sock);
2707  anim_move('x', 1, 2, mesh, color, sock);
2708  anim_move('z', 2, 3, mesh, color, sock);
2709  anim_move('x', 1, 2, mesh, color, sock);
2710  break;
2711  }
2712  }
2713 }
2714 
2715 void
2716 move_to_e9(int i9, int o9,
2717  Mesh & mesh, GridFunction & color, socketstream & sock)
2718 {
2719  if (o9 == 0)
2720  {
2721  switch (i9)
2722  {
2723  case 0: // Verified
2724  anim_move('z', 1, 1, mesh, color, sock);
2725  anim_move('x', 3, 3, mesh, color, sock);
2726  anim_move('z', 1, 3, mesh, color, sock);
2727  anim_move('x', 3, 1, mesh, color, sock);
2728  anim_move('y', 1, 1, mesh, color, sock);
2729  anim_move('x', 3, 1, mesh, color, sock);
2730  anim_move('y', 1, 3, mesh, color, sock);
2731  anim_move('x', 3, 3, mesh, color, sock);
2732  break;
2733  case 1: // Verified
2734  anim_move('z', 1, 2, mesh, color, sock);
2735  anim_move('x', 3, 3, mesh, color, sock);
2736  anim_move('z', 1, 3, mesh, color, sock);
2737  anim_move('x', 3, 1, mesh, color, sock);
2738  anim_move('y', 1, 1, mesh, color, sock);
2739  anim_move('x', 3, 1, mesh, color, sock);
2740  anim_move('y', 1, 3, mesh, color, sock);
2741  anim_move('x', 3, 3, mesh, color, sock);
2742  break;
2743  case 2: // Verified
2744  anim_move('y', 1, 3, mesh, color, sock);
2745  anim_move('z', 1, 1, mesh, color, sock);
2746  anim_move('y', 1, 1, mesh, color, sock);
2747  anim_move('x', 3, 1, mesh, color, sock);
2748  anim_move('y', 1, 1, mesh, color, sock);
2749  anim_move('x', 3, 3, mesh, color, sock);
2750  anim_move('y', 1, 3, mesh, color, sock);
2751  break;
2752  case 3: // Verified
2753  anim_move('z', 1, 1, mesh, color, sock);
2754  anim_move('y', 1, 3, mesh, color, sock);
2755  anim_move('z', 1, 1, mesh, color, sock);
2756  anim_move('y', 1, 1, mesh, color, sock);
2757  anim_move('x', 3, 1, mesh, color, sock);
2758  anim_move('y', 1, 1, mesh, color, sock);
2759  anim_move('x', 3, 3, mesh, color, sock);
2760  anim_move('y', 1, 3, mesh, color, sock);
2761  break;
2762  case 10: // Verified
2763  anim_move('y', 3, 3, mesh, color, sock);
2764  permute_edges(mesh, color, sock, true);
2765  anim_move('y', 3, 1, mesh, color, sock);
2766  anim_move('z', 1, 3, mesh, color, sock);
2767  anim_move('y', 1, 3, mesh, color, sock);
2768  permute_edges(mesh, color, sock, false);
2769  anim_move('y', 1, 1, mesh, color, sock);
2770  break;
2771  case 11: // Verified
2772  anim_move('z', 2, 1, mesh, color, sock);
2773  anim_move('x', 3, 2, mesh, color, sock);
2774  anim_move('z', 2, 3, mesh, color, sock);
2775  anim_move('x', 3, 2, mesh, color, sock);
2776  break;
2777  }
2778  }
2779  else
2780  {
2781  switch (i9)
2782  {
2783  case 0: // Verified
2784  anim_move('z', 1, 2, mesh, color, sock);
2785  anim_move('y', 1, 3, mesh, color, sock);
2786  anim_move('z', 1, 1, mesh, color, sock);
2787  anim_move('y', 1, 1, mesh, color, sock);
2788  anim_move('x', 3, 1, mesh, color, sock);
2789  anim_move('y', 1, 1, mesh, color, sock);
2790  anim_move('x', 3, 3, mesh, color, sock);
2791  anim_move('y', 1, 3, mesh, color, sock);
2792  break;
2793  case 1: // Verified
2794  anim_move('z', 1, 3, mesh, color, sock);
2795  anim_move('y', 1, 3, mesh, color, sock);
2796  anim_move('z', 1, 1, mesh, color, sock);
2797  anim_move('y', 1, 1, mesh, color, sock);
2798  anim_move('x', 3, 1, mesh, color, sock);
2799  anim_move('y', 1, 1, mesh, color, sock);
2800  anim_move('x', 3, 3, mesh, color, sock);
2801  anim_move('y', 1, 3, mesh, color, sock);
2802  break;
2803  case 2: // Verified
2804  anim_move('z', 1, 3, mesh, color, sock);
2805  anim_move('x', 3, 3, mesh, color, sock);
2806  anim_move('z', 1, 3, mesh, color, sock);
2807  anim_move('x', 3, 1, mesh, color, sock);
2808  anim_move('y', 1, 1, mesh, color, sock);
2809  anim_move('x', 3, 1, mesh, color, sock);
2810  anim_move('y', 1, 3, mesh, color, sock);
2811  anim_move('x', 3, 3, mesh, color, sock);
2812  break;
2813  case 3: // Verified
2814  anim_move('x', 3, 3, mesh, color, sock);
2815  anim_move('z', 1, 3, mesh, color, sock);
2816  anim_move('x', 3, 1, mesh, color, sock);
2817  anim_move('y', 1, 1, mesh, color, sock);
2818  anim_move('x', 3, 1, mesh, color, sock);
2819  anim_move('y', 1, 3, mesh, color, sock);
2820  anim_move('x', 3, 3, mesh, color, sock);
2821  break;
2822  case 9: // Verified
2823  anim_move('x', 3, 3, mesh, color, sock);
2824  anim_move('z', 1, 3, mesh, color, sock);
2825  anim_move('x', 3, 1, mesh, color, sock);
2826  anim_move('y', 1, 1, mesh, color, sock);
2827  anim_move('x', 3, 1, mesh, color, sock);
2828  anim_move('y', 1, 3, mesh, color, sock);
2829  anim_move('x', 3, 3, mesh, color, sock);
2830  anim_move('z', 1, 3, mesh, color, sock);
2831  anim_move('x', 3, 3, mesh, color, sock);
2832  anim_move('z', 1, 3, mesh, color, sock);
2833  anim_move('x', 3, 1, mesh, color, sock);
2834  anim_move('y', 1, 1, mesh, color, sock);
2835  anim_move('x', 3, 1, mesh, color, sock);
2836  anim_move('y', 1, 3, mesh, color, sock);
2837  anim_move('x', 3, 3, mesh, color, sock);
2838  break;
2839  case 10: // Verified
2840  anim_move('x', 3, 2, mesh, color, sock);
2841  anim_move('z', 1, 2, mesh, color, sock);
2842  anim_move('x', 3, 2, mesh, color, sock);
2843  anim_move('z', 1, 2, mesh, color, sock);
2844  anim_move('x', 3, 2, mesh, color, sock);
2845  break;
2846  case 11: // Verified
2847  anim_move('y', 3, 1, mesh, color, sock);
2848  permute_edges(mesh, color, sock, true);
2849  anim_move('y', 3, 3, mesh, color, sock);
2850  anim_move('z', 1, 3, mesh, color, sock);
2851  anim_move('y', 1, 3, mesh, color, sock);
2852  permute_edges(mesh, color, sock, false);
2853  anim_move('y', 1, 1, mesh, color, sock);
2854  break;
2855  }
2856  }
2857 }
2858 
2859 void
2860 move_to_e10(int i10, int o10,
2861  Mesh & mesh, GridFunction & color, socketstream & sock)
2862 {
2863  if (o10 == 0)
2864  {
2865  switch (i10)
2866  {
2867  case 0: // Verified
2868  anim_move('y', 3, 3, mesh, color, sock);
2869  anim_move('z', 1, 3, mesh, color, sock);
2870  anim_move('y', 3, 1, mesh, color, sock);
2871  anim_move('x', 3, 3, mesh, color, sock);
2872  anim_move('y', 3, 1, mesh, color, sock);
2873  anim_move('x', 3, 1, mesh, color, sock);
2874  anim_move('y', 3, 3, mesh, color, sock);
2875  break;
2876  case 1: // Verified
2877  anim_move('z', 1, 1, mesh, color, sock);
2878  anim_move('y', 3, 3, mesh, color, sock);
2879  anim_move('z', 1, 3, mesh, color, sock);
2880  anim_move('y', 3, 1, mesh, color, sock);
2881  anim_move('x', 3, 3, mesh, color, sock);
2882  anim_move('y', 3, 1, mesh, color, sock);
2883  anim_move('x', 3, 1, mesh, color, sock);
2884  anim_move('y', 3, 3, mesh, color, sock);
2885  break;
2886  case 2: // Verified
2887  anim_move('z', 1, 3, mesh, color, sock);
2888  anim_move('x', 3, 1, mesh, color, sock);
2889  anim_move('z', 1, 1, mesh, color, sock);
2890  anim_move('x', 3, 3, mesh, color, sock);
2891  anim_move('y', 3, 1, mesh, color, sock);
2892  anim_move('x', 3, 3, mesh, color, sock);
2893  anim_move('y', 3, 3, mesh, color, sock);
2894  anim_move('x', 3, 1, mesh, color, sock);
2895  break;
2896  case 3: // Verified
2897  anim_move('x', 3, 1, mesh, color, sock);
2898  anim_move('z', 1, 1, mesh, color, sock);
2899  anim_move('x', 3, 3, mesh, color, sock);
2900  anim_move('y', 3, 1, mesh, color, sock);
2901  anim_move('x', 3, 3, mesh, color, sock);
2902  anim_move('y', 3, 3, mesh, color, sock);
2903  anim_move('x', 3, 1, mesh, color, sock);
2904  break;
2905  case 11: // Verified
2906  anim_move('y', 3, 1, mesh, color, sock);
2907  permute_edges(mesh, color, sock, true);
2908  anim_move('y', 3, 3, mesh, color, sock);
2909  anim_move('z', 1, 1, mesh, color, sock);
2910  anim_move('y', 3, 3, mesh, color, sock);
2911  permute_edges(mesh, color, sock, true);
2912  anim_move('y', 3, 1, mesh, color, sock);
2913  break;
2914  }
2915  }
2916  else
2917  {
2918  switch (i10)
2919  {
2920  case 0: // Verified
2921  anim_move('z', 1, 1, mesh, color, sock);
2922  anim_move('x', 3, 1, mesh, color, sock);
2923  anim_move('z', 1, 1, mesh, color, sock);
2924  anim_move('x', 3, 3, mesh, color, sock);
2925  anim_move('y', 3, 1, mesh, color, sock);
2926  anim_move('x', 3, 3, mesh, color, sock);
2927  anim_move('y', 3, 3, mesh, color, sock);
2928  anim_move('x', 3, 1, mesh, color, sock);
2929  break;
2930  case 1: // Verified
2931  anim_move('z', 1, 2, mesh, color, sock);
2932  anim_move('x', 3, 1, mesh, color, sock);
2933  anim_move('z', 1, 1, mesh, color, sock);
2934  anim_move('x', 3, 3, mesh, color, sock);
2935  anim_move('y', 3, 1, mesh, color, sock);
2936  anim_move('x', 3, 3, mesh, color, sock);
2937  anim_move('y', 3, 3, mesh, color, sock);
2938  anim_move('x', 3, 1, mesh, color, sock);
2939  break;
2940  case 2: // Verified
2941  anim_move('z', 1, 2, mesh, color, sock);
2942  anim_move('y', 3, 3, mesh, color, sock);
2943  anim_move('z', 1, 3, mesh, color, sock);
2944  anim_move('y', 3, 1, mesh, color, sock);
2945  anim_move('x', 3, 3, mesh, color, sock);
2946  anim_move('y', 3, 1, mesh, color, sock);
2947  anim_move('x', 3, 1, mesh, color, sock);
2948  anim_move('y', 3, 3, mesh, color, sock);
2949  break;
2950  case 3: // Verified
2951  anim_move('z', 1, 3, mesh, color, sock);
2952  anim_move('y', 3, 3, mesh, color, sock);
2953  anim_move('z', 1, 3, mesh, color, sock);
2954  anim_move('y', 3, 1, mesh, color, sock);
2955  anim_move('x', 3, 3, mesh, color, sock);
2956  anim_move('y', 3, 1, mesh, color, sock);
2957  anim_move('x', 3, 1, mesh, color, sock);
2958  anim_move('y', 3, 3, mesh, color, sock);
2959  break;
2960  case 10: // Verified
2961  anim_move('x', 3, 1, mesh, color, sock);
2962  anim_move('z', 1, 1, mesh, color, sock);
2963  anim_move('x', 3, 3, mesh, color, sock);
2964  anim_move('y', 3, 1, mesh, color, sock);
2965  anim_move('x', 3, 3, mesh, color, sock);
2966  anim_move('y', 3, 3, mesh, color, sock);
2967  anim_move('x', 3, 1, mesh, color, sock);
2968  anim_move('z', 1, 1, mesh, color, sock);
2969  anim_move('x', 3, 1, mesh, color, sock);
2970  anim_move('z', 1, 1, mesh, color, sock);
2971  anim_move('x', 3, 3, mesh, color, sock);
2972  anim_move('y', 3, 1, mesh, color, sock);
2973  anim_move('x', 3, 3, mesh, color, sock);
2974  anim_move('y', 3, 3, mesh, color, sock);
2975  anim_move('x', 3, 1, mesh, color, sock);
2976  break;
2977  case 11: // Verified
2978  anim_move('y', 3, 2, mesh, color, sock);
2979  anim_move('z', 1, 2, mesh, color, sock);
2980  anim_move('y', 3, 2, mesh, color, sock);
2981  anim_move('z', 1, 2, mesh, color, sock);
2982  anim_move('y', 3, 2, mesh, color, sock);
2983  break;
2984  }
2985  }
2986 }
2987 
2988 void
2989 move_to_e11(int i11, int o11,
2990  Mesh & mesh, GridFunction & color, socketstream & sock)
2991 {
2992  if (o11 == 0)
2993  {
2994  switch (i11)
2995  {
2996  case 0: // Verified
2997  anim_move('z', 1, 3, mesh, color, sock);
2998  anim_move('x', 1, 1, mesh, color, sock);
2999  anim_move('z', 1, 3, mesh, color, sock);
3000  anim_move('x', 1, 3, mesh, color, sock);
3001  anim_move('y', 3, 3, mesh, color, sock);
3002  anim_move('x', 1, 3, mesh, color, sock);
3003  anim_move('y', 3, 1, mesh, color, sock);
3004  anim_move('x', 1, 1, mesh, color, sock);
3005  break;
3006  case 1: // Verified
3007  anim_move('x', 1, 1, mesh, color, sock);
3008  anim_move('z', 1, 3, mesh, color, sock);
3009  anim_move('x', 1, 3, mesh, color, sock);
3010  anim_move('y', 3, 3, mesh, color, sock);
3011  anim_move('x', 1, 3, mesh, color, sock);
3012  anim_move('y', 3, 1, mesh, color, sock);
3013  anim_move('x', 1, 1, mesh, color, sock);
3014  break;
3015  case 2: // Verified
3016  anim_move('z', 1, 2, mesh, color, sock);
3017  anim_move('y', 3, 1, mesh, color, sock);
3018  anim_move('z', 1, 1, mesh, color, sock);
3019  anim_move('y', 3, 3, mesh, color, sock);
3020  anim_move('x', 1, 3, mesh, color, sock);
3021  anim_move('y', 3, 3, mesh, color, sock);
3022  anim_move('x', 1, 1, mesh, color, sock);
3023  anim_move('y', 3, 1, mesh, color, sock);
3024  break;
3025  case 3: // Verified
3026  anim_move('z', 1, 3, mesh, color, sock);
3027  anim_move('y', 3, 1, mesh, color, sock);
3028  anim_move('z', 1, 1, mesh, color, sock);
3029  anim_move('y', 3, 3, mesh, color, sock);
3030  anim_move('x', 1, 3, mesh, color, sock);
3031  anim_move('y', 3, 3, mesh, color, sock);
3032  anim_move('x', 1, 1, mesh, color, sock);
3033  anim_move('y', 3, 1, mesh, color, sock);
3034  break;
3035  }
3036  }
3037  else
3038  {
3039  switch (i11)
3040  {
3041  case 0: // Verified
3042  anim_move('y', 3, 1, mesh, color, sock);
3043  anim_move('z', 1, 1, mesh, color, sock);
3044  anim_move('y', 3, 3, mesh, color, sock);
3045  anim_move('x', 1, 3, mesh, color, sock);
3046  anim_move('y', 3, 3, mesh, color, sock);
3047  anim_move('x', 1, 1, mesh, color, sock);
3048  anim_move('y', 3, 1, mesh, color, sock);
3049  break;
3050  case 1: // Verified
3051  anim_move('z', 1, 1, mesh, color, sock);
3052  anim_move('y', 3, 1, mesh, color, sock);
3053  anim_move('z', 1, 1, mesh, color, sock);
3054  anim_move('y', 3, 3, mesh, color, sock);
3055  anim_move('x', 1, 3, mesh, color, sock);
3056  anim_move('y', 3, 3, mesh, color, sock);
3057  anim_move('x', 1, 1, mesh, color, sock);
3058  anim_move('y', 3, 1, mesh, color, sock);
3059  break;
3060  case 2: // Verified
3061  anim_move('z', 1, 1, mesh, color, sock);
3062  anim_move('x', 1, 1, mesh, color, sock);
3063  anim_move('z', 1, 3, mesh, color, sock);
3064  anim_move('x', 1, 3, mesh, color, sock);
3065  anim_move('y', 3, 3, mesh, color, sock);
3066  anim_move('x', 1, 3, mesh, color, sock);
3067  anim_move('y', 3, 1, mesh, color, sock);
3068  anim_move('x', 1, 1, mesh, color, sock);
3069  break;
3070  case 3: // Verified
3071  anim_move('z', 1, 2, mesh, color, sock);
3072  anim_move('x', 1, 1, mesh, color, sock);
3073  anim_move('z', 1, 3, mesh, color, sock);
3074  anim_move('x', 1, 3, mesh, color, sock);
3075  anim_move('y', 3, 3, mesh, color, sock);
3076  anim_move('x', 1, 3, mesh, color, sock);
3077  anim_move('y', 3, 1, mesh, color, sock);
3078  anim_move('x', 1, 1, mesh, color, sock);
3079  break;
3080  case 11: // Verified
3081  anim_move('x', 1, 1, mesh, color, sock);
3082  anim_move('z', 1, 3, mesh, color, sock);
3083  anim_move('x', 1, 3, mesh, color, sock);
3084  anim_move('y', 3, 3, mesh, color, sock);
3085  anim_move('x', 1, 3, mesh, color, sock);
3086  anim_move('y', 3, 1, mesh, color, sock);
3087  anim_move('x', 1, 1, mesh, color, sock);
3088  anim_move('z', 1, 3, mesh, color, sock);
3089  anim_move('x', 1, 1, mesh, color, sock);
3090  anim_move('z', 1, 3, mesh, color, sock);
3091  anim_move('x', 1, 3, mesh, color, sock);
3092  anim_move('y', 3, 3, mesh, color, sock);
3093  anim_move('x', 1, 3, mesh, color, sock);
3094  anim_move('y', 3, 1, mesh, color, sock);
3095  anim_move('x', 1, 1, mesh, color, sock);
3096  break;
3097  }
3098  }
3099 }
3100 
3101 void
3103 {
3104  if (logging_ > 1)
3105  {
3106  cout << "Entering solve_top_edges" << endl;
3107  }
3108  if (logging_ > 2)
3109  {
3110  print_state(cout);
3111  }
3112 
3113  // Locate fourth edge in the top tier
3114  {
3115  int l4 = locate_edge(4);
3116  int i4 = max(l4,-1-l4);
3117  int o4 = (l4 >= 0) ? 0 : 1;
3118  if (logging_ > 1)
3119  {
3120  cout << "Location of 4-th edge: " << i4
3121  << " with orientation " << o4 << endl;
3122  }
3123  if (i4 < 12 && ((i4 < 4) ||
3124  (i4 > 4 && o4 == 0) ||
3125  (o4 == 1) ))
3126  {
3127  move_to_e4(i4, o4, mesh, color, sock);
3128  }
3129  }
3130 
3131  // Locate fifth edge in the top tier
3132  {
3133  int l5 = locate_edge(5);
3134  int i5 = max(l5,-1-l5);
3135  int o5 = (l5 >= 0) ? 0 : 1;
3136  if (logging_ > 1)
3137  {
3138  cout << "Location of 5-th edge: " << i5
3139  << " with orientation " << o5 << endl;
3140  }
3141  if (i5 < 12 && ((i5 < 4) ||
3142  (i5 > 5 && o5 == 0) ||
3143  (i5 > 4 && o5 == 1) ))
3144  {
3145  move_to_e5(i5, o5, mesh, color, sock);
3146  }
3147  }
3148 
3149  // Locate sixth edge in the top tier
3150  {
3151  int l6 = locate_edge(6);
3152  int i6 = max(l6,-1-l6);
3153  int o6 = (l6 >= 0) ? 0 : 1;
3154  if (logging_ > 1)
3155  {
3156  cout << "Location of 6-th edge: " << i6
3157  << " with orientation " << o6 << endl;
3158  }
3159  if (i6 < 12 && ((i6 < 4) ||
3160  (i6 > 6 && o6 == 0) ||
3161  (i6 > 5 && o6 == 1) ))
3162  {
3163  move_to_e6(i6, o6, mesh, color, sock);
3164  }
3165  }
3166 
3167  // Locate seventh edge in the top tier
3168  {
3169  int l7 = locate_edge(7);
3170  int i7 = max(l7,-1-l7);
3171  int o7 = (l7 >= 0) ? 0 : 1;
3172  if (logging_ > 1)
3173  {
3174  cout << "Location of 7-th edge: " << i7
3175  << " with orientation " << o7 << endl;
3176  }
3177  if (i7 < 12 && ((i7 < 4) ||
3178  (i7 > 7 && o7 == 0) ||
3179  (i7 > 6 && o7 == 1) ))
3180  {
3181  move_to_e7(i7, o7, mesh, color, sock);
3182  }
3183  }
3184 }
3185 
3186 void
3188 {
3189  if (logging_ > 1)
3190  {
3191  cout << "Entering solve_mid_edges" << endl;
3192  }
3193  if (logging_ > 2)
3194  {
3195  print_state(cout);
3196  }
3197 
3198  // Locate eighth edge
3199  {
3200  int l8 = locate_edge(8);
3201  int i8 = max(l8,-1-l8);
3202  int o8 = (l8 >= 0) ? 0 : 1;
3203  if (logging_ > 1)
3204  {
3205  cout << "Location of 8-th edge: " << i8
3206  << " with orientation " << o8 << endl;
3207  }
3208  if (i8 >= 4 && i8 < 8)
3209  {
3210  cout << "Moving edges from top tier to middle tier is not supported."
3211  << endl;
3212  }
3213  else if (i8 < 12 && ((i8 < 4) ||
3214  (i8 > 8 && o8 == 0) ||
3215  (i8 > 7 && o8 == 1) ))
3216  {
3217  move_to_e8(i8, o8, mesh, color, sock);
3218  }
3219  }
3220 
3221  // Locate ninth edge
3222  {
3223  int l9 = locate_edge(9);
3224  int i9 = max(l9,-1-l9);
3225  int o9 = (l9 >= 0) ? 0 : 1;
3226  if (logging_ > 1)
3227  {
3228  cout << "Location of 9-th edge: " << i9
3229  << " with orientation " << o9 << endl;
3230  }
3231  if (i9 >= 4 && i9 < 8)
3232  {
3233  cout << "Moving edges from top tier to middle tier is not supported."
3234  << endl;
3235  }
3236  else if (i9 < 12 && ((i9 < 4) ||
3237  (i9 > 9 && o9 == 0) ||
3238  (i9 > 8 && o9 == 1) ))
3239  {
3240  move_to_e9(i9, o9, mesh, color, sock);
3241  }
3242  }
3243 
3244  // Locate tenth edge
3245  {
3246  int l10 = locate_edge(10);
3247  int i10 = max(l10,-1-l10);
3248  int o10 = (l10 >= 0) ? 0 : 1;
3249  if (logging_ > 1)
3250  {
3251  cout << "Location of 10-th edge: " << i10
3252  << " with orientation " << o10 << endl;
3253  }
3254  if (i10 >= 4 && i10 < 8)
3255  {
3256  cout << "Moving edges from top tier to middle tier is not supported."
3257  << endl;
3258  }
3259  else if (i10 < 12 && ((i10 < 4) ||
3260  (i10 > 10 && o10 == 0) ||
3261  (i10 > 9 && o10 == 1) ))
3262  {
3263  move_to_e10(i10, o10, mesh, color, sock);
3264  }
3265  }
3266 
3267  // Locate eleventh edge
3268  {
3269  int l11 = locate_edge(11);
3270  int i11 = max(l11,-1-l11);
3271  int o11 = (l11 >= 0) ? 0 : 1;
3272  if (logging_ > 1)
3273  {
3274  cout << "Location of 11-th edge: " << i11
3275  << " with orientation " << o11 << endl;
3276  }
3277  if (i11 >= 4 && i11 < 8)
3278  {
3279  cout << "Moving edges from top tier to middle tier is not supported."
3280  << endl;
3281  }
3282  else if (i11 < 12 && ((i11 < 4) ||
3283  (i11 > 11 && o11 == 0) ||
3284  (i11 > 10 && o11 == 1) ))
3285  {
3286  move_to_e11(i11, o11, mesh, color, sock);
3287  }
3288  }
3289 }
3290 
3291 void
3292 swap_corners(Mesh & mesh, GridFunction & color, socketstream & sock,
3293  int * c0, int * c1)
3294 {
3295  if (logging_ > 1)
3296  {
3297  cout << "Entering swap_corners" << endl;
3298  }
3299 
3300  if (c0 != NULL)
3301  {
3302  // Locate first incorrectly filled corner location
3303  int i0 = -1;
3304  for (int i=0; i<8; i++)
3305  {
3306  if ((rubik.corn_[3 * i] == c0[0] &&
3307  rubik.corn_[3 * i + 1] == c0[1] &&
3308  rubik.corn_[3 * i + 2] == c0[2]) ||
3309  (rubik.corn_[3 * i] == c0[1] &&
3310  rubik.corn_[3 * i + 1] == c0[2] &&
3311  rubik.corn_[3 * i + 2] == c0[0]) ||
3312  (rubik.corn_[3 * i] == c0[2] &&
3313  rubik.corn_[3 * i + 1] == c0[0] &&
3314  rubik.corn_[3 * i + 2] == c0[1]) ||
3315  (rubik.corn_[3 * i] == c0[2] &&
3316  rubik.corn_[3 * i + 1] == c0[1] &&
3317  rubik.corn_[3 * i + 2] == c0[0]) ||
3318  (rubik.corn_[3 * i] == c0[1] &&
3319  rubik.corn_[3 * i + 1] == c0[0] &&
3320  rubik.corn_[3 * i + 2] == c0[2]) ||
3321  (rubik.corn_[3 * i] == c0[0] &&
3322  rubik.corn_[3 * i + 1] == c0[2] &&
3323  rubik.corn_[3 * i + 2] == c0[1]))
3324  {
3325  i0 = i;
3326  break;
3327  }
3328  }
3329  if (logging_ > 1)
3330  {
3331  cout << "Location of c0 = {"<<c0[0]<<","<<c0[1]<<","<<c0[2]<<"}: "
3332  << i0 << endl;
3333  }
3334 
3335  switch (i0)
3336  {
3337  case 0:
3338  swap_corners(mesh, color, sock, NULL, c1);
3339  break;
3340  case 1:
3341  case 2:
3342  case 3:
3343  anim_move('z', 1, i0, mesh, color, sock);
3344  swap_corners(mesh, color, sock, NULL, c1);
3345  anim_move('z', 1, 4-i0, mesh, color, sock);
3346  break;
3347  case 4:
3348  anim_move('x', 1, 3, mesh, color, sock);
3349  swap_corners(mesh, color, sock, NULL, c1);
3350  anim_move('x', 1, 1, mesh, color, sock);
3351  break;
3352  case 5:
3353  anim_move('y', 1, 2, mesh, color, sock);
3354  swap_corners(mesh, color, sock, NULL, c1);
3355  anim_move('y', 1, 2, mesh, color, sock);
3356  break;
3357  case 6:
3358  anim_move('z', 3, 2, mesh, color, sock);
3359  anim_move('x', 1, 3, mesh, color, sock);
3360  swap_corners(mesh, color, sock, NULL, c1);
3361  anim_move('x', 1, 1, mesh, color, sock);
3362  anim_move('z', 3, 2, mesh, color, sock);
3363  break;
3364  case 7:
3365  anim_move('x', 1, 2, mesh, color, sock);
3366  swap_corners(mesh, color, sock, NULL, c1);
3367  anim_move('x', 1, 2, mesh, color, sock);
3368  break;
3369  }
3370  }
3371  else if (c1 != NULL)
3372  {
3373  // Locate corner piece which belongs at i0
3374  int i1 = -1;
3375  for (int i=1; i<8; i++)
3376  {
3377  if ((rubik.corn_[3 * i] == c1[0] &&
3378  rubik.corn_[3 * i + 1] == c1[1] &&
3379  rubik.corn_[3 * i + 2] == c1[2]) ||
3380  (rubik.corn_[3 * i] == c1[1] &&
3381  rubik.corn_[3 * i + 1] == c1[2] &&
3382  rubik.corn_[3 * i + 2] == c1[0]) ||
3383  (rubik.corn_[3 * i] == c1[2] &&
3384  rubik.corn_[3 * i + 1] == c1[0] &&
3385  rubik.corn_[3 * i + 2] == c1[1]) ||
3386  (rubik.corn_[3 * i] == c1[2] &&
3387  rubik.corn_[3 * i + 1] == c1[1] &&
3388  rubik.corn_[3 * i + 2] == c1[0]) ||
3389  (rubik.corn_[3 * i] == c1[1] &&
3390  rubik.corn_[3 * i + 1] == c1[0] &&
3391  rubik.corn_[3 * i + 2] == c1[2]) ||
3392  (rubik.corn_[3 * i] == c1[0] &&
3393  rubik.corn_[3 * i + 1] == c1[2] &&
3394  rubik.corn_[3 * i + 2] == c1[1]))
3395  {
3396  i1 = i;
3397  break;
3398  }
3399  }
3400  if (logging_ > 1)
3401  {
3402  cout << "Location of piece belonging at " << 0 << " (c1) is "
3403  << i1 << endl;
3404  }
3405 
3406  switch (i1)
3407  {
3408  case 1:
3409  swap_corners(mesh, color, sock, NULL, NULL);
3410  break;
3411  case 2:
3412  anim_move('x', 3, 1, mesh, color, sock);
3413  swap_corners(mesh, color, sock, NULL, NULL);
3414  anim_move('x', 3, 3, mesh, color, sock);
3415  break;
3416  case 3:
3417  anim_move('y', 3, 1, mesh, color, sock);
3418  anim_move('x', 3, 1, mesh, color, sock);
3419  swap_corners(mesh, color, sock, NULL, NULL);
3420  anim_move('x', 3, 3, mesh, color, sock);
3421  anim_move('y', 3, 3, mesh, color, sock);
3422  break;
3423  case 4:
3424  anim_move('z', 3, 3, mesh, color, sock);
3425  anim_move('x', 3, 3, mesh, color, sock);
3426  swap_corners(mesh, color, sock, NULL, NULL);
3427  anim_move('x', 3, 1, mesh, color, sock);
3428  anim_move('z', 3, 1, mesh, color, sock);
3429  break;
3430  case 5:
3431  anim_move('x', 3, 3, mesh, color, sock);
3432  swap_corners(mesh, color, sock, NULL, NULL);
3433  anim_move('x', 3, 1, mesh, color, sock);
3434  break;
3435  case 6:
3436  anim_move('x', 3, 2, mesh, color, sock);
3437  swap_corners(mesh, color, sock, NULL, NULL);
3438  anim_move('x', 3, 2, mesh, color, sock);
3439  break;
3440  case 7:
3441  anim_move('z', 3, 2, mesh, color, sock);
3442  anim_move('x', 3, 3, mesh, color, sock);
3443  swap_corners(mesh, color, sock, NULL, NULL);
3444  anim_move('x', 3, 1, mesh, color, sock);
3445  anim_move('z', 3, 2, mesh, color, sock);
3446  break;
3447  }
3448  }
3449  else
3450  {
3451  anim_move('x', 3, 3, mesh, color, sock);
3452  anim_move('z', 1, 1, mesh, color, sock);
3453  anim_move('x', 3, 1, mesh, color, sock);
3454  anim_move('y', 1, 3, mesh, color, sock);
3455  anim_move('z', 1, 3, mesh, color, sock);
3456  anim_move('y', 1, 1, mesh, color, sock);
3457  anim_move('x', 3, 3, mesh, color, sock);
3458  anim_move('z', 1, 3, mesh, color, sock);
3459  anim_move('x', 3, 1, mesh, color, sock);
3460  anim_move('z', 1, 2, mesh, color, sock);
3461  }
3462 }
3463 
3464 void
3466 {
3467  if (logging_ > 1)
3468  {
3469  cout << "Entering solve_corner_locations" << endl;
3470  }
3471  if (logging_ > 2)
3472  {
3473  print_state(cout);
3474  }
3475 
3476  // Locate first incorrectly filled corner location
3477  int i0 = -1;
3478  for (int i=0; i<8; i++)
3479  {
3480  if (!((rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 0] &&
3481  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 1] &&
3482  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 2]) ||
3483  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 1] &&
3484  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 2] &&
3485  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 0]) ||
3486  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 2] &&
3487  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 0] &&
3488  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 1]) ||
3489  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 2] &&
3490  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 1] &&
3491  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 0]) ||
3492  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 1] &&
3493  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 0] &&
3494  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 2]) ||
3495  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 0] &&
3496  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 2] &&
3497  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 1])))
3498  {
3499  i0 = i;
3500  break;
3501  }
3502  }
3503  if (logging_ > 1)
3504  {
3505  cout << "First incorrectly filled corner location: " << i0 << endl;
3506  }
3507 
3508  if (i0 < 0) { return; }
3509 
3510  // Locate corner piece which belongs at i0
3511  int l1 = locate_corner(i0);
3512  int i1 = l1 % 8;
3513  if (logging_ > 1)
3514  {
3515  cout << "Location of piece belonging at " << i0 << " is " << i1 << endl;
3516  }
3517 
3518  if (i1 < 0)
3519  {
3520  cout << "Invalid configuration of corners" << endl;
3521  return;
3522  }
3523 
3524  int c0[3] = {rubik.corn_[3 * i0],
3525  rubik.corn_[3 * i0 + 1],
3526  rubik.corn_[3 * i0 + 2]
3527  };
3528  int c1[3] = {rubik.corn_[3 * i1],
3529  rubik.corn_[3 * i1 + 1],
3530  rubik.corn_[3 * i1 + 2]
3531  };
3532 
3533  swap_corners(mesh, color, sock, c0, c1);
3534 
3535  solve_corner_locations(mesh, color, sock);
3536 }
3537 
3538 void
3540  socketstream & sock)
3541 {
3542  if (logging_ > 1)
3543  {
3544  cout << "Entering solve_bot_corner_locations" << endl;
3545  }
3546  if (logging_ > 2)
3547  {
3548  print_state(cout);
3549  }
3550 
3551  // Locate first corner in the bottom tier
3552  {
3553  int l0 = locate_corner(0);
3554  int i0 = l0 % 8;
3555  if (logging_ > 1)
3556  {
3557  cout << "Location of piece belonging at 0 is " << i0 << endl;
3558  }
3559  if (i0 != 0)
3560  {
3561  anim_move('z', 1, i0, mesh, color, sock);
3562  }
3563  }
3564 
3565  // Locate second corner in bottom tier
3566  {
3567  int l1 = locate_corner(1);
3568  int i1 = l1 % 8;
3569  if (logging_ > 1)
3570  {
3571  cout << "Location of piece belonging at 1 is " << i1 << endl;
3572  }
3573 
3574  if (i1 < 0)
3575  {
3576  cout << "Invalid configuration of corners" << endl;
3577  }
3578 
3579  switch (i1)
3580  {
3581  case 2:
3582  anim_move('y', 3, 3, mesh, color, sock);
3583  anim_move('z', 1, 1, mesh, color, sock);
3584  anim_move('y', 3, 1, mesh, color, sock);
3585  anim_move('x', 3, 1, mesh, color, sock);
3586  anim_move('z', 1, 3, mesh, color, sock);
3587  anim_move('x', 3, 3, mesh, color, sock);
3588  anim_move('y', 3, 3, mesh, color, sock);
3589  anim_move('z', 1, 3, mesh, color, sock);
3590  anim_move('y', 3, 1, mesh, color, sock);
3591  anim_move('z', 1, 2, mesh, color, sock);
3592  break;
3593  case 3:
3594  anim_move('y', 3, 3, mesh, color, sock);
3595  anim_move('z', 1, 1, mesh, color, sock);
3596  anim_move('y', 3, 1, mesh, color, sock);
3597  anim_move('x', 3, 1, mesh, color, sock);
3598  anim_move('z', 1, 2, mesh, color, sock);
3599  anim_move('x', 3, 3, mesh, color, sock);
3600  anim_move('y', 3, 3, mesh, color, sock);
3601  anim_move('z', 1, 3, mesh, color, sock);
3602  anim_move('y', 3, 1, mesh, color, sock);
3603  anim_move('z', 1, 3, mesh, color, sock);
3604  break;
3605  }
3606  }
3607 
3608  // Locate second corner in bottom tier
3609  {
3610  int l2 = locate_corner(2);
3611  int i2 = l2 % 8;
3612  if (logging_ > 1)
3613  {
3614  cout << "Location of piece belonging at 2 is " << i2 << endl;
3615  }
3616 
3617  if (i2 < 0)
3618  {
3619  cout << "Invalid configuration of corners" << endl;
3620  }
3621 
3622  if (i2 == 3)
3623  {
3624  anim_move('x', 1, 1, mesh, color, sock);
3625  anim_move('z', 1, 1, mesh, color, sock);
3626  anim_move('x', 1, 3, mesh, color, sock);
3627  anim_move('y', 3, 1, mesh, color, sock);
3628  anim_move('z', 1, 3, mesh, color, sock);
3629  anim_move('y', 3, 3, mesh, color, sock);
3630  anim_move('x', 1, 1, mesh, color, sock);
3631  anim_move('z', 1, 3, mesh, color, sock);
3632  anim_move('x', 1, 3, mesh, color, sock);
3633  anim_move('z', 1, 2, mesh, color, sock);
3634  }
3635  }
3636 }
3637 
3638 void
3640  bool cw, int * c0, int * c1, int * c2)
3641 {
3642  if (c0 != NULL)
3643  {
3644  // Locate corner corresponding to c0
3645  int i0 = -1;
3646  for (int i=0; i<8; i++)
3647  {
3648  if ((rubik.corn_[3 * i] == c0[0] &&
3649  rubik.corn_[3 * i + 1] == c0[1] &&
3650  rubik.corn_[3 * i + 2] == c0[2]) ||
3651  (rubik.corn_[3 * i] == c0[1] &&
3652  rubik.corn_[3 * i + 1] == c0[2] &&
3653  rubik.corn_[3 * i + 2] == c0[0]) ||
3654  (rubik.corn_[3 * i] == c0[2] &&
3655  rubik.corn_[3 * i + 1] == c0[0] &&
3656  rubik.corn_[3 * i + 2] == c0[1]) ||
3657  (rubik.corn_[3 * i] == c0[2] &&
3658  rubik.corn_[3 * i + 1] == c0[1] &&
3659  rubik.corn_[3 * i + 2] == c0[0]) ||
3660  (rubik.corn_[3 * i] == c0[1] &&
3661  rubik.corn_[3 * i + 1] == c0[0] &&
3662  rubik.corn_[3 * i + 2] == c0[2]) ||
3663  (rubik.corn_[3 * i] == c0[0] &&
3664  rubik.corn_[3 * i + 1] == c0[2] &&
3665  rubik.corn_[3 * i + 2] == c0[1]))
3666  {
3667  i0 = i;
3668  break;
3669  }
3670  }
3671  if (logging_ > 1)
3672  {
3673  cout << "Location of c0 = {"<<c0[0]<<","<<c0[1]<<","<<c0[2]<<"}: "
3674  << i0 << endl;
3675  }
3676 
3677  switch (i0)
3678  {
3679  case 0:
3680  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3681  break;
3682  case 1:
3683  case 2:
3684  case 3:
3685  anim_move('z', 1, i0, mesh, color, sock);
3686  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3687  anim_move('z', 1, 4-i0, mesh, color, sock);
3688  break;
3689  case 4:
3690  anim_move('x', 1, 3, mesh, color, sock);
3691  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3692  anim_move('x', 1, 1, mesh, color, sock);
3693  break;
3694  case 5:
3695  anim_move('y', 1, 2, mesh, color, sock);
3696  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3697  anim_move('y', 1, 2, mesh, color, sock);
3698  break;
3699  case 6:
3700  anim_move('z', 3, 2, mesh, color, sock);
3701  anim_move('x', 1, 3, mesh, color, sock);
3702  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3703  anim_move('x', 1, 1, mesh, color, sock);
3704  anim_move('z', 3, 2, mesh, color, sock);
3705  break;
3706  case 7:
3707  anim_move('x', 1, 2, mesh, color, sock);
3708  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3709  anim_move('x', 1, 2, mesh, color, sock);
3710  break;
3711  }
3712 
3713  }
3714  else if (c1 != NULL)
3715  {
3716  // Locate corner piece corresponding to c1
3717  int i1 = -1;
3718  for (int i=1; i<8; i++)
3719  {
3720  if ((rubik.corn_[3 * i] == c1[0] &&
3721  rubik.corn_[3 * i + 1] == c1[1] &&
3722  rubik.corn_[3 * i + 2] == c1[2]) ||
3723  (rubik.corn_[3 * i] == c1[1] &&
3724  rubik.corn_[3 * i + 1] == c1[2] &&
3725  rubik.corn_[3 * i + 2] == c1[0]) ||
3726  (rubik.corn_[3 * i] == c1[2] &&
3727  rubik.corn_[3 * i + 1] == c1[0] &&
3728  rubik.corn_[3 * i + 2] == c1[1]) ||
3729  (rubik.corn_[3 * i] == c1[2] &&
3730  rubik.corn_[3 * i + 1] == c1[1] &&
3731  rubik.corn_[3 * i + 2] == c1[0]) ||
3732  (rubik.corn_[3 * i] == c1[1] &&
3733  rubik.corn_[3 * i + 1] == c1[0] &&
3734  rubik.corn_[3 * i + 2] == c1[2]) ||
3735  (rubik.corn_[3 * i] == c1[0] &&
3736  rubik.corn_[3 * i + 1] == c1[2] &&
3737  rubik.corn_[3 * i + 2] == c1[1]))
3738  {
3739  i1 = i;
3740  break;
3741  }
3742  }
3743  if (logging_ > 1)
3744  {
3745  cout << "Location of c1 = {"<<c1[0]<<","<<c1[1]<<","<<c1[2]<<"}: "
3746  << i1 << endl;
3747  }
3748 
3749  if (c2 != NULL)
3750  {
3751  switch (i1)
3752  {
3753  case 1:
3754  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3755  break;
3756  case 2:
3757  anim_move('x', 3, 1, mesh, color, sock);
3758  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3759  anim_move('x', 3, 3, mesh, color, sock);
3760  break;
3761  case 3:
3762  anim_move('y', 3, 1, mesh, color, sock);
3763  anim_move('x', 3, 1, mesh, color, sock);
3764  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3765  anim_move('x', 3, 3, mesh, color, sock);
3766  anim_move('y', 3, 3, mesh, color, sock);
3767  break;
3768  case 4:
3769  anim_move('z', 3, 3, mesh, color, sock);
3770  anim_move('x', 3, 3, mesh, color, sock);
3771  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3772  anim_move('x', 3, 1, mesh, color, sock);
3773  anim_move('z', 3, 1, mesh, color, sock);
3774  break;
3775  case 5:
3776  anim_move('x', 3, 3, mesh, color, sock);
3777  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3778  anim_move('x', 3, 1, mesh, color, sock);
3779  break;
3780  case 6:
3781  anim_move('x', 3, 2, mesh, color, sock);
3782  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3783  anim_move('x', 3, 2, mesh, color, sock);
3784  break;
3785  case 7:
3786  anim_move('z', 3, 2, mesh, color, sock);
3787  anim_move('x', 3, 3, mesh, color, sock);
3788  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3789  anim_move('x', 3, 1, mesh, color, sock);
3790  anim_move('z', 3, 2, mesh, color, sock);
3791  break;
3792  }
3793  }
3794  else
3795  {
3796  switch (i1)
3797  {
3798  case 3:
3799  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3800  break;
3801  case 2:
3802  anim_move('y', 3, 3, mesh, color, sock);
3803  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3804  anim_move('y', 3, 1, mesh, color, sock);
3805  break;
3806  case 1:
3807  anim_move('x', 3, 3, mesh, color, sock);
3808  anim_move('y', 3, 3, mesh, color, sock);
3809  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3810  anim_move('y', 3, 1, mesh, color, sock);
3811  anim_move('x', 3, 1, mesh, color, sock);
3812  break;
3813  case 4:
3814  anim_move('z', 3, 1, mesh, color, sock);
3815  anim_move('y', 3, 1, mesh, color, sock);
3816  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3817  anim_move('y', 3, 3, mesh, color, sock);
3818  anim_move('z', 3, 3, mesh, color, sock);
3819  break;
3820  case 5:
3821  anim_move('z', 3, 2, mesh, color, sock);
3822  anim_move('y', 3, 1, mesh, color, sock);
3823  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3824  anim_move('y', 3, 3, mesh, color, sock);
3825  anim_move('z', 3, 2, mesh, color, sock);
3826  break;
3827  case 6:
3828  anim_move('y', 3, 2, mesh, color, sock);
3829  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3830  anim_move('y', 3, 2, mesh, color, sock);
3831  break;
3832  case 7:
3833  anim_move('y', 3, 1, mesh, color, sock);
3834  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3835  anim_move('y', 3, 3, mesh, color, sock);
3836  break;
3837  }
3838  }
3839  }
3840  else if (c2 != NULL)
3841  {
3842  // Locate corner piece corresponding to c2
3843  int i2 = -1;
3844  for (int i=2; i<8; i++)
3845  {
3846  if ((rubik.corn_[3 * i] == c2[0] &&
3847  rubik.corn_[3 * i + 1] == c2[1] &&
3848  rubik.corn_[3 * i + 2] == c2[2]) ||
3849  (rubik.corn_[3 * i] == c2[1] &&
3850  rubik.corn_[3 * i + 1] == c2[2] &&
3851  rubik.corn_[3 * i + 2] == c2[0]) ||
3852  (rubik.corn_[3 * i] == c2[2] &&
3853  rubik.corn_[3 * i + 1] == c2[0] &&
3854  rubik.corn_[3 * i + 2] == c2[1]) ||
3855  (rubik.corn_[3 * i] == c2[2] &&
3856  rubik.corn_[3 * i + 1] == c2[1] &&
3857  rubik.corn_[3 * i + 2] == c2[0]) ||
3858  (rubik.corn_[3 * i] == c2[1] &&
3859  rubik.corn_[3 * i + 1] == c2[0] &&
3860  rubik.corn_[3 * i + 2] == c2[2]) ||
3861  (rubik.corn_[3 * i] == c2[0] &&
3862  rubik.corn_[3 * i + 1] == c2[2] &&
3863  rubik.corn_[3 * i + 2] == c2[1]))
3864  {
3865  i2 = i;
3866  break;
3867  }
3868  }
3869  if (logging_ > 1)
3870  {
3871  cout << "Location of c2 = {"<<c2[0]<<","<<c2[1]<<","<<c2[2]<<"}: "
3872  << i2 << endl;
3873  }
3874 
3875  switch (i2)
3876  {
3877  case 2:
3878  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3879  break;
3880  case 3:
3881  anim_move('y', 3, 1, mesh, color, sock);
3882  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3883  anim_move('y', 3, 3, mesh, color, sock);
3884  break;
3885  case 4:
3886  anim_move('z', 3, 2, mesh, color, sock);
3887  anim_move('y', 3, 3, mesh, color, sock);
3888  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3889  anim_move('y', 3, 1, mesh, color, sock);
3890  anim_move('z', 3, 2, mesh, color, sock);
3891  break;
3892  case 5:
3893  anim_move('z', 3, 3, mesh, color, sock);
3894  anim_move('y', 3, 3, mesh, color, sock);
3895  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3896  anim_move('y', 3, 1, mesh, color, sock);
3897  anim_move('z', 3, 1, mesh, color, sock);
3898  break;
3899  case 6:
3900  anim_move('y', 3, 3, mesh, color, sock);
3901  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3902  anim_move('y', 3, 1, mesh, color, sock);
3903  break;
3904  case 7:
3905  anim_move('y', 3, 2, mesh, color, sock);
3906  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3907  anim_move('y', 3, 2, mesh, color, sock);
3908  break;
3909  }
3910  }
3911  else
3912  {
3913  if (cw)
3914  {
3915  if (logging_ > 1)
3916  {
3917  cout << "twist_corners performing clockwise twist" << endl;
3918  }
3919  anim_move('x', 3, 1, mesh, color, sock);
3920  anim_move('z', 1, 3, mesh, color, sock);
3921  anim_move('x', 3, 3, mesh, color, sock);
3922  anim_move('z', 1, 3, mesh, color, sock);
3923  anim_move('x', 3, 1, mesh, color, sock);
3924  anim_move('z', 1, 2, mesh, color, sock);
3925  anim_move('x', 3, 3, mesh, color, sock);
3926  anim_move('z', 1, 2, mesh, color, sock);
3927  }
3928  else
3929  {
3930  if (logging_ > 1)
3931  {
3932  cout << "twist_corners performing counter-clockwise twist" << endl;
3933  }
3934  anim_move('y', 1, 1, mesh, color, sock);
3935  anim_move('z', 1, 1, mesh, color, sock);
3936  anim_move('y', 1, 3, mesh, color, sock);
3937  anim_move('z', 1, 1, mesh, color, sock);
3938  anim_move('y', 1, 1, mesh, color, sock);
3939  anim_move('z', 1, 2, mesh, color, sock);
3940  anim_move('y', 1, 3, mesh, color, sock);
3941  anim_move('z', 1, 2, mesh, color, sock);
3942  }
3943  }
3944 }
3945 
3946 void
3948  socketstream & sock)
3949 {
3950  if (logging_ > 1)
3951  {
3952  cout << "Entering solve_corner_orientations" << endl;
3953  }
3954  if (logging_ > 2)
3955  {
3956  print_state(cout);
3957  }
3958 
3959  // Locate first incorrectly oriented corner
3960  int i0 = -1;
3961  bool cw = true;
3962  for (int i=0; i<8; i++)
3963  {
3964  if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0])
3965  {
3966  i0 = i;
3967  switch (i0)
3968  {
3969  case 0:
3970  case 2:
3971  case 5:
3972  case 7:
3973  cw = rubik.corn_[3 * i0 + 0] == corn_colors_[3 * i0 + 1];
3974  break;
3975  case 1:
3976  case 3:
3977  case 4:
3978  case 6:
3979  cw = rubik.corn_[3 * i0 + 0] == corn_colors_[3 * i0 + 2];
3980  break;
3981  }
3982  break;
3983  }
3984  }
3985 
3986  if (i0 < 0) { return; }
3987 
3988  if (logging_ > 1)
3989  {
3990  cout << "First incorrectly oriented corner: " << i0 << endl;
3991  }
3992 
3993  // Locate second incorrectly oriented corner
3994  int i1 = -1;
3995  for (int i=i0+1; i<8; i++)
3996  {
3997  if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0])
3998  {
3999  i1 = i;
4000  break;
4001  }
4002  }
4003  if (logging_ > 1)
4004  {
4005  cout << "Second incorrectly oriented corner: " << i1 << endl;
4006  }
4007 
4008  // Locate third incorrectly oriented corner (if such exists)
4009  int i2 = -1;
4010  // int i3 = -1;
4011  for (int i=i1+1; i<8; i++)
4012  {
4013  if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0])
4014  {
4015  i2 = i;
4016  break;
4017  }
4018  }
4019  if (i2 > 0)
4020  {
4021  if (logging_ > 1)
4022  {
4023  cout << "Third incorrectly oriented corner: " << i2 << endl;
4024  }
4025 
4026  // Three incorrectly oriented corners were found
4027  int c0[3] = {rubik.corn_[3 * i0],
4028  rubik.corn_[3 * i0 + 1],
4029  rubik.corn_[3 * i0 + 2]
4030  };
4031  int c1[3] = {rubik.corn_[3 * i1],
4032  rubik.corn_[3 * i1 + 1],
4033  rubik.corn_[3 * i1 + 2]
4034  };
4035  int c2[3] = {rubik.corn_[3 * i2],
4036  rubik.corn_[3 * i2 + 1],
4037  rubik.corn_[3 * i2 + 2]
4038  };
4039 
4040  twist_corners(mesh, color, sock, cw, c0, c1, c2);
4041  }
4042  else
4043  {
4044  // Two incorrectly oriented corners were found
4045  int c0[3] = {rubik.corn_[3 * i0],
4046  rubik.corn_[3 * i0 + 1],
4047  rubik.corn_[3 * i0 + 2]
4048  };
4049  int c1[3] = {rubik.corn_[3 * i1],
4050  rubik.corn_[3 * i1 + 1],
4051  rubik.corn_[3 * i1 + 2]
4052  };
4053  twist_corners(mesh, color, sock, cw, c0, c1);
4054  }
4055 
4056  solve_corner_orientations(mesh, color, sock);
4057 }
4058 
4059 void
4061  int * e0, int * e1, int * e2)
4062 {
4063  if (logging_ > 1)
4064  {
4065  cout << "Entering permute_edges" << endl;
4066  }
4067 
4068  if (e0 != NULL)
4069  {
4070  // Locate first incorrectly filled edge location
4071  int i0 = -1;
4072  for (int i=0; i<12; i++)
4073  {
4074  if ((rubik.edge_[2 * i] == e0[0] &&
4075  rubik.edge_[2 * i + 1] == e0[1]) ||
4076  (rubik.edge_[2 * i] == e0[1] &&
4077  rubik.edge_[2 * i + 1] == e0[0]))
4078  {
4079  i0 = i;
4080  break;
4081  }
4082  }
4083  if (logging_ > 1)
4084  {
4085  cout << "Location of e0 = {"<<e0[0]<<","<<e0[1]<<"}: " << i0 << endl;
4086  }
4087 
4088  switch (i0)
4089  {
4090  case 0:
4091  permute_edges(mesh, color, sock, NULL, e1, e2);
4092  break;
4093  case 1:
4094  case 2:
4095  case 3:
4096  anim_move('z', 1, i0, mesh, color, sock);
4097  permute_edges(mesh, color, sock, NULL, e1, e2);
4098  anim_move('z', 1, 4-i0, mesh, color, sock);
4099  break;
4100  case 4:
4101  anim_move('x', 2, 3, mesh, color, sock);
4102  permute_edges(mesh, color, sock, NULL, e1, e2);
4103  anim_move('x', 2, 1, mesh, color, sock);
4104  break;
4105  case 5:
4106  anim_move('y', 2, 3, mesh, color, sock);
4107  permute_edges(mesh, color, sock, NULL, e1, e2);
4108  anim_move('y', 2, 1, mesh, color, sock);
4109  break;
4110  case 6:
4111  anim_move('x', 2, 2, mesh, color, sock);
4112  permute_edges(mesh, color, sock, NULL, e1, e2);
4113  anim_move('x', 2, 2, mesh, color, sock);
4114  break;
4115  case 7:
4116  anim_move('y', 2, 1, mesh, color, sock);
4117  permute_edges(mesh, color, sock, NULL, e1, e2);
4118  anim_move('y', 2, 3, mesh, color, sock);
4119  break;
4120  case 8:
4121  anim_move('y', 1, 1, mesh, color, sock);
4122  permute_edges(mesh, color, sock, NULL, e1, e2);
4123  anim_move('y', 1, 3, mesh, color, sock);
4124  break;
4125  case 9:
4126  anim_move('y', 1, 3, mesh, color, sock);
4127  permute_edges(mesh, color, sock, NULL, e1, e2);
4128  anim_move('y', 1, 1, mesh, color, sock);
4129  break;
4130  case 10:
4131  anim_move('x', 3, 1, mesh, color, sock);
4132  permute_edges(mesh, color, sock, NULL, e1, e2);
4133  anim_move('x', 3, 3, mesh, color, sock);
4134  break;
4135  case 11:
4136  anim_move('x', 1, 1, mesh, color, sock);
4137  permute_edges(mesh, color, sock, NULL, e1, e2);
4138  anim_move('x', 1, 3, mesh, color, sock);
4139  break;
4140  }
4141  }
4142  else if (e1 != NULL)
4143  {
4144  // Locate edge piece which belongs at e0
4145  int i1 = -1;
4146  for (int i=1; i<12; i++)
4147  {
4148  if ((rubik.edge_[2 * i] == e1[0] &&
4149  rubik.edge_[2 * i + 1] == e1[1]) ||
4150  (rubik.edge_[2 * i] == e1[1] &&
4151  rubik.edge_[2 * i + 1] == e1[0]))
4152  {
4153  i1 = i;
4154  break;
4155  }
4156  }
4157  if (logging_ > 1)
4158  {
4159  cout << "Location of piece belonging at " << 0 << " (e1) is "
4160  << i1 << endl;
4161  }
4162 
4163  switch (i1)
4164  {
4165  case 1:
4166  permute_edges(mesh, color, sock, NULL, NULL, e2);
4167  break;
4168  case 2:
4169  case 3:
4170  anim_move('y', 1, 1, mesh, color, sock);
4171  anim_move('z', 1, i1-1, mesh, color, sock);
4172  anim_move('y', 1, 3, mesh, color, sock);
4173  permute_edges(mesh, color, sock, NULL, NULL, e2);
4174  anim_move('y', 1, 1, mesh, color, sock);
4175  anim_move('z', 1, 5-i1, mesh, color, sock);
4176  anim_move('y', 1, 3, mesh, color, sock);
4177  break;
4178  case 4:
4179  case 5:
4180  case 6:
4181  case 7:
4182  anim_move('z', 3, (i1-1)%4, mesh, color, sock);
4183  anim_move('x', 3, 2, mesh, color, sock);
4184  permute_edges(mesh, color, sock, NULL, NULL, e2);
4185  anim_move('x', 3, 2, mesh, color, sock);
4186  anim_move('z', 3, (9-i1)%4, mesh, color, sock);
4187  break;
4188  case 8:
4189  case 9:
4190  case 10:
4191  case 11:
4192  anim_move('z', 2, (i1-5)%4, mesh, color, sock);
4193  anim_move('x', 3, 3, mesh, color, sock);
4194  permute_edges(mesh, color, sock, NULL, NULL, e2);
4195  anim_move('x', 3, 1, mesh, color, sock);
4196  anim_move('z', 2, (13-i1)%4, mesh, color, sock);
4197  break;
4198  }
4199  }
4200  else if (e2 != NULL)
4201  {
4202  // Locate a third incorrect edge
4203  int i2 = -1;
4204  for (int i=2; i<12; i++)
4205  {
4206  if ((rubik.edge_[2 * i] == e2[0] &&
4207  rubik.edge_[2 * i + 1] == e2[1]) ||
4208  (rubik.edge_[2 * i] == e2[1] &&
4209  rubik.edge_[2 * i + 1] == e2[0]))
4210  {
4211  i2 = i;
4212  break;
4213  }
4214  }
4215  if (logging_ > 1)
4216  {
4217  cout << "Location of e2: " << i2 << endl;
4218  }
4219 
4220  switch (i2)
4221  {
4222  case 2:
4223  permute_edges(mesh, color, sock, NULL, NULL, NULL);
4224  break;
4225  case 3:
4226  anim_move('x', 1, 3, mesh, color, sock);
4227  anim_move('y', 3, 1, mesh, color, sock);
4228  permute_edges(mesh, color, sock, NULL, NULL, NULL);
4229  anim_move('y', 3, 3, mesh, color, sock);
4230  anim_move('x', 1, 1, mesh, color, sock);
4231  break;
4232  case 4:
4233  case 5:
4234  case 6:
4235  case 7:
4236  anim_move('z', 3, (i2-2)%4, mesh, color, sock);
4237  anim_move('y', 3, 2, mesh, color, sock);
4238  permute_edges(mesh, color, sock, NULL, NULL, NULL);
4239  anim_move('y', 3, 2, mesh, color, sock);
4240  anim_move('z', 3, (10-i2)%4, mesh, color, sock);
4241  break;
4242  case 8:
4243  case 9:
4244  case 10:
4245  case 11:
4246  anim_move('z', 2, (i2-6)%4, mesh, color, sock);
4247  anim_move('y', 3, 3, mesh, color, sock);
4248  permute_edges(mesh, color, sock, NULL, NULL, NULL);
4249  anim_move('y', 3, 1, mesh, color, sock);
4250  anim_move('z', 2, (14-i2)%4, mesh, color, sock);
4251  break;
4252  }
4253  }
4254  else
4255  {
4256  permute_edges(mesh, color, sock, true);
4257  }
4258 }
4259 
4260 void
4261 permute_edges(Mesh & mesh, GridFunction & color, socketstream & sock, bool cw)
4262 {
4263  if (cw)
4264  {
4265  anim_move('y', 2, 1, mesh, color, sock);
4266  anim_move('z', 1, 1, mesh, color, sock);
4267  anim_move('y', 2, 3, mesh, color, sock);
4268  anim_move('z', 1, 2, mesh, color, sock);
4269  anim_move('y', 2, 1, mesh, color, sock);
4270  anim_move('z', 1, 1, mesh, color, sock);
4271  anim_move('y', 2, 3, mesh, color, sock);
4272  }
4273  else
4274  {
4275  anim_move('y', 2, 1, mesh, color, sock);
4276  anim_move('z', 1, 3, mesh, color, sock);
4277  anim_move('y', 2, 3, mesh, color, sock);
4278  anim_move('z', 1, 2, mesh, color, sock);
4279  anim_move('y', 2, 1, mesh, color, sock);
4280  anim_move('z', 1, 3, mesh, color, sock);
4281  anim_move('y', 2, 3, mesh, color, sock);
4282  }
4283 }
4284 
4285 void
4287 {
4288  if (logging_ > 1)
4289  {
4290  cout << "Entering solve_edge_locations" << endl;
4291  }
4292  if (logging_ > 2)
4293  {
4294  print_state(cout);
4295  }
4296 
4297  // Locate first incorrectly filled edge location
4298  int i0 = -1;
4299  for (int i=0; i<12; i++)
4300  {
4301  if (!((rubik.edge_[2 * i] == edge_colors_[2 * i] &&
4302  rubik.edge_[2 * i + 1] == edge_colors_[2 * i + 1]) ||
4303  (rubik.edge_[2 * i] == edge_colors_[2 * i + 1] &&
4304  rubik.edge_[2 * i + 1] == edge_colors_[2 * i])))
4305  {
4306  i0 = i;
4307  break;
4308  }
4309  }
4310  if (logging_ > 1)
4311  {
4312  cout << "First incorrectly filled edge location: " << i0 << endl;
4313  }
4314 
4315  if (i0 < 0) { return; }
4316 
4317  // Locate edge piece which belongs at e0
4318  int i1 = locate_edge(i0);
4319  if (i1 < 0 ) { i1 = -1 - i1; }
4320  if (logging_ > 1)
4321  {
4322  cout << "Location of piece belonging at " << i0 << " is " << i1 << endl;
4323  }
4324 
4325  // Locate a third incorrect edge
4326  int i2 = -1;
4327  for (int i=i0+1; i<12; i++)
4328  {
4329  if (i == i1) { continue; }
4330  if (!((rubik.edge_[2 * i + 0] == edge_colors_[2 * i + 0] &&
4331  rubik.edge_[2 * i + 1] == edge_colors_[2 * i + 1]) ||
4332  (rubik.edge_[2 * i + 0] == edge_colors_[2 * i + 1] &&
4333  rubik.edge_[2 * i + 1] == edge_colors_[2 * i + 0])))
4334  {
4335  i2 = i;
4336  break;
4337  }
4338  }
4339  if (logging_ > 1)
4340  {
4341  cout << "Another incorrectly filled edge location: " << i2 << endl;
4342  }
4343 
4344  if (i1 < 0 || i2 <0)
4345  {
4346  cout << "Invalid configuration of edges" << endl;
4347  return;
4348  }
4349 
4350  int e0[2] = {rubik.edge_[2 * i0], rubik.edge_[2 * i0 + 1]};
4351  int e1[2] = {rubik.edge_[2 * i1], rubik.edge_[2 * i1 + 1]};
4352  int e2[2] = {rubik.edge_[2 * i2], rubik.edge_[2 * i2 + 1]};
4353 
4354  permute_edges(mesh, color, sock, e0, e1, e2);
4355 
4356  solve_edge_locations(mesh, color, sock);
4357 }
4358 
4359 void
4360 flip_edges(Mesh & mesh, GridFunction & color, socketstream & sock,
4361  int n, int * e0, int * e1, int * e2, int * e3)
4362 {
4363  if (n == 2)
4364  {
4365  if (e0 != NULL)
4366  {
4367  // Locate first incorrectly oriented edge
4368  int i0 = -1;
4369  for (int i=0; i<12; i++)
4370  {
4371  if ((rubik.edge_[2 * i] == e0[0] &&
4372  rubik.edge_[2 * i + 1] == e0[1]) ||
4373  (rubik.edge_[2 * i] == e0[1] &&
4374  rubik.edge_[2 * i + 1] == e0[0]))
4375  {
4376  i0 = i;
4377  break;
4378  }
4379  }
4380  if (logging_ > 1)
4381  {
4382  cout << "Location of e0 = {"<<e0[0]<<","<<e0[1]<<"}: " << i0 << endl;
4383  }
4384 
4385  switch (i0)
4386  {
4387  case 0:
4388  flip_edges(mesh, color, sock, 2, NULL, e1);
4389  break;
4390  case 1:
4391  case 2:
4392  case 3:
4393  anim_move('z', 1, i0, mesh, color, sock);
4394  flip_edges(mesh, color, sock, 2, NULL, e1);
4395  anim_move('z', 1, 4-i0, mesh, color, sock);
4396  break;
4397  case 4:
4398  anim_move('x', 2, 3, mesh, color, sock);
4399  flip_edges(mesh, color, sock, 2, NULL, e1);
4400  anim_move('x', 2, 1, mesh, color, sock);
4401  break;
4402  case 5:
4403  anim_move('y', 2, 3, mesh, color, sock);
4404  flip_edges(mesh, color, sock, 2, NULL, e1);
4405  anim_move('y', 2, 1, mesh, color, sock);
4406  break;
4407  case 6:
4408  anim_move('x', 2, 2, mesh, color, sock);
4409  flip_edges(mesh, color, sock, 2, NULL, e1);
4410  anim_move('x', 2, 2, mesh, color, sock);
4411  break;
4412  case 7:
4413  anim_move('y', 2, 1, mesh, color, sock);
4414  flip_edges(mesh, color, sock, 2, NULL, e1);
4415  anim_move('y', 2, 3, mesh, color, sock);
4416  break;
4417  case 8:
4418  anim_move('y', 1, 1, mesh, color, sock);
4419  flip_edges(mesh, color, sock, 2, NULL, e1);
4420  anim_move('y', 1, 3, mesh, color, sock);
4421  break;
4422  case 9:
4423  anim_move('y', 1, 3, mesh, color, sock);
4424  flip_edges(mesh, color, sock, 2, NULL, e1);
4425  anim_move('y', 1, 1, mesh, color, sock);
4426  break;
4427  case 10:
4428  anim_move('x', 3, 1, mesh, color, sock);
4429  flip_edges(mesh, color, sock, 2, NULL, e1);
4430  anim_move('x', 3, 3, mesh, color, sock);
4431  break;
4432  case 11:
4433  anim_move('x', 1, 1, mesh, color, sock);
4434  flip_edges(mesh, color, sock, 2, NULL, e1);
4435  anim_move('x', 1, 3, mesh, color, sock);
4436  break;
4437  }
4438  }
4439  else if (e1 != NULL)
4440  {
4441  // Locate second incorrectly oriented edge
4442  int i1 = -1;
4443  for (int i=1; i<12; i++)
4444  {
4445  if ((rubik.edge_[2 * i] == e1[0] &&
4446  rubik.edge_[2 * i + 1] == e1[1]) ||
4447  (rubik.edge_[2 * i] == e1[1] &&
4448  rubik.edge_[2 * i + 1] == e1[0]))
4449  {
4450  i1 = i;
4451  break;
4452  }
4453  }
4454  if (logging_ > 1)
4455  {
4456  cout << "Location of e1: " << i1 << endl;
4457  }
4458 
4459  switch (i1)
4460  {
4461  case 1:
4462  anim_move('x', 3, 3, mesh, color, sock);
4463  anim_move('y', 3, 3, mesh, color, sock);
4464  flip_edges(mesh, color, sock, 2, NULL, NULL);
4465  anim_move('y', 3, 1, mesh, color, sock);
4466  anim_move('x', 3, 1, mesh, color, sock);
4467  break;
4468  case 2:
4469  flip_edges(mesh, color, sock, 2, NULL, NULL);
4470  break;
4471  case 3:
4472  anim_move('x', 1, 3, mesh, color, sock);
4473  anim_move('y', 3, 1, mesh, color, sock);
4474  flip_edges(mesh, color, sock, 2, NULL, NULL);
4475  anim_move('y', 3, 3, mesh, color, sock);
4476  anim_move('x', 1, 1, mesh, color, sock);
4477  break;
4478  case 4:
4479  case 5:
4480  case 6:
4481  case 7:
4482  anim_move('z', 3, (i1-2)%4, mesh, color, sock);
4483  anim_move('y', 3, 2, mesh, color, sock);
4484  flip_edges(mesh, color, sock, 2, NULL, NULL);
4485  anim_move('y', 3, 2, mesh, color, sock);
4486  anim_move('z', 3, (10-i1)%4, mesh, color, sock);
4487  break;
4488  case 8:
4489  case 9:
4490  case 10:
4491  case 11:
4492  anim_move('z', 2, (i1-6)%4, mesh, color, sock);
4493  anim_move('y', 3, 3, mesh, color, sock);
4494  flip_edges(mesh, color, sock, 2, NULL, NULL);
4495  anim_move('y', 3, 1, mesh, color, sock);
4496  anim_move('z', 2, (14-i1)%4, mesh, color, sock);
4497  break;
4498  }
4499  }
4500  else
4501  {
4502  anim_move('x', 2, 3, mesh, color, sock);
4503  anim_move('z', 1, 3, mesh, color, sock);
4504  anim_move('x', 2, 1, mesh, color, sock);
4505  anim_move('z', 1, 3, mesh, color, sock);
4506  anim_move('x', 2, 3, mesh, color, sock);
4507  anim_move('z', 1, 3, mesh, color, sock);
4508  anim_move('x', 2, 1, mesh, color, sock);
4509  anim_move('z', 1, 3, mesh, color, sock);
4510  anim_move('x', 2, 3, mesh, color, sock);
4511  anim_move('z', 1, 2, mesh, color, sock);
4512  anim_move('x', 2, 1, mesh, color, sock);
4513  anim_move('z', 1, 3, mesh, color, sock);
4514  anim_move('x', 2, 3, mesh, color, sock);
4515  anim_move('z', 1, 3, mesh, color, sock);
4516  anim_move('x', 2, 1, mesh, color, sock);
4517  anim_move('z', 1, 3, mesh, color, sock);
4518  anim_move('x', 2, 3, mesh, color, sock);
4519  anim_move('z', 1, 3, mesh, color, sock);
4520  anim_move('x', 2, 1, mesh, color, sock);
4521  anim_move('z', 1, 2, mesh, color, sock);
4522  }
4523  }
4524  else if (n == 4)
4525  {
4526  if (e0 != NULL)
4527  {
4528  // Locate first incorrectly oriented edge
4529  int i0 = -1;
4530  for (int i=0; i<12; i++)
4531  {
4532  if ((rubik.edge_[2 * i] == e0[0] &&
4533  rubik.edge_[2 * i + 1] == e0[1]) ||
4534  (rubik.edge_[2 * i] == e0[1] &&
4535  rubik.edge_[2 * i + 1] == e0[0]))
4536  {
4537  i0 = i;
4538  break;
4539  }
4540  }
4541  if (logging_ > 1)
4542  {
4543  cout << "Location of e0 = {"<<e0[0]<<","<<e0[1]<<"}: " << i0 << endl;
4544  }
4545 
4546  switch (i0)
4547  {
4548  case 0:
4549  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4550  break;
4551  case 1:
4552  case 2:
4553  case 3:
4554  anim_move('z', 1, i0, mesh, color, sock);
4555  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4556  anim_move('z', 1, 4-i0, mesh, color, sock);
4557  break;
4558  case 4:
4559  anim_move('x', 2, 3, mesh, color, sock);
4560  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4561  anim_move('x', 2, 1, mesh, color, sock);
4562  break;
4563  case 5:
4564  anim_move('y', 2, 3, mesh, color, sock);
4565  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4566  anim_move('y', 2, 1, mesh, color, sock);
4567  break;
4568  case 6:
4569  anim_move('x', 2, 2, mesh, color, sock);
4570  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4571  anim_move('x', 2, 2, mesh, color, sock);
4572  break;
4573  case 7:
4574  anim_move('y', 2, 1, mesh, color, sock);
4575  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4576  anim_move('y', 2, 3, mesh, color, sock);
4577  break;
4578  case 8:
4579  anim_move('y', 1, 1, mesh, color, sock);
4580  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4581  anim_move('y', 1, 3, mesh, color, sock);
4582  break;
4583  case 9:
4584  anim_move('y', 1, 3, mesh, color, sock);
4585  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4586  anim_move('y', 1, 1, mesh, color, sock);
4587  break;
4588  case 10:
4589  anim_move('x', 3, 1, mesh, color, sock);
4590  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4591  anim_move('x', 3, 3, mesh, color, sock);
4592  break;
4593  case 11:
4594  anim_move('x', 1, 1, mesh, color, sock);
4595  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4596  anim_move('x', 1, 3, mesh, color, sock);
4597  break;
4598  }
4599  }
4600  else if (e1 != NULL)
4601  {
4602  // Locate second incorrectly oriented edge
4603  int i1 = -1;
4604  for (int i=1; i<12; i++)
4605  {
4606  if ((rubik.edge_[2 * i] == e1[0] &&
4607  rubik.edge_[2 * i + 1] == e1[1]) ||
4608  (rubik.edge_[2 * i] == e1[1] &&
4609  rubik.edge_[2 * i + 1] == e1[0]))
4610  {
4611  i1 = i;
4612  break;
4613  }
4614  }
4615  if (logging_ > 1)
4616  {
4617  cout << "Location of e1: " << i1 << endl;
4618  }
4619 
4620  switch (i1)
4621  {
4622  case 1:
4623  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4624  break;
4625  case 2:
4626  anim_move('y', 3, 1, mesh, color, sock);
4627  anim_move('x', 3, 1, mesh, color, sock);
4628  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4629  anim_move('x', 3, 3, mesh, color, sock);
4630  anim_move('y', 3, 3, mesh, color, sock);
4631  break;
4632  case 3:
4633  anim_move('y', 2, 1, mesh, color, sock);
4634  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4635  anim_move('y', 2, 3, mesh, color, sock);
4636  break;
4637  case 4:
4638  case 5:
4639  case 6:
4640  case 7:
4641  anim_move('z', 3, (i1-1)%4, mesh, color, sock);
4642  anim_move('x', 3, 2, mesh, color, sock);
4643  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4644  anim_move('x', 3, 2, mesh, color, sock);
4645  anim_move('z', 3, (9-i1)%4, mesh, color, sock);
4646  break;
4647  case 8:
4648  case 9:
4649  case 10:
4650  case 11:
4651  anim_move('z', 2, (i1-5)%4, mesh, color, sock);
4652  anim_move('x', 3, 3, mesh, color, sock);
4653  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4654  anim_move('x', 3, 1, mesh, color, sock);
4655  anim_move('z', 2, (13-i1)%4, mesh, color, sock);
4656  break;
4657  }
4658  }
4659  else if (e2 != NULL)
4660  {
4661  // Locate third incorrectly oriented edge
4662  int i2 = -1;
4663  for (int i=2; i<12; i++)
4664  {
4665  if ((rubik.edge_[2 * i] == e2[0] &&
4666  rubik.edge_[2 * i + 1] == e2[1]) ||
4667  (rubik.edge_[2 * i] == e2[1] &&
4668  rubik.edge_[2 * i + 1] == e2[0]))
4669  {
4670  i2 = i;
4671  break;
4672  }
4673  }
4674  if (logging_ > 1)
4675  {
4676  cout << "Location of e2: " << i2 << endl;
4677  }
4678 
4679  switch (i2)
4680  {
4681  case 2:
4682  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3);
4683  break;
4684  case 3:
4685  anim_move('x', 1, 3, mesh, color, sock);
4686  anim_move('y', 3, 1, mesh, color, sock);
4687  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3);
4688  anim_move('y', 3, 3, mesh, color, sock);
4689  anim_move('x', 1, 1, mesh, color, sock);
4690  break;
4691  case 4:
4692  case 5:
4693  case 6:
4694  case 7:
4695  anim_move('z', 3, (i2-2)%4, mesh, color, sock);
4696  anim_move('y', 3, 2, mesh, color, sock);
4697  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3);
4698  anim_move('y', 3, 2, mesh, color, sock);
4699  anim_move('z', 3, (10-i2)%4, mesh, color, sock);
4700  break;
4701  case 8:
4702  case 9:
4703  case 10:
4704  case 11:
4705  anim_move('z', 2, (i2-6)%4, mesh, color, sock);
4706  anim_move('y', 3, 3, mesh, color, sock);
4707  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3);
4708  anim_move('y', 3, 1, mesh, color, sock);
4709  anim_move('z', 2, (14-i2)%4, mesh, color, sock);
4710  break;
4711  }
4712  }
4713  else if (e3 != NULL)
4714  {
4715  // Locate fourth incorrectly oriented edge
4716  int i3 = -1;
4717  for (int i=3; i<12; i++)
4718  {
4719  if ((rubik.edge_[2 * i] == e3[0] &&
4720  rubik.edge_[2 * i + 1] == e3[1]) ||
4721  (rubik.edge_[2 * i] == e3[1] &&
4722  rubik.edge_[2 * i + 1] == e3[0]))
4723  {
4724  i3 = i;
4725  break;
4726  }
4727  }
4728  if (logging_ > 1)
4729  {
4730  cout << "Location of e3: " << i3 << endl;
4731  }
4732 
4733  switch (i3)
4734  {
4735  case 3:
4736  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, NULL);
4737  break;
4738  case 4:
4739  case 5:
4740  case 6:
4741  case 7:
4742  anim_move('z', 3, (i3-3)%4, mesh, color, sock);
4743  anim_move('x', 1, 2, mesh, color, sock);
4744  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, NULL);
4745  anim_move('x', 1, 2, mesh, color, sock);
4746  anim_move('z', 3, (7-i3)%4, mesh, color, sock);
4747  break;
4748  case 8:
4749  case 9:
4750  case 10:
4751  case 11:
4752  anim_move('z', 2, (i3-4)%4, mesh, color, sock);
4753  anim_move('x', 1, 3, mesh, color, sock);
4754  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, NULL);
4755  anim_move('x', 1, 1, mesh, color, sock);
4756  anim_move('z', 2, (12-i3)%4, mesh, color, sock);
4757  break;
4758  }
4759  }
4760  else
4761  {
4762  anim_move('x', 2, 3, mesh, color, sock);
4763  anim_move('z', 1, 2, mesh, color, sock);
4764  anim_move('x', 2, 1, mesh, color, sock);
4765  anim_move('z', 1, 2, mesh, color, sock);
4766  anim_move('x', 2, 3, mesh, color, sock);
4767  anim_move('z', 1, 3, mesh, color, sock);
4768  anim_move('x', 2, 1, mesh, color, sock);
4769  anim_move('z', 1, 2, mesh, color, sock);
4770  anim_move('x', 2, 3, mesh, color, sock);
4771  anim_move('z', 1, 2, mesh, color, sock);
4772  anim_move('x', 2, 1, mesh, color, sock);
4773  anim_move('z', 1, 1, mesh, color, sock);
4774  }
4775  }
4776 }
4777 
4778 void
4780 {
4781  if (logging_ > 1)
4782  {
4783  cout << "Entering solve_edge_orientations" << endl;
4784  }
4785  if (logging_ > 2)
4786  {
4787  print_state(cout);
4788  }
4789 
4790  // Locate first incorrectly oriented edge
4791  int i0 = -1;
4792  for (int i=0; i<12; i++)
4793  {
4794  if (rubik.edge_[2 * i] != edge_colors_[2 * i])
4795  {
4796  i0 = i;
4797  break;
4798  }
4799  }
4800  if (logging_ > 1)
4801  {
4802  cout << "First incorrectly oriented edge location: " << i0 << endl;
4803  }
4804 
4805  if (i0 < 0) { return; }
4806 
4807  // Locate second incorrectly oriented edge
4808  int i1 = -1;
4809  for (int i=i0+1; i<12; i++)
4810  {
4811  if (rubik.edge_[2 * i] != edge_colors_[2 * i])
4812  {
4813  i1 = i;
4814  break;
4815  }
4816  }
4817  if (logging_ > 1)
4818  {
4819  cout << "Second incorrectly oriented edge location: " << i1 << endl;
4820  }
4821 
4822  // Locate third incorrectly oriented edge (if such exists)
4823  int i2 = -1;
4824  int i3 = -1;
4825  for (int i=i1+1; i<12; i++)
4826  {
4827  if (rubik.edge_[2 * i] != edge_colors_[2 * i])
4828  {
4829  i2 = i;
4830  break;
4831  }
4832  }
4833  if (i2 > 0)
4834  {
4835  if (logging_ > 1)
4836  {
4837  cout << "Third incorrectly oriented edge location: " << i2 << endl;
4838  }
4839 
4840  // Locate fourth incorrectly oriented edge (if such exists)
4841  for (int i=i2+1; i<12; i++)
4842  {
4843  if (rubik.edge_[2 * i] != edge_colors_[2 * i])
4844  {
4845  i3 = i;
4846  break;
4847  }
4848  }
4849  if (logging_ > 1)
4850  {
4851  cout << "Fourth incorrectly oriented edge location: " << i3 << endl;
4852  }
4853  }
4854 
4855  int e0[2] = {rubik.edge_[2 * i0], rubik.edge_[2 * i0 + 1]};
4856  int e1[2] = {rubik.edge_[2 * i1], rubik.edge_[2 * i1 + 1]};
4857  int e2[2] = {rubik.edge_[2 * max(i2,0)], rubik.edge_[2 * max(i2,0) + 1]};
4858  int e3[2] = {rubik.edge_[2 * max(i3,0)], rubik.edge_[2 * max(i3,0) + 1]};
4859 
4860  if (i2 == -1)
4861  {
4862  flip_edges(mesh, color, sock, 2, e0, e1);
4863  }
4864  else
4865  {
4866  flip_edges(mesh, color, sock, 4, e0, e1, e2, e3);
4867  }
4868 
4869  solve_edge_orientations(mesh, color, sock);
4870 }
4871 
4872 void
4873 solve_top(Mesh & mesh, GridFunction & color, socketstream & sock)
4874 {
4875  count_ = 0;
4876  if (logging_ > 0)
4877  {
4878  cout << "Solving top center block..." << endl;
4879  }
4880  solve_top_center(mesh, color, sock);
4881  if (logging_ > 0)
4882  {
4883  cout << "Solving top tier edges..." << endl;
4884  }
4885  solve_top_edges(mesh, color, sock);
4886  if (logging_ > 0)
4887  {
4888  cout << "Solving center blocks..." << endl;
4889  }
4890  if (logging_ > 0)
4891  {
4892  cout << "Solving top tier corners..." << endl;
4893  }
4894  solve_top_corners(mesh, color, sock);
4895 
4896  cout << "Move count: " << count_ << endl;
4897 }
4898 
4899 void
4900 solve_mid(Mesh & mesh, GridFunction & color, socketstream & sock)
4901 {
4902  count_ = 0;
4903  if (logging_ > 0)
4904  {
4905  cout << "Solving center blocks in the middle tier..." << endl;
4906  }
4907  solve_centers(mesh, color, sock);
4908  if (logging_ > 0)
4909  {
4910  cout << "Solving edge blocks in the middle tier..." << endl;
4911  }
4912  solve_mid_edges(mesh, color, sock);
4913 
4914  cout << "Move count: " << count_ << endl;
4915 }
4916 
4917 void
4918 solve_bot(Mesh & mesh, GridFunction & color, socketstream & sock)
4919 {
4920  if (logging_ > 0)
4921  {
4922  cout << "Solving corner block locations in the bottom tier..." << endl;
4923  }
4924  solve_bot_corner_locations(mesh, color, sock);
4925  if (logging_ > 0)
4926  {
4927  cout << "Solving corner block orientations..." << endl;
4928  }
4929  solve_corner_orientations(mesh, color, sock);
4930  if (logging_ > 0)
4931  {
4932  cout << "Solving edge block locations..." << endl;
4933  }
4934  solve_edge_locations(mesh, color, sock);
4935  if (logging_ > 0)
4936  {
4937  cout << "Solving edge block orientations..." << endl;
4938  }
4939  solve_edge_orientations(mesh, color, sock);
4940 }
4941 
4942 void
4943 solve(Mesh & mesh, GridFunction & color, socketstream & sock)
4944 {
4945  count_ = 0;
4946  if (logging_ > 0)
4947  {
4948  cout << "Solving top center block..." << endl;
4949  }
4950  solve_top_center(mesh, color, sock);
4951  if (logging_ > 0)
4952  {
4953  cout << "Solving top tier edges..." << endl;
4954  }
4955  solve_top_edges(mesh, color, sock);
4956  if (logging_ > 0)
4957  {
4958  cout << "Solving top tier corners..." << endl;
4959  }
4960  solve_top_corners(mesh, color, sock);
4961  if (logging_ > 0)
4962  {
4963  cout << "Solving center blocks in the middle tier..." << endl;
4964  }
4965  solve_centers(mesh, color, sock);
4966  if (logging_ > 0)
4967  {
4968  cout << "Solving edge blocks in the middle tier..." << endl;
4969  }
4970  solve_mid_edges(mesh, color, sock);
4971  if (logging_ > 0)
4972  {
4973  cout << "Solving corner block locations in the bottom tier..." << endl;
4974  }
4975  solve_bot_corner_locations(mesh, color, sock);
4976  if (logging_ > 0)
4977  {
4978  cout << "Solving corner block orientations..." << endl;
4979  }
4980  solve_corner_orientations(mesh, color, sock);
4981  if (logging_ > 0)
4982  {
4983  cout << "Solving edge block locations..." << endl;
4984  }
4985  solve_edge_locations(mesh, color, sock);
4986  if (logging_ > 0)
4987  {
4988  cout << "Solving edge block orientations..." << endl;
4989  }
4990  solve_edge_orientations(mesh, color, sock);
4991 
4992  cout << "Move count: " << count_ << endl;
4993 }
void move_to_e7(int i7, int o7, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2468
void solve(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4943
int Size() const
Return the logical size of the array.
Definition: array.hpp:138
int locate_corner(int ind)
Definition: rubik.cpp:1376
bool validate_centers(const int max_ind=6)
void move_to_e8(int i8, int o8, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2557
const double * GetVertex(int i) const
Return pointer to vertex i&#39;s coordinates.
Definition: mesh.hpp:1012
void print_state(ostream &out)
Definition: rubik.cpp:876
Class for grid function - Vector with associated FE space.
Definition: gridfunc.hpp:30
void move_to_e10(int i10, int o10, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2860
void update_centers(char axis, int incr)
Definition: rubik.cpp:560
int GetNBE() const
Returns number of boundary elements.
Definition: mesh.hpp:926
void solve_edge_orientations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4779
bool validate_edges(const int max_ind=12)
void move_to_c7(int i7, int o7, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1935
void solve_mid(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4900
void move_to_c4(int i4, int o4, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1421
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:923
void move_to_e5(int i5, int o5, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2264
void permute_edges(Mesh &mesh, GridFunction &color, socketstream &sock, int *e0, int *e1, int *e2)
Definition: rubik.cpp:4060
void solve_edge_locations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4286
int AddVertex(double x, double y=0.0, double z=0.0)
Definition: mesh.cpp:1613
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
Definition: optparser.cpp:151
constexpr char vishost[]
void update_edges(char axis, int tier, int incr)
Definition: rubik.cpp:729
constexpr int visport
void move_to_e4(int i4, int o4, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2152
void solve_centers(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1255
void GetBdrElementAdjacentElement(int bdr_el, int &el, int &info) const
For the given boundary element, bdr_el, return its adjacent element and its info, i...
Definition: mesh.cpp:6206
void anim_move(char axis, int tier, int increment, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1164
void solve_top(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4873
void solve_corner_orientations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3947
void init_hex_mesh(Mesh &mesh)
Definition: rubik.cpp:406
void PrintUsage(std::ostream &out) const
Print the usage message.
Definition: optparser.cpp:454
void solve_bot_corner_locations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3539
void solve_corner_locations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3465
void update_corners(char axis, int tier, int incr)
Definition: rubik.cpp:588
void move_to_c6(int i6, int o6, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1791
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:96
int AddHex(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int attr=1)
Definition: mesh.cpp:1737
void flip_edges(Mesh &mesh, GridFunction &color, socketstream &sock, int n, int *e0=NULL, int *e1=NULL, int *e2=NULL, int *e3=NULL)
Definition: rubik.cpp:4360
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
Definition: mesh.cpp:2890
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set &#39;var&#39; to receive the value. Enable/disable tags are used to set the bool...
Definition: optparser.hpp:82
void move_to_e6(int i6, int o6, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2371
void swap_corners(Mesh &mesh, GridFunction &color, socketstream &sock, int *c0=NULL, int *c1=NULL)
Definition: rubik.cpp:3292
void rotate_step(char axis, int incr, double *x)
Definition: rubik.cpp:1003
void solve_top_edges(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3102
A piecewise constant coefficient with the constants keyed off the element attribute numbers...
void mark_elements(Mesh &mesh, char axis, int tier)
Definition: rubik.cpp:1104
virtual void Print(std::ostream &os=mfem::out) const
Definition: mesh.hpp:1671
void interactive_help()
Definition: rubik.cpp:360
void solve_bot(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4918
void solve_top_corners(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2064
void determine_random_moves(Array< Move > &moves)
Definition: rubik.cpp:1176
void PrintOptions(std::ostream &out) const
Print the options.
Definition: optparser.cpp:324
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Definition: gridfunc.cpp:2399
void init_state()
Definition: rubik.cpp:552
void twist_corners(Mesh &mesh, GridFunction &color, socketstream &sock, bool cw, int *c0=NULL, int *c1=NULL, int *c2=NULL)
Definition: rubik.cpp:3639
void SetAttribute(int i, int attr)
Set the attribute of element i.
Definition: mesh.hpp:1483
void move_to_c5(int i5, int o5, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1619
Vector data type.
Definition: vector.hpp:60
bool anim_step(char axis, int incr, Mesh &mesh)
Definition: rubik.cpp:1076
void repaint_cube(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:902
bool validate_corners(const int max_ind=8)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
void move_to_e9(int i9, int o9, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2716
void solve_top_center(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1220
int GetAttribute(int i) const
Return the attribute of element i.
Definition: mesh.hpp:1480
void solve_mid_edges(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3187
int locate_edge(int ind)
Definition: rubik.cpp:2133
void move_to_e11(int i11, int o11, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2989
void GetBdrElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of boundary element i.
Definition: mesh.hpp:1113
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
Definition: mesh.hpp:1109
int main()
void update_state(char axis, int tier, int incr)
Definition: rubik.cpp:856
Arbitrary order &quot;L2-conforming&quot; discontinuous finite elements.
Definition: fe_coll.hpp:288
bool Good() const
Return true if the command line options were parsed successfully.
Definition: optparser.hpp:150