MFEM  v4.6.0
Finite element discretization library
rubik.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2023, 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;
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  Array<int> v;
1110  for (int i=0; i<mesh.GetNE(); i++)
1111  {
1112  mesh.GetElementVertices(i, v);
1113 
1114  x = 0.0;
1115  for (int j=0; j<v.Size(); j++)
1116  {
1117  Vector vx(mesh.GetVertex(v[j]), 3);
1118  x += vx;
1119  }
1120  x /= v.Size();
1121 
1122  switch (axis)
1123  {
1124  case 'x':
1125  if ( x[0] > -2.5 + tier && x[0] < -1.5 + tier )
1126  {
1127  mesh.SetAttribute(i, 2);
1128  }
1129  else
1130  {
1131  mesh.SetAttribute(i, 1);
1132  }
1133  break;
1134  case 'y':
1135  if ( x[1] > -2.5 + tier && x[1] < -1.5 + tier )
1136  {
1137  mesh.SetAttribute(i, 2);
1138  }
1139  else
1140  {
1141  mesh.SetAttribute(i, 1);
1142  }
1143  break;
1144  case 'z':
1145  if ( x[2] > -2.5 + tier && x[2] < -1.5 + tier )
1146  {
1147  mesh.SetAttribute(i, 2);
1148  }
1149  else
1150  {
1151  mesh.SetAttribute(i, 1);
1152  }
1153  break;
1154  }
1155  }
1156 }
1157 
1158 void
1159 anim_move(char axis, int tier, int incr,
1160  Mesh & mesh, GridFunction & color, socketstream & sock)
1161 {
1162  update_state(axis, tier, incr);
1163  mark_elements(mesh, axis, tier);
1164  while (anim_step(axis, incr, mesh))
1165  {
1166  sock << "solution\n" << mesh << color << flush;
1167  }
1168  count_++;
1169 }
1170 
1172 {
1173  for (int i=0; i<moves.Size(); i++)
1174  {
1175  double ran = double(rand()) / RAND_MAX;
1176  int ir = (int)(26 * ran);
1177  int incr = (ir % 3) + 1; ir /= 3;
1178  int tier = (ir % 3) + 1; ir /= 3;
1179  char axis = (ir == 0)? 'x' : ((ir == 1) ? 'y' : 'z');
1180 
1181  if (i == 0)
1182  {
1183  moves[i].axis = axis;
1184  moves[i].tier = tier;
1185  moves[i].incr = incr;
1186  }
1187  else if (axis == moves[i-1].axis)
1188  {
1189  if (tier == moves[i-1].tier)
1190  {
1191  int new_incr = (moves[i-1].incr + incr) % 4;
1192  if (new_incr != 0)
1193  {
1194  moves[i-1].incr = new_incr;
1195  }
1196  i--;
1197  }
1198  else if (incr == moves[i-1].incr)
1199  {
1200  moves[i-1].tier = 6 - moves[i-1].tier - tier;
1201  moves[i-1].incr = 4 - incr;
1202  i--;
1203  }
1204  }
1205  else
1206  {
1207  moves[i].axis = axis;
1208  moves[i].tier = tier;
1209  moves[i].incr = incr;
1210  }
1211  }
1212 }
1213 
1214 void
1216 {
1217  int i5 = -1;
1218  for (int i=0; i<6; i++)
1219  {
1220  if (rubik.cent_[i] == 5)
1221  {
1222  i5 = i;
1223  break;
1224  }
1225  }
1226  switch (i5)
1227  {
1228  case 0:
1229  anim_move('x', 2, 2, mesh, color, sock);
1230  break;
1231  case 1:
1232  anim_move('x', 2, 1, mesh, color, sock);
1233  break;
1234  case 2:
1235  anim_move('y', 2, 1, mesh, color, sock);
1236  break;
1237  case 3:
1238  anim_move('x', 2, 3, mesh, color, sock);
1239  break;
1240  case 4:
1241  anim_move('y', 2, 3, mesh, color, sock);
1242  break;
1243  case 5:
1244  // Do nothing
1245  break;
1246  }
1247 }
1248 
1249 void
1251 {
1252  // Centers are either all correct, all wrong, or two are correct.
1253  // Check for two being correct
1254  bool allWrong = true;
1255  bool allRight = true;
1256  for (int i=0; i<6; i++)
1257  {
1258  if (rubik.cent_[i] == i)
1259  {
1260  allWrong = false;
1261  }
1262  else
1263  {
1264  allRight = false;
1265  }
1266  }
1267 
1268  // If the centers are already correct then return.
1269  if (allRight) { return; }
1270 
1271  if (!allWrong)
1272  {
1273  // Two are correct. Determine which axis should be spun and by how much.
1274  char axis = ' ';
1275  int incr = 0;
1276 
1277  if (rubik.cent_[2] == 2)
1278  {
1279  axis = 'x';
1280 
1281  switch (rubik.cent_[0])
1282  {
1283  case 1:
1284  incr = 1;
1285  break;
1286  case 5:
1287  incr = 2;
1288  break;
1289  case 3:
1290  incr = 3;
1291  break;
1292  }
1293  }
1294  else if (rubik.cent_[1] == 1)
1295  {
1296  axis = 'y';
1297 
1298  switch (rubik.cent_[0])
1299  {
1300  case 2:
1301  incr = 1;
1302  break;
1303  case 5:
1304  incr = 2;
1305  break;
1306  case 4:
1307  incr = 3;
1308  break;
1309  }
1310  }
1311  else
1312  {
1313  axis = 'z';
1314 
1315  switch (rubik.cent_[1])
1316  {
1317  case 4:
1318  incr = 1;
1319  break;
1320  case 3:
1321  incr = 2;
1322  break;
1323  case 2:
1324  incr = 3;
1325  break;
1326  }
1327  }
1328  anim_move(axis, 2, incr, mesh, color, sock);
1329  }
1330  else
1331  {
1332  // They are all incorrect. Find the bottom center and move it into place.
1333  int i0 = -1;
1334  for (int i=1; i<6; i++)
1335  {
1336  if (rubik.cent_[i] == 0)
1337  {
1338  i0 = i;
1339  break;
1340  }
1341  }
1342 
1343  char axis = ' ';
1344  int incr = 0;
1345  switch (i0)
1346  {
1347  case 1:
1348  axis = 'x'; incr = 3;
1349  break;
1350  case 2:
1351  axis = 'y'; incr = 3;
1352  break;
1353  case 3:
1354  axis = 'x'; incr = 1;
1355  break;
1356  case 4:
1357  axis = 'y'; incr = 1;
1358  break;
1359  case 5:
1360  axis = 'x'; incr = 2;
1361  break;
1362  }
1363  anim_move(axis, 2, incr, mesh, color, sock);
1364 
1365  // Two centers should be correct now so recall this function.
1366  solve_centers(mesh, color, sock);
1367  }
1368 }
1369 
1370 int
1372 {
1373  for (int i=0; i<8; i++)
1374  {
1375  if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 0] &&
1376  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 1] &&
1377  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 2])
1378  {
1379  return i;
1380  }
1381  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 1] &&
1382  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 2] &&
1383  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 0])
1384  {
1385  return i + 8;
1386  }
1387  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 2] &&
1388  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 0] &&
1389  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 1])
1390  {
1391  return i + 16;
1392  }
1393  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 2] &&
1394  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 1] &&
1395  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 0])
1396  {
1397  return i + 24;
1398  }
1399  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 1] &&
1400  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 0] &&
1401  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 2])
1402  {
1403  return i + 32;
1404  }
1405  else if (rubik.corn_[3 * i + 0] == corn_colors_[3 * ind + 0] &&
1406  rubik.corn_[3 * i + 1] == corn_colors_[3 * ind + 2] &&
1407  rubik.corn_[3 * i + 2] == corn_colors_[3 * ind + 1])
1408  {
1409  return i + 40;
1410  }
1411  }
1412  return -1;
1413 }
1414 
1415 void
1416 move_to_c4(int i4, int o4,
1417  Mesh & mesh, GridFunction & color, socketstream & sock)
1418 {
1419  switch (i4)
1420  {
1421  case 0:
1422  switch (o4)
1423  {
1424  case 3:
1425  anim_move('x', 1, 3, mesh, color, sock);
1426  anim_move('z', 1, 3, mesh, color, sock);
1427  anim_move('x', 1, 1, mesh, color, sock);
1428  break;
1429  case 4:
1430  anim_move('y', 1, 1, mesh, color, sock);
1431  anim_move('z', 1, 3, mesh, color, sock);
1432  anim_move('y', 1, 3, mesh, color, sock);
1433  anim_move('x', 1, 3, mesh, color, sock);
1434  anim_move('z', 1, 2, mesh, color, sock);
1435  anim_move('x', 1, 1, mesh, color, sock);
1436  break;
1437  case 5:
1438  anim_move('y', 1, 1, mesh, color, sock);
1439  anim_move('z', 1, 1, mesh, color, sock);
1440  anim_move('y', 1, 3, mesh, color, sock);
1441  break;
1442  }
1443  break;
1444  case 1:
1445  switch (o4)
1446  {
1447  case 0:
1448  anim_move('x', 2, 1, mesh, color, sock);
1449  anim_move('y', 1, 2, mesh, color, sock);
1450  anim_move('x', 2, 3, mesh, color, sock);
1451  break;
1452  case 1:
1453  anim_move('z', 1, 1, mesh, color, sock);
1454  anim_move('x', 2, 1, mesh, color, sock);
1455  anim_move('y', 1, 3, mesh, color, sock);
1456  anim_move('x', 2, 3, mesh, color, sock);
1457  break;
1458  case 2:
1459  anim_move('x', 1, 3, mesh, color, sock);
1460  anim_move('z', 1, 1, mesh, color, sock);
1461  anim_move('x', 1, 1, mesh, color, sock);
1462  break;
1463  }
1464  break;
1465  case 2:
1466  switch (o4)
1467  {
1468  case 3:
1469  anim_move('y', 1, 1, mesh, color, sock);
1470  anim_move('z', 1, 2, mesh, color, sock);
1471  anim_move('y', 1, 3, mesh, color, sock);
1472  break;
1473  case 4:
1474  anim_move('x', 3, 1, mesh, color, sock);
1475  anim_move('z', 1, 1, mesh, color, sock);
1476  anim_move('x', 3, 3, mesh, color, sock);
1477  anim_move('x', 2, 1, mesh, color, sock);
1478  anim_move('y', 1, 3, mesh, color, sock);
1479  anim_move('x', 2, 3, mesh, color, sock);
1480  break;
1481  case 5:
1482  anim_move('x', 1, 3, mesh, color, sock);
1483  anim_move('z', 1, 2, mesh, color, sock);
1484  anim_move('x', 1, 1, mesh, color, sock);
1485  break;
1486  }
1487  break;
1488  case 3:
1489  switch (o4)
1490  {
1491  case 0:
1492  anim_move('y', 2, 3, mesh, color, sock);
1493  anim_move('x', 1, 2, mesh, color, sock);
1494  anim_move('y', 2, 1, mesh, color, sock);
1495  break;
1496  case 1:
1497  anim_move('y', 1, 1, mesh, color, sock);
1498  anim_move('z', 1, 3, mesh, color, sock);
1499  anim_move('y', 1, 3, mesh, color, sock);
1500  break;
1501  case 2:
1502  anim_move('z', 1, 3, mesh, color, sock);
1503  anim_move('y', 1, 1, mesh, color, sock);
1504  anim_move('z', 1, 1, mesh, color, sock);
1505  anim_move('y', 1, 3, mesh, color, sock);
1506  break;
1507  }
1508  break;
1509  case 4:
1510  switch (o4)
1511  {
1512  case 1:
1513  anim_move('y', 1, 1, mesh, color, sock);
1514  anim_move('z', 1, 1, mesh, color, sock);
1515  anim_move('y', 1, 3, mesh, color, sock);
1516  anim_move('z', 1, 3, mesh, color, sock);
1517  anim_move('y', 1, 1, mesh, color, sock);
1518  anim_move('z', 1, 1, mesh, color, sock);
1519  anim_move('y', 1, 3, mesh, color, sock);
1520  break;
1521  case 2:
1522  anim_move('x', 1, 3, mesh, color, sock);
1523  anim_move('z', 1, 3, mesh, color, sock);
1524  anim_move('x', 1, 1, mesh, color, sock);
1525  anim_move('z', 1, 1, mesh, color, sock);
1526  anim_move('x', 1, 3, mesh, color, sock);
1527  anim_move('z', 1, 3, mesh, color, sock);
1528  anim_move('x', 1, 1, mesh, color, sock);
1529  break;
1530  }
1531  break;
1532  case 5:
1533  switch (o4)
1534  {
1535  case 3:
1536  anim_move('x', 2, 1, mesh, color, sock);
1537  anim_move('y', 1, 1, mesh, color, sock);
1538  anim_move('x', 2, 3, mesh, color, sock);
1539  break;
1540  case 4:
1541  anim_move('x', 3, 3, mesh, color, sock);
1542  anim_move('z', 1, 1, mesh, color, sock);
1543  anim_move('x', 3, 1, mesh, color, sock);
1544  anim_move('x', 1, 3, mesh, color, sock);
1545  anim_move('z', 1, 3, mesh, color, sock);
1546  anim_move('x', 1, 1, mesh, color, sock);
1547  break;
1548  case 5:
1549  anim_move('y', 1, 3, mesh, color, sock);
1550  anim_move('z', 1, 3, mesh, color, sock);
1551  anim_move('y', 1, 2, mesh, color, sock);
1552  anim_move('z', 1, 2, mesh, color, sock);
1553  anim_move('y', 1, 3, mesh, color, sock);
1554  break;
1555  }
1556  break;
1557  case 6:
1558  switch (o4)
1559  {
1560  case 0:
1561  anim_move('y', 1, 1, mesh, color, sock);
1562  anim_move('y', 3, 3, mesh, color, sock);
1563  anim_move('z', 1, 2, mesh, color, sock);
1564  anim_move('y', 3, 1, mesh, color, sock);
1565  anim_move('y', 1, 3, mesh, color, sock);
1566  break;
1567  case 1:
1568  anim_move('x', 3, 1, mesh, color, sock);
1569  anim_move('z', 1, 1, mesh, color, sock);
1570  anim_move('x', 3, 3, mesh, color, sock);
1571  anim_move('x', 1, 3, mesh, color, sock);
1572  anim_move('z', 1, 2, mesh, color, sock);
1573  anim_move('x', 1, 1, mesh, color, sock);
1574  break;
1575  case 2:
1576  anim_move('y', 3, 3, mesh, color, sock);
1577  anim_move('z', 1, 3, mesh, color, sock);
1578  anim_move('y', 3, 1, mesh, color, sock);
1579  anim_move('y', 1, 1, mesh, color, sock);
1580  anim_move('z', 1, 2, mesh, color, sock);
1581  anim_move('y', 1, 3, mesh, color, sock);
1582  break;
1583  }
1584  break;
1585  case 7:
1586  switch (o4)
1587  {
1588  case 3:
1589  anim_move('x', 1, 1, mesh, color, sock);
1590  anim_move('z', 1, 1, mesh, color, sock);
1591  anim_move('x', 1, 2, mesh, color, sock);
1592  anim_move('z', 1, 2, mesh, color, sock);
1593  anim_move('x', 1, 1, mesh, color, sock);
1594  break;
1595  case 4:
1596  anim_move('y', 3, 1, mesh, color, sock);
1597  anim_move('z', 1, 3, mesh, color, sock);
1598  anim_move('y', 3, 3, mesh, color, sock);
1599  anim_move('y', 1, 1, mesh, color, sock);
1600  anim_move('z', 1, 1, mesh, color, sock);
1601  anim_move('y', 1, 3, mesh, color, sock);
1602  break;
1603  case 5:
1604  anim_move('y', 2, 3, mesh, color, sock);
1605  anim_move('x', 1, 3, mesh, color, sock);
1606  anim_move('y', 2, 1, mesh, color, sock);
1607  break;
1608  }
1609  break;
1610  }
1611 }
1612 
1613 void
1614 move_to_c5(int i5, int o5,
1615  Mesh & mesh, GridFunction & color, socketstream & sock)
1616 {
1617  switch (i5)
1618  {
1619  case 0:
1620  switch (o5)
1621  {
1622  case 0:
1623  anim_move('z', 1, 2, mesh, color, sock);
1624  anim_move('y', 2, 1, mesh, color, sock);
1625  anim_move('x', 3, 2, mesh, color, sock);
1626  anim_move('y', 2, 3, mesh, color, sock);
1627  break;
1628  case 1:
1629  anim_move('z', 1, 3, mesh, color, sock);
1630  anim_move('x', 3, 3, mesh, color, sock);
1631  anim_move('z', 1, 1, mesh, color, sock);
1632  anim_move('x', 3, 1, mesh, color, sock);
1633  break;
1634  case 2:
1635  anim_move('x', 3, 3, mesh, color, sock);
1636  anim_move('z', 1, 3, mesh, color, sock);
1637  anim_move('x', 3, 1, mesh, color, sock);
1638  break;
1639  }
1640  break;
1641  case 1:
1642  switch (o5)
1643  {
1644  case 3:
1645  anim_move('x', 3, 3, mesh, color, sock);
1646  anim_move('z', 1, 1, mesh, color, sock);
1647  anim_move('x', 3, 1, mesh, color, sock);
1648  break;
1649  case 4:
1650  anim_move('y', 1, 3, mesh, color, sock);
1651  anim_move('z', 1, 1, mesh, color, sock);
1652  anim_move('y', 1, 1, mesh, color, sock);
1653  anim_move('x', 3, 3, mesh, color, sock);
1654  anim_move('z', 1, 2, mesh, color, sock);
1655  anim_move('x', 3, 1, mesh, color, sock);
1656  break;
1657  case 5:
1658  anim_move('y', 1, 3, mesh, color, sock);
1659  anim_move('z', 1, 3, mesh, color, sock);
1660  anim_move('y', 1, 1, mesh, color, sock);
1661  break;
1662  }
1663  break;
1664  case 2:
1665  switch (o5)
1666  {
1667  case 0:
1668  anim_move('y', 2, 1, mesh, color, sock);
1669  anim_move('x', 3, 2, mesh, color, sock);
1670  anim_move('y', 2, 3, mesh, color, sock);
1671  break;
1672  case 1:
1673  anim_move('y', 1, 3, mesh, color, sock);
1674  anim_move('z', 1, 1, mesh, color, sock);
1675  anim_move('y', 1, 1, mesh, color, sock);
1676  break;
1677  case 2:
1678  anim_move('z', 1, 1, mesh, color, sock);
1679  anim_move('y', 2, 1, mesh, color, sock);
1680  anim_move('x', 3, 1, mesh, color, sock);
1681  anim_move('y', 2, 3, mesh, color, sock);
1682  break;
1683  }
1684  break;
1685  case 3:
1686  switch (o5)
1687  {
1688  case 3:
1689  anim_move('y', 1, 3, mesh, color, sock);
1690  anim_move('z', 1, 2, mesh, color, sock);
1691  anim_move('y', 1, 1, mesh, color, sock);
1692  break;
1693  case 4:
1694  anim_move('z', 1, 1, mesh, color, sock);
1695  anim_move('y', 2, 1, mesh, color, sock);
1696  anim_move('x', 3, 2, mesh, color, sock);
1697  anim_move('y', 2, 3, mesh, color, sock);
1698  break;
1699  case 5:
1700  anim_move('x', 3, 3, mesh, color, sock);
1701  anim_move('z', 1, 2, mesh, color, sock);
1702  anim_move('x', 3, 1, mesh, color, sock);
1703  break;
1704  }
1705  break;
1706  case 5:
1707  switch (o5)
1708  {
1709  case 1:
1710  anim_move('y', 1, 3, mesh, color, sock);
1711  anim_move('z', 1, 3, mesh, color, sock);
1712  anim_move('y', 1, 1, mesh, color, sock);
1713  anim_move('z', 1, 1, mesh, color, sock);
1714  anim_move('y', 1, 3, mesh, color, sock);
1715  anim_move('z', 1, 3, mesh, color, sock);
1716  anim_move('y', 1, 1, mesh, color, sock);
1717  break;
1718  case 2:
1719  anim_move('x', 3, 3, mesh, color, sock);
1720  anim_move('z', 1, 1, mesh, color, sock);
1721  anim_move('x', 3, 1, mesh, color, sock);
1722  anim_move('z', 1, 3, mesh, color, sock);
1723  anim_move('x', 3, 3, mesh, color, sock);
1724  anim_move('z', 1, 1, mesh, color, sock);
1725  anim_move('x', 3, 1, mesh, color, sock);
1726  break;
1727  }
1728  break;
1729  case 6:
1730  switch (o5)
1731  {
1732  case 3:
1733  anim_move('x', 3, 1, mesh, color, sock);
1734  anim_move('z', 1, 3, mesh, color, sock);
1735  anim_move('x', 3, 2, mesh, color, sock);
1736  anim_move('z', 1, 2, mesh, color, sock);
1737  anim_move('x', 3, 1, mesh, color, sock);
1738  break;
1739  case 4:
1740  anim_move('y', 3, 3, mesh, color, sock);
1741  anim_move('z', 1, 1, mesh, color, sock);
1742  anim_move('y', 3, 1, mesh, color, sock);
1743  anim_move('y', 1, 3, mesh, color, sock);
1744  anim_move('z', 1, 3, mesh, color, sock);
1745  anim_move('y', 1, 1, mesh, color, sock);
1746  break;
1747  case 5:
1748  anim_move('y', 2, 1, mesh, color, sock);
1749  anim_move('x', 3, 3, mesh, color, sock);
1750  anim_move('y', 2, 3, mesh, color, sock);
1751  break;
1752  }
1753  break;
1754  case 7:
1755  switch (o5)
1756  {
1757  case 0:
1758  anim_move('y', 1, 3, mesh, color, sock);
1759  anim_move('y', 3, 1, mesh, color, sock);
1760  anim_move('z', 1, 2, mesh, color, sock);
1761  anim_move('y', 3, 3, mesh, color, sock);
1762  anim_move('y', 1, 1, mesh, color, sock);
1763  break;
1764  case 1:
1765  anim_move('x', 1, 1, mesh, color, sock);
1766  anim_move('z', 1, 3, mesh, color, sock);
1767  anim_move('x', 1, 3, mesh, color, sock);
1768  anim_move('x', 3, 3, mesh, color, sock);
1769  anim_move('z', 1, 2, mesh, color, sock);
1770  anim_move('x', 3, 1, mesh, color, sock);
1771  break;
1772  case 2:
1773  anim_move('y', 3, 1, mesh, color, sock);
1774  anim_move('z', 1, 1, mesh, color, sock);
1775  anim_move('y', 3, 3, mesh, color, sock);
1776  anim_move('y', 1, 3, mesh, color, sock);
1777  anim_move('z', 1, 2, mesh, color, sock);
1778  anim_move('y', 1, 1, mesh, color, sock);
1779  break;
1780  }
1781  break;
1782  }
1783 }
1784 
1785 void
1786 move_to_c6(int i6, int o6,
1787  Mesh & mesh, GridFunction & color, socketstream & sock)
1788 {
1789  switch (i6)
1790  {
1791  case 0:
1792  switch (o6)
1793  {
1794  case 3:
1795  anim_move('y', 3, 3, mesh, color, sock);
1796  anim_move('z', 1, 2, mesh, color, sock);
1797  anim_move('y', 3, 1, mesh, color, sock);
1798  break;
1799  case 4:
1800  anim_move('z', 1, 1, mesh, color, sock);
1801  anim_move('x', 2, 3, mesh, color, sock);
1802  anim_move('y', 3, 2, mesh, color, sock);
1803  anim_move('x', 2, 1, mesh, color, sock);
1804  break;
1805  case 5:
1806  anim_move('x', 3, 1, mesh, color, sock);
1807  anim_move('z', 1, 2, mesh, color, sock);
1808  anim_move('x', 3, 3, mesh, color, sock);
1809  break;
1810  }
1811  break;
1812  case 1:
1813  switch (o6)
1814  {
1815  case 0:
1816  anim_move('z', 1, 2, mesh, color, sock);
1817  anim_move('x', 2, 3, mesh, color, sock);
1818  anim_move('y', 3, 2, mesh, color, sock);
1819  anim_move('x', 2, 1, mesh, color, sock);
1820  break;
1821  case 1:
1822  anim_move('y', 3, 3, mesh, color, sock);
1823  anim_move('z', 1, 3, mesh, color, sock);
1824  anim_move('y', 3, 1, mesh, color, sock);
1825  break;
1826  case 2:
1827  anim_move('z', 1, 1, mesh, color, sock);
1828  anim_move('x', 3, 1, mesh, color, sock);
1829  anim_move('z', 1, 2, mesh, color, sock);
1830  anim_move('x', 3, 3, mesh, color, sock);
1831  break;
1832  }
1833  break;
1834  case 2:
1835  switch (o6)
1836  {
1837  case 3:
1838  anim_move('x', 3, 1, mesh, color, sock);
1839  anim_move('z', 1, 3, mesh, color, sock);
1840  anim_move('x', 3, 3, mesh, color, sock);
1841  break;
1842  case 4:
1843  anim_move('x', 3, 1, mesh, color, sock);
1844  anim_move('z', 1, 1, mesh, color, sock);
1845  anim_move('x', 3, 3, mesh, color, sock);
1846  anim_move('y', 3, 3, mesh, color, sock);
1847  anim_move('z', 1, 2, mesh, color, sock);
1848  anim_move('y', 3, 1, mesh, color, sock);
1849  break;
1850  case 5:
1851  anim_move('y', 3, 3, mesh, color, sock);
1852  anim_move('z', 1, 1, mesh, color, sock);
1853  anim_move('y', 3, 1, mesh, color, sock);
1854  break;
1855  }
1856  break;
1857  case 3:
1858  switch (o6)
1859  {
1860  case 0:
1861  anim_move('x', 2, 3, mesh, color, sock);
1862  anim_move('y', 3, 2, mesh, color, sock);
1863  anim_move('x', 2, 1, mesh, color, sock);
1864  break;
1865  case 1:
1866  anim_move('z', 1, 1, mesh, color, sock);
1867  anim_move('x', 2, 3, mesh, color, sock);
1868  anim_move('y', 3, 1, mesh, color, sock);
1869  anim_move('x', 2, 1, mesh, color, sock);
1870  break;
1871  case 2:
1872  anim_move('x', 3, 1, mesh, color, sock);
1873  anim_move('z', 1, 1, mesh, color, sock);
1874  anim_move('x', 3, 3, mesh, color, sock);
1875  break;
1876  }
1877  break;
1878  case 6:
1879  switch (o6)
1880  {
1881  case 1:
1882  anim_move('y', 3, 3, mesh, color, sock);
1883  anim_move('z', 1, 1, mesh, color, sock);
1884  anim_move('y', 3, 1, mesh, color, sock);
1885  anim_move('z', 1, 3, mesh, color, sock);
1886  anim_move('y', 3, 3, mesh, color, sock);
1887  anim_move('z', 1, 1, mesh, color, sock);
1888  anim_move('y', 3, 1, mesh, color, sock);
1889  break;
1890  case 2:
1891  anim_move('x', 3, 1, mesh, color, sock);
1892  anim_move('z', 1, 3, mesh, color, sock);
1893  anim_move('x', 3, 3, mesh, color, sock);
1894  anim_move('z', 1, 1, mesh, color, sock);
1895  anim_move('x', 3, 1, mesh, color, sock);
1896  anim_move('z', 1, 3, mesh, color, sock);
1897  anim_move('x', 3, 3, mesh, color, sock);
1898  break;
1899  }
1900  break;
1901  case 7:
1902  switch (o6)
1903  {
1904  case 3:
1905  anim_move('x', 2, 3, mesh, color, sock);
1906  anim_move('y', 3, 3, mesh, color, sock);
1907  anim_move('x', 2, 1, mesh, color, sock);
1908  break;
1909  case 4:
1910  anim_move('x', 1, 1, mesh, color, sock);
1911  anim_move('z', 1, 1, mesh, color, sock);
1912  anim_move('x', 1, 3, mesh, color, sock);
1913  anim_move('x', 3, 1, mesh, color, sock);
1914  anim_move('z', 1, 3, mesh, color, sock);
1915  anim_move('x', 3, 3, mesh, color, sock);
1916  break;
1917  case 5:
1918  anim_move('y', 3, 1, mesh, color, sock);
1919  anim_move('z', 1, 3, mesh, color, sock);
1920  anim_move('y', 3, 2, mesh, color, sock);
1921  anim_move('z', 1, 2, mesh, color, sock);
1922  anim_move('y', 3, 1, mesh, color, sock);
1923  break;
1924  }
1925  break;
1926  }
1927 }
1928 
1929 void
1930 move_to_c7(int i7, int o7,
1931  Mesh & mesh, GridFunction & color, socketstream & sock)
1932 {
1933  switch (i7)
1934  {
1935  case 0:
1936  switch (o7)
1937  {
1938  case 0:
1939  anim_move('z', 1, 1, mesh, color, sock);
1940  anim_move('y', 3, 1, mesh, color, sock);
1941  anim_move('z', 1, 1, mesh, color, sock);
1942  anim_move('y', 3, 3, mesh, color, sock);
1943  anim_move('x', 1, 1, mesh, color, sock);
1944  anim_move('z', 1, 2, mesh, color, sock);
1945  anim_move('x', 1, 3, mesh, color, sock);
1946  break;
1947  case 1:
1948  anim_move('y', 3, 1, mesh, color, sock);
1949  anim_move('z', 1, 1, mesh, color, sock);
1950  anim_move('y', 3, 3, mesh, color, sock);
1951  break;
1952  case 2:
1953  anim_move('z', 1, 3, mesh, color, sock);
1954  anim_move('x', 1, 1, mesh, color, sock);
1955  anim_move('z', 1, 2, mesh, color, sock);
1956  anim_move('x', 1, 3, mesh, color, sock);
1957  break;
1958  }
1959  break;
1960  case 1:
1961  switch (o7)
1962  {
1963  case 3:
1964  anim_move('y', 3, 1, mesh, color, sock);
1965  anim_move('z', 1, 2, mesh, color, sock);
1966  anim_move('y', 3, 3, mesh, color, sock);
1967  break;
1968  case 4:
1969  anim_move('z', 1, 2, mesh, color, sock);
1970  anim_move('x', 1, 1, mesh, color, sock);
1971  anim_move('z', 1, 3, mesh, color, sock);
1972  anim_move('x', 1, 3, mesh, color, sock);
1973  anim_move('y', 3, 1, mesh, color, sock);
1974  anim_move('z', 1, 2, mesh, color, sock);
1975  anim_move('y', 3, 3, mesh, color, sock);
1976  break;
1977  case 5:
1978  anim_move('x', 1, 1, mesh, color, sock);
1979  anim_move('z', 1, 2, mesh, color, sock);
1980  anim_move('x', 1, 3, mesh, color, sock);
1981  break;
1982  }
1983  break;
1984  case 2:
1985  switch (o7)
1986  {
1987  case 0:
1988  anim_move('z', 1, 3, mesh, color, sock);
1989  anim_move('x', 1, 1, mesh, color, sock);
1990  anim_move('z', 1, 3, mesh, color, sock);
1991  anim_move('x', 1, 3, mesh, color, sock);
1992  anim_move('y', 3, 1, mesh, color, sock);
1993  anim_move('z', 1, 2, mesh, color, sock);
1994  anim_move('y', 3, 3, mesh, color, sock);
1995  break;
1996  case 1:
1997  anim_move('z', 1, 1, mesh, color, sock);
1998  anim_move('y', 3, 1, mesh, color, sock);
1999  anim_move('z', 1, 2, mesh, color, sock);
2000  anim_move('y', 3, 3, mesh, color, sock);
2001  break;
2002  case 2:
2003  anim_move('x', 1, 1, mesh, color, sock);
2004  anim_move('z', 1, 3, mesh, color, sock);
2005  anim_move('x', 1, 3, mesh, color, sock);
2006  break;
2007  }
2008  break;
2009  case 3:
2010  switch (o7)
2011  {
2012  case 3:
2013  anim_move('x', 1, 1, mesh, color, sock);
2014  anim_move('z', 1, 1, mesh, color, sock);
2015  anim_move('x', 1, 3, mesh, color, sock);
2016  break;
2017  case 4:
2018  anim_move('y', 3, 1, mesh, color, sock);
2019  anim_move('z', 1, 1, mesh, color, sock);
2020  anim_move('y', 3, 3, mesh, color, sock);
2021  anim_move('x', 1, 1, mesh, color, sock);
2022  anim_move('z', 1, 2, mesh, color, sock);
2023  anim_move('x', 1, 3, mesh, color, sock);
2024  break;
2025  case 5:
2026  anim_move('y', 3, 1, mesh, color, sock);
2027  anim_move('z', 1, 3, mesh, color, sock);
2028  anim_move('y', 3, 3, mesh, color, sock);
2029  break;
2030  }
2031  break;
2032  case 7:
2033  switch (o7)
2034  {
2035  case 1:
2036  anim_move('y', 3, 1, mesh, color, sock);
2037  anim_move('z', 1, 3, mesh, color, sock);
2038  anim_move('y', 3, 3, mesh, color, sock);
2039  anim_move('z', 1, 1, mesh, color, sock);
2040  anim_move('y', 3, 1, mesh, color, sock);
2041  anim_move('z', 1, 3, mesh, color, sock);
2042  anim_move('y', 3, 3, mesh, color, sock);
2043  break;
2044  case 2:
2045  anim_move('x', 1, 1, mesh, color, sock);
2046  anim_move('z', 1, 1, mesh, color, sock);
2047  anim_move('x', 1, 3, mesh, color, sock);
2048  anim_move('z', 1, 3, mesh, color, sock);
2049  anim_move('x', 1, 1, mesh, color, sock);
2050  anim_move('z', 1, 1, mesh, color, sock);
2051  anim_move('x', 1, 3, mesh, color, sock);
2052  break;
2053  }
2054  break;
2055  }
2056 }
2057 
2058 void
2060 {
2061  if (logging_ > 1)
2062  {
2063  cout << "Entering solve_top_corners" << endl;
2064  }
2065  if (logging_ > 2)
2066  {
2067  print_state(cout);
2068  }
2069 
2070  // Locate first incorrectly filled corner location in the top tier
2071  int l4 = locate_corner(4);
2072  int i4 = l4 % 8;
2073  int o4 = l4 / 8;
2074  if (logging_ > 1)
2075  {
2076  cout << "Location of 4-th corner: " << i4
2077  << " with orientation " << o4 << endl;
2078  }
2079  if (i4 >= 0)
2080  {
2081  move_to_c4(i4, o4, mesh, color, sock);
2082  }
2083 
2084  // Locate second incorrectly filled corner location in the top tier
2085  int l5 = locate_corner(5);
2086  int i5 = l5 % 8;
2087  int o5 = l5 / 8;
2088  if (logging_ > 1)
2089  {
2090  cout << "Location of 5-th corner: " << i5
2091  << " with orientation " << o5 << endl;
2092  }
2093  if (i5 >= 0)
2094  {
2095  move_to_c5(i5, o5, mesh, color, sock);
2096  }
2097 
2098  // Locate third incorrectly filled corner location in the top tier
2099  int l6 = locate_corner(6);
2100  int i6 = l6 % 8;
2101  int o6 = l6 / 8;
2102  if (logging_ > 1)
2103  {
2104  cout << "Location of 6-th corner: " << i6
2105  << " with orientation " << o6 << endl;
2106  }
2107  if (i6 >= 0)
2108  {
2109  move_to_c6(i6, o6, mesh, color, sock);
2110  }
2111 
2112  // Locate fourth incorrectly filled corner location in the top tier
2113  int l7 = locate_corner(7);
2114  int i7 = l7 % 8;
2115  int o7 = l7 / 8;
2116  if (logging_ > 1)
2117  {
2118  cout << "Location of 7-th corner: " << i7
2119  << " with orientation " << o7 << endl;
2120  }
2121  if (i7 >= 0)
2122  {
2123  move_to_c7(i7, o7, mesh, color, sock);
2124  }
2125 }
2126 
2127 int
2128 locate_edge(int ind)
2129 {
2130  for (int i=0; i<12; i++)
2131  {
2132  if ((rubik.edge_[2 * i + 0] == edge_colors_[2 * ind + 0] &&
2133  rubik.edge_[2 * i + 1] == edge_colors_[2 * ind + 1]))
2134  {
2135  return i;
2136  }
2137  if ((rubik.edge_[2 * i + 0] == edge_colors_[2 * ind + 1] &&
2138  rubik.edge_[2 * i + 1] == edge_colors_[2 * ind + 0]))
2139  {
2140  return -i - 1;
2141  }
2142  }
2143  return -99;
2144 }
2145 
2146 void
2147 move_to_e4(int i4, int o4,
2148  Mesh & mesh, GridFunction & color, socketstream & sock)
2149 {
2150  if (o4 == 0)
2151  {
2152  switch (i4)
2153  {
2154  case 0:
2155  anim_move('y', 2, 1, mesh, color, sock);
2156  anim_move('x', 2, 1, mesh, color, sock);
2157  anim_move('y', 2, 3, mesh, color, sock);
2158  break;
2159  case 1:
2160  anim_move('x', 3, 1, mesh, color, sock);
2161  anim_move('y', 1, 1, mesh, color, sock);
2162  break;
2163  case 2:
2164  anim_move('y', 3, 2, mesh, color, sock);
2165  anim_move('z', 3, 2, mesh, color, sock);
2166  break;
2167  case 3:
2168  anim_move('x', 1, 2, mesh, color, sock);
2169  anim_move('z', 3, 3, mesh, color, sock);
2170  break;
2171  case 5:
2172  anim_move('z', 3, 1, mesh, color, sock);
2173  break;
2174  case 6:
2175  anim_move('y', 2, 1, mesh, color, sock);
2176  anim_move('x', 2, 3, mesh, color, sock);
2177  anim_move('y', 2, 3, mesh, color, sock);
2178  break;
2179  case 7:
2180  anim_move('y', 2, 3, mesh, color, sock);
2181  anim_move('z', 3, 1, mesh, color, sock);
2182  anim_move('y', 2, 1, mesh, color, sock);
2183  break;
2184  case 8:
2185  anim_move('y', 1, 3, mesh, color, sock);
2186  break;
2187  case 9:
2188  anim_move('z', 2, 1, mesh, color, sock);
2189  anim_move('y', 1, 3, mesh, color, sock);
2190  break;
2191  case 10:
2192  anim_move('y', 3, 1, mesh, color, sock);
2193  anim_move('z', 3, 2, mesh, color, sock);
2194  break;
2195  case 11:
2196  anim_move('x', 1, 3, mesh, color, sock);
2197  anim_move('z', 3, 3, mesh, color, sock);
2198  break;
2199  }
2200  }
2201  else
2202  {
2203  switch (i4)
2204  {
2205  case 0:
2206  anim_move('y', 1, 2, mesh, color, sock);
2207  break;
2208  case 1:
2209  anim_move('z', 1, 3, mesh, color, sock);
2210  anim_move('y', 1, 2, mesh, color, sock);
2211  break;
2212  case 2:
2213  anim_move('x', 2, 3, mesh, color, sock);
2214  anim_move('z', 3, 1, mesh, color, sock);
2215  anim_move('x', 2, 1, mesh, color, sock);
2216  anim_move('z', 3, 1, mesh, color, sock);
2217  break;
2218  case 3:
2219  anim_move('y', 2, 3, mesh, color, sock);
2220  anim_move('z', 3, 3, mesh, color, sock);
2221  anim_move('y', 2, 1, mesh, color, sock);
2222  break;
2223  case 4:
2224  anim_move('y', 1, 3, mesh, color, sock);
2225  anim_move('z', 2, 1, mesh, color, sock);
2226  anim_move('y', 1, 3, mesh, color, sock);
2227  break;
2228  case 5:
2229  anim_move('y', 2, 1, mesh, color, sock);
2230  anim_move('z', 3, 3, mesh, color, sock);
2231  anim_move('y', 2, 3, mesh, color, sock);
2232  break;
2233  case 6:
2234  anim_move('z', 3, 2, mesh, color, sock);
2235  break;
2236  case 7:
2237  anim_move('z', 3, 3, mesh, color, sock);
2238  break;
2239  case 8:
2240  anim_move('z', 2, 3, mesh, color, sock);
2241  anim_move('y', 1, 1, mesh, color, sock);
2242  break;
2243  case 9:
2244  anim_move('y', 1, 1, mesh, color, sock);
2245  break;
2246  case 10:
2247  anim_move('x', 3, 3, mesh, color, sock);
2248  anim_move('z', 3, 1, mesh, color, sock);
2249  break;
2250  case 11:
2251  anim_move('y', 3, 3, mesh, color, sock);
2252  anim_move('z', 3, 2, mesh, color, sock);
2253  break;
2254  }
2255  }
2256 }
2257 
2258 void
2259 move_to_e5(int i5, int o5,
2260  Mesh & mesh, GridFunction & color, socketstream & sock)
2261 {
2262  if (o5 == 0)
2263  {
2264  switch (i5)
2265  {
2266  case 0:
2267  anim_move('y', 1, 3, mesh, color, sock);
2268  anim_move('x', 3, 1, mesh, color, sock);
2269  anim_move('y', 1, 1, mesh, color, sock);
2270  break;
2271  case 1:
2272  anim_move('x', 2, 3, mesh, color, sock);
2273  anim_move('y', 2, 1, mesh, color, sock);
2274  anim_move('x', 2, 1, mesh, color, sock);
2275  break;
2276  case 2:
2277  anim_move('z', 1, 1, mesh, color, sock);
2278  anim_move('x', 3, 2, mesh, color, sock);
2279  break;
2280  case 3:
2281  anim_move('z', 1, 2, mesh, color, sock);
2282  anim_move('x', 3, 2, mesh, color, sock);
2283  break;
2284  case 6:
2285  anim_move('y', 3, 3, mesh, color, sock);
2286  anim_move('x', 3, 3, mesh, color, sock);
2287  break;
2288  case 7:
2289  anim_move('x', 2, 1, mesh, color, sock);
2290  anim_move('y', 2, 3, mesh, color, sock);
2291  anim_move('x', 2, 3, mesh, color, sock);
2292  break;
2293  case 8:
2294  anim_move('z', 2, 3, mesh, color, sock);
2295  anim_move('x', 3, 1, mesh, color, sock);
2296  break;
2297  case 9:
2298  anim_move('x', 3, 1, mesh, color, sock);
2299  break;
2300  case 10:
2301  anim_move('z', 2, 1, mesh, color, sock);
2302  anim_move('x', 3, 1, mesh, color, sock);
2303  break;
2304  case 11:
2305  anim_move('y', 3, 2, mesh, color, sock);
2306  anim_move('x', 3, 3, mesh, color, sock);
2307  break;
2308  }
2309  }
2310  else
2311  {
2312  switch (i5)
2313  {
2314  case 0:
2315  anim_move('z', 1, 3, mesh, color, sock);
2316  anim_move('x', 3, 2, mesh, color, sock);
2317  break;
2318  case 1:
2319  anim_move('x', 3, 2, mesh, color, sock);
2320  break;
2321  case 2:
2322  anim_move('y', 3, 1, mesh, color, sock);
2323  anim_move('x', 3, 3, mesh, color, sock);
2324  break;
2325  case 3:
2326  anim_move('z', 1, 2, mesh, color, sock);
2327  anim_move('x', 2, 3, mesh, color, sock);
2328  anim_move('y', 2, 1, mesh, color, sock);
2329  anim_move('x', 2, 1, mesh, color, sock);
2330  break;
2331  case 5:
2332  anim_move('x', 3, 1, mesh, color, sock);
2333  anim_move('z', 2, 1, mesh, color, sock);
2334  anim_move('x', 3, 1, mesh, color, sock);
2335  break;
2336  case 6:
2337  anim_move('y', 1, 1, mesh, color, sock);
2338  anim_move('z', 3, 1, mesh, color, sock);
2339  anim_move('y', 1, 3, mesh, color, sock);
2340  break;
2341  case 7:
2342  anim_move('y', 1, 1, mesh, color, sock);
2343  anim_move('z', 3, 2, mesh, color, sock);
2344  anim_move('y', 1, 3, mesh, color, sock);
2345  break;
2346  case 8:
2347  anim_move('z', 2, 2, mesh, color, sock);
2348  anim_move('x', 3, 3, mesh, color, sock);
2349  break;
2350  case 9:
2351  anim_move('z', 2, 3, mesh, color, sock);
2352  anim_move('x', 3, 3, mesh, color, sock);
2353  break;
2354  case 10:
2355  anim_move('x', 3, 3, mesh, color, sock);
2356  break;
2357  case 11:
2358  anim_move('z', 2, 1, mesh, color, sock);
2359  anim_move('x', 3, 3, mesh, color, sock);
2360  break;
2361  }
2362  }
2363 }
2364 
2365 void
2366 move_to_e6(int i6, int o6,
2367  Mesh & mesh, GridFunction & color, socketstream & sock)
2368 {
2369  if (o6 == 0)
2370  {
2371  switch (i6)
2372  {
2373  case 0:
2374  anim_move('z', 1, 2, mesh, color, sock);
2375  anim_move('y', 3, 2, mesh, color, sock);
2376  break;
2377  case 1:
2378  anim_move('z', 1, 3, mesh, color, sock);
2379  anim_move('y', 3, 2, mesh, color, sock);
2380  break;
2381  case 2:
2382  anim_move('y', 3, 1, mesh, color, sock);
2383  anim_move('z', 2, 3, mesh, color, sock);
2384  anim_move('y', 3, 3, mesh, color, sock);
2385  break;
2386  case 3:
2387  anim_move('x', 1, 3, mesh, color, sock);
2388  anim_move('y', 3, 3, mesh, color, sock);
2389  break;
2390  case 7:
2391  anim_move('z', 3, 1, mesh, color, sock);
2392  anim_move('y', 3, 1, mesh, color, sock);
2393  anim_move('z', 3, 3, mesh, color, sock);
2394  anim_move('y', 3, 3, mesh, color, sock);
2395  break;
2396  case 8:
2397  anim_move('z', 2, 1, mesh, color, sock);
2398  anim_move('y', 3, 3, mesh, color, sock);
2399  break;
2400  case 9:
2401  anim_move('z', 2, 2, mesh, color, sock);
2402  anim_move('y', 3, 3, mesh, color, sock);
2403  break;
2404  case 10:
2405  anim_move('z', 2, 3, mesh, color, sock);
2406  anim_move('y', 3, 3, mesh, color, sock);
2407  break;
2408  case 11:
2409  anim_move('y', 3, 3, mesh, color, sock);
2410  break;
2411  }
2412  }
2413  else
2414  {
2415  switch (i6)
2416  {
2417  case 0:
2418  anim_move('z', 1, 1, mesh, color, sock);
2419  anim_move('x', 1, 3, mesh, color, sock);
2420  anim_move('y', 3, 3, mesh, color, sock);
2421  break;
2422  case 1:
2423  anim_move('x', 2, 1, mesh, color, sock);
2424  anim_move('z', 1, 3, mesh, color, sock);
2425  anim_move('x', 2, 3, mesh, color, sock);
2426  break;
2427  case 2:
2428  anim_move('y', 3, 2, mesh, color, sock);
2429  break;
2430  case 3:
2431  anim_move('z', 1, 1, mesh, color, sock);
2432  anim_move('y', 3, 2, mesh, color, sock);
2433  break;
2434  case 6:
2435  anim_move('y', 3, 1, mesh, color, sock);
2436  anim_move('z', 2, 1, mesh, color, sock);
2437  anim_move('y', 3, 1, mesh, color, sock);
2438  break;
2439  case 7:
2440  anim_move('x', 1, 1, mesh, color, sock);
2441  anim_move('y', 3, 3, mesh, color, sock);
2442  break;
2443  case 8:
2444  anim_move('z', 2, 2, mesh, color, sock);
2445  anim_move('y', 3, 1, mesh, color, sock);
2446  break;
2447  case 9:
2448  anim_move('z', 2, 3, mesh, color, sock);
2449  anim_move('y', 3, 1, mesh, color, sock);
2450  break;
2451  case 10:
2452  anim_move('y', 3, 1, mesh, color, sock);
2453  break;
2454  case 11:
2455  anim_move('z', 2, 1, mesh, color, sock);
2456  anim_move('y', 3, 1, mesh, color, sock);
2457  break;
2458  }
2459  }
2460 }
2461 
2462 void
2463 move_to_e7(int i7, int o7,
2464  Mesh & mesh, GridFunction & color, socketstream & sock)
2465 {
2466  if (o7 == 0)
2467  {
2468  switch (i7)
2469  {
2470  case 0:
2471  anim_move('z', 1, 1, mesh, color, sock);
2472  anim_move('x', 1, 2, mesh, color, sock);
2473  break;
2474  case 1:
2475  anim_move('z', 1, 2, mesh, color, sock);
2476  anim_move('x', 1, 2, mesh, color, sock);
2477  break;
2478  case 2:
2479  anim_move('y', 3, 3, mesh, color, sock);
2480  anim_move('x', 1, 3, mesh, color, sock);
2481  anim_move('y', 3, 1, mesh, color, sock);
2482  break;
2483  case 3:
2484  anim_move('x', 1, 1, mesh, color, sock);
2485  anim_move('z', 2, 1, mesh, color, sock);
2486  anim_move('x', 1, 3, mesh, color, sock);
2487  break;
2488  case 8:
2489  anim_move('x', 1, 1, mesh, color, sock);
2490  break;
2491  case 9:
2492  anim_move('z', 2, 1, mesh, color, sock);
2493  anim_move('x', 1, 1, mesh, color, sock);
2494  break;
2495  case 10:
2496  anim_move('z', 2, 2, mesh, color, sock);
2497  anim_move('x', 1, 1, mesh, color, sock);
2498  break;
2499  case 11:
2500  anim_move('z', 2, 3, mesh, color, sock);
2501  anim_move('x', 1, 1, mesh, color, sock);
2502  break;
2503  }
2504  }
2505  else
2506  {
2507  switch (i7)
2508  {
2509  case 0:
2510  anim_move('y', 1, 3, mesh, color, sock);
2511  anim_move('x', 1, 1, mesh, color, sock);
2512  anim_move('y', 1, 1, mesh, color, sock);
2513  break;
2514  case 1:
2515  anim_move('z', 1, 3, mesh, color, sock);
2516  anim_move('y', 3, 3, mesh, color, sock);
2517  anim_move('x', 1, 3, mesh, color, sock);
2518  anim_move('y', 3, 1, mesh, color, sock);
2519  break;
2520  case 2:
2521  anim_move('z', 1, 3, mesh, color, sock);
2522  anim_move('x', 1, 2, mesh, color, sock);
2523  break;
2524  case 3:
2525  anim_move('x', 1, 2, mesh, color, sock);
2526  break;
2527  case 7:
2528  anim_move('x', 1, 1, mesh, color, sock);
2529  anim_move('z', 2, 3, mesh, color, sock);
2530  anim_move('x', 1, 1, mesh, color, sock);
2531  break;
2532  case 8:
2533  anim_move('z', 2, 1, mesh, color, sock);
2534  anim_move('x', 1, 3, mesh, color, sock);
2535  break;
2536  case 9:
2537  anim_move('z', 2, 2, mesh, color, sock);
2538  anim_move('x', 1, 3, mesh, color, sock);
2539  break;
2540  case 10:
2541  anim_move('z', 2, 3, mesh, color, sock);
2542  anim_move('x', 1, 3, mesh, color, sock);
2543  break;
2544  case 11:
2545  anim_move('x', 1, 3, mesh, color, sock);
2546  break;
2547  }
2548  }
2549 }
2550 
2551 void
2552 move_to_e8(int i8, int o8,
2553  Mesh & mesh, GridFunction & color, socketstream & sock)
2554 {
2555  if (o8 == 0)
2556  {
2557  switch (i8)
2558  {
2559  case 0: // Verified
2560  anim_move('z', 1, 2, mesh, color, sock);
2561  anim_move('y', 1, 1, mesh, color, sock);
2562  anim_move('z', 1, 3, mesh, color, sock);
2563  anim_move('y', 1, 3, mesh, color, sock);
2564  anim_move('x', 1, 1, mesh, color, sock);
2565  anim_move('y', 1, 3, mesh, color, sock);
2566  anim_move('x', 1, 3, mesh, color, sock);
2567  anim_move('y', 1, 1, mesh, color, sock);
2568  break;
2569  case 1: // Verified
2570  anim_move('z', 1, 3, mesh, color, sock);
2571  anim_move('y', 1, 1, mesh, color, sock);
2572  anim_move('z', 1, 3, mesh, color, sock);
2573  anim_move('y', 1, 3, mesh, color, sock);
2574  anim_move('x', 1, 1, mesh, color, sock);
2575  anim_move('y', 1, 3, mesh, color, sock);
2576  anim_move('x', 1, 3, mesh, color, sock);
2577  anim_move('y', 1, 1, mesh, color, sock);
2578  break;
2579  case 2: // Verified
2580  anim_move('z', 1, 1, mesh, color, sock);
2581  anim_move('x', 1, 3, mesh, color, sock);
2582  anim_move('z', 1, 1, mesh, color, sock);
2583  anim_move('x', 1, 1, mesh, color, sock);
2584  anim_move('y', 1, 3, mesh, color, sock);
2585  anim_move('x', 1, 1, mesh, color, sock);
2586  anim_move('y', 1, 1, mesh, color, sock);
2587  anim_move('x', 1, 3, mesh, color, sock);
2588  break;
2589  case 3: // Verified
2590  anim_move('z', 1, 2, mesh, color, sock);
2591  anim_move('x', 1, 3, mesh, color, sock);
2592  anim_move('z', 1, 1, mesh, color, sock);
2593  anim_move('x', 1, 1, mesh, color, sock);
2594  anim_move('y', 1, 3, mesh, color, sock);
2595  anim_move('x', 1, 1, mesh, color, sock);
2596  anim_move('y', 1, 1, mesh, color, sock);
2597  anim_move('x', 1, 3, mesh, color, sock);
2598  break;
2599  case 9: // Verified
2600  anim_move('x', 3, 3, mesh, color, sock);
2601  permute_edges(mesh, color, sock, false);
2602  anim_move('x', 3, 1, mesh, color, sock);
2603  anim_move('z', 1, 1, mesh, color, sock);
2604  anim_move('y', 1, 1, mesh, color, sock);
2605  permute_edges(mesh, color, sock, true);
2606  anim_move('y', 1, 3, mesh, color, sock);
2607  break;
2608  case 10: // Verified
2609  anim_move('z', 2, 1, mesh, color, sock);
2610  anim_move('y', 1, 2, mesh, color, sock);
2611  anim_move('z', 2, 3, mesh, color, sock);
2612  anim_move('y', 1, 2, mesh, color, sock);
2613  break;
2614  case 11: // Verified
2615  anim_move('y', 3, 1, mesh, color, sock);
2616  permute_edges(mesh, color, sock, true);
2617  anim_move('y', 3, 3, mesh, color, sock);
2618  anim_move('z', 1, 3, mesh, color, sock);
2619  anim_move('y', 1, 1, mesh, color, sock);
2620  permute_edges(mesh, color, sock, false);
2621  anim_move('y', 1, 3, mesh, color, sock);
2622  break;
2623  }
2624  }
2625  else
2626  {
2627  switch (i8)
2628  {
2629  case 0: // Verified
2630  anim_move('z', 1, 3, mesh, color, sock);
2631  anim_move('x', 1, 3, mesh, color, sock);
2632  anim_move('z', 1, 1, mesh, color, sock);
2633  anim_move('x', 1, 1, mesh, color, sock);
2634  anim_move('y', 1, 3, mesh, color, sock);
2635  anim_move('x', 1, 1, mesh, color, sock);
2636  anim_move('y', 1, 1, mesh, color, sock);
2637  anim_move('x', 1, 3, mesh, color, sock);
2638  break;
2639  case 1: // Verified
2640  anim_move('x', 1, 3, mesh, color, sock);
2641  anim_move('z', 1, 1, mesh, color, sock);
2642  anim_move('x', 1, 1, mesh, color, sock);
2643  anim_move('y', 1, 3, mesh, color, sock);
2644  anim_move('x', 1, 1, mesh, color, sock);
2645  anim_move('y', 1, 1, mesh, color, sock);
2646  anim_move('x', 1, 3, mesh, color, sock);
2647  break;
2648  case 2: // Verified
2649  anim_move('y', 1, 1, mesh, color, sock);
2650  anim_move('z', 1, 3, mesh, color, sock);
2651  anim_move('y', 1, 3, mesh, color, sock);
2652  anim_move('x', 1, 1, mesh, color, sock);
2653  anim_move('y', 1, 3, mesh, color, sock);
2654  anim_move('x', 1, 3, mesh, color, sock);
2655  anim_move('y', 1, 1, mesh, color, sock);
2656  break;
2657  case 3: // Verified
2658  anim_move('z', 1, 1, mesh, color, sock);
2659  anim_move('y', 1, 1, mesh, color, sock);
2660  anim_move('z', 1, 3, mesh, color, sock);
2661  anim_move('y', 1, 3, mesh, color, sock);
2662  anim_move('x', 1, 1, mesh, color, sock);
2663  anim_move('y', 1, 3, mesh, color, sock);
2664  anim_move('x', 1, 3, mesh, color, sock);
2665  anim_move('y', 1, 1, mesh, color, sock);
2666  break;
2667  case 8: // Verified
2668  anim_move('y', 1, 1, mesh, color, sock);
2669  anim_move('z', 1, 3, mesh, color, sock);
2670  anim_move('y', 1, 3, mesh, color, sock);
2671  anim_move('x', 1, 1, mesh, color, sock);
2672  anim_move('y', 1, 3, mesh, color, sock);
2673  anim_move('x', 1, 3, mesh, color, sock);
2674  anim_move('y', 1, 1, mesh, color, sock);
2675  anim_move('z', 1, 3, mesh, color, sock);
2676  anim_move('y', 1, 1, mesh, color, sock);
2677  anim_move('z', 1, 3, mesh, color, sock);
2678  anim_move('y', 1, 3, mesh, color, sock);
2679  anim_move('x', 1, 1, mesh, color, sock);
2680  anim_move('y', 1, 3, mesh, color, sock);
2681  anim_move('x', 1, 3, mesh, color, sock);
2682  anim_move('y', 1, 1, mesh, color, sock);
2683  break;
2684  case 9: // Verified
2685  anim_move('y', 1, 2, mesh, color, sock);
2686  anim_move('z', 1, 2, mesh, color, sock);
2687  anim_move('y', 1, 2, mesh, color, sock);
2688  anim_move('z', 1, 2, mesh, color, sock);
2689  anim_move('y', 1, 2, mesh, color, sock);
2690  break;
2691  case 10: // Verified
2692  anim_move('y', 3, 3, mesh, color, sock);
2693  permute_edges(mesh, color, sock, false);
2694  anim_move('y', 3, 1, mesh, color, sock);
2695  anim_move('z', 1, 3, mesh, color, sock);
2696  anim_move('y', 1, 1, mesh, color, sock);
2697  permute_edges(mesh, color, sock, true);
2698  anim_move('y', 1, 3, mesh, color, sock);
2699  break;
2700  case 11: // Verified
2701  anim_move('z', 2, 1, mesh, color, sock);
2702  anim_move('x', 1, 2, mesh, color, sock);
2703  anim_move('z', 2, 3, mesh, color, sock);
2704  anim_move('x', 1, 2, mesh, color, sock);
2705  break;
2706  }
2707  }
2708 }
2709 
2710 void
2711 move_to_e9(int i9, int o9,
2712  Mesh & mesh, GridFunction & color, socketstream & sock)
2713 {
2714  if (o9 == 0)
2715  {
2716  switch (i9)
2717  {
2718  case 0: // Verified
2719  anim_move('z', 1, 1, mesh, color, sock);
2720  anim_move('x', 3, 3, mesh, color, sock);
2721  anim_move('z', 1, 3, mesh, color, sock);
2722  anim_move('x', 3, 1, mesh, color, sock);
2723  anim_move('y', 1, 1, mesh, color, sock);
2724  anim_move('x', 3, 1, mesh, color, sock);
2725  anim_move('y', 1, 3, mesh, color, sock);
2726  anim_move('x', 3, 3, mesh, color, sock);
2727  break;
2728  case 1: // Verified
2729  anim_move('z', 1, 2, mesh, color, sock);
2730  anim_move('x', 3, 3, mesh, color, sock);
2731  anim_move('z', 1, 3, mesh, color, sock);
2732  anim_move('x', 3, 1, mesh, color, sock);
2733  anim_move('y', 1, 1, mesh, color, sock);
2734  anim_move('x', 3, 1, mesh, color, sock);
2735  anim_move('y', 1, 3, mesh, color, sock);
2736  anim_move('x', 3, 3, mesh, color, sock);
2737  break;
2738  case 2: // Verified
2739  anim_move('y', 1, 3, mesh, color, sock);
2740  anim_move('z', 1, 1, mesh, color, sock);
2741  anim_move('y', 1, 1, mesh, color, sock);
2742  anim_move('x', 3, 1, mesh, color, sock);
2743  anim_move('y', 1, 1, mesh, color, sock);
2744  anim_move('x', 3, 3, mesh, color, sock);
2745  anim_move('y', 1, 3, mesh, color, sock);
2746  break;
2747  case 3: // Verified
2748  anim_move('z', 1, 1, mesh, color, sock);
2749  anim_move('y', 1, 3, mesh, color, sock);
2750  anim_move('z', 1, 1, mesh, color, sock);
2751  anim_move('y', 1, 1, mesh, color, sock);
2752  anim_move('x', 3, 1, mesh, color, sock);
2753  anim_move('y', 1, 1, mesh, color, sock);
2754  anim_move('x', 3, 3, mesh, color, sock);
2755  anim_move('y', 1, 3, mesh, color, sock);
2756  break;
2757  case 10: // Verified
2758  anim_move('y', 3, 3, mesh, color, sock);
2759  permute_edges(mesh, color, sock, true);
2760  anim_move('y', 3, 1, mesh, color, sock);
2761  anim_move('z', 1, 3, mesh, color, sock);
2762  anim_move('y', 1, 3, mesh, color, sock);
2763  permute_edges(mesh, color, sock, false);
2764  anim_move('y', 1, 1, mesh, color, sock);
2765  break;
2766  case 11: // Verified
2767  anim_move('z', 2, 1, mesh, color, sock);
2768  anim_move('x', 3, 2, mesh, color, sock);
2769  anim_move('z', 2, 3, mesh, color, sock);
2770  anim_move('x', 3, 2, mesh, color, sock);
2771  break;
2772  }
2773  }
2774  else
2775  {
2776  switch (i9)
2777  {
2778  case 0: // Verified
2779  anim_move('z', 1, 2, mesh, color, sock);
2780  anim_move('y', 1, 3, mesh, color, sock);
2781  anim_move('z', 1, 1, mesh, color, sock);
2782  anim_move('y', 1, 1, mesh, color, sock);
2783  anim_move('x', 3, 1, mesh, color, sock);
2784  anim_move('y', 1, 1, mesh, color, sock);
2785  anim_move('x', 3, 3, mesh, color, sock);
2786  anim_move('y', 1, 3, mesh, color, sock);
2787  break;
2788  case 1: // Verified
2789  anim_move('z', 1, 3, mesh, color, sock);
2790  anim_move('y', 1, 3, mesh, color, sock);
2791  anim_move('z', 1, 1, mesh, color, sock);
2792  anim_move('y', 1, 1, mesh, color, sock);
2793  anim_move('x', 3, 1, mesh, color, sock);
2794  anim_move('y', 1, 1, mesh, color, sock);
2795  anim_move('x', 3, 3, mesh, color, sock);
2796  anim_move('y', 1, 3, mesh, color, sock);
2797  break;
2798  case 2: // Verified
2799  anim_move('z', 1, 3, mesh, color, sock);
2800  anim_move('x', 3, 3, mesh, color, sock);
2801  anim_move('z', 1, 3, mesh, color, sock);
2802  anim_move('x', 3, 1, mesh, color, sock);
2803  anim_move('y', 1, 1, mesh, color, sock);
2804  anim_move('x', 3, 1, mesh, color, sock);
2805  anim_move('y', 1, 3, mesh, color, sock);
2806  anim_move('x', 3, 3, mesh, color, sock);
2807  break;
2808  case 3: // Verified
2809  anim_move('x', 3, 3, mesh, color, sock);
2810  anim_move('z', 1, 3, mesh, color, sock);
2811  anim_move('x', 3, 1, mesh, color, sock);
2812  anim_move('y', 1, 1, mesh, color, sock);
2813  anim_move('x', 3, 1, mesh, color, sock);
2814  anim_move('y', 1, 3, mesh, color, sock);
2815  anim_move('x', 3, 3, mesh, color, sock);
2816  break;
2817  case 9: // Verified
2818  anim_move('x', 3, 3, mesh, color, sock);
2819  anim_move('z', 1, 3, mesh, color, sock);
2820  anim_move('x', 3, 1, mesh, color, sock);
2821  anim_move('y', 1, 1, mesh, color, sock);
2822  anim_move('x', 3, 1, mesh, color, sock);
2823  anim_move('y', 1, 3, mesh, color, sock);
2824  anim_move('x', 3, 3, mesh, color, sock);
2825  anim_move('z', 1, 3, mesh, color, sock);
2826  anim_move('x', 3, 3, mesh, color, sock);
2827  anim_move('z', 1, 3, mesh, color, sock);
2828  anim_move('x', 3, 1, mesh, color, sock);
2829  anim_move('y', 1, 1, mesh, color, sock);
2830  anim_move('x', 3, 1, mesh, color, sock);
2831  anim_move('y', 1, 3, mesh, color, sock);
2832  anim_move('x', 3, 3, mesh, color, sock);
2833  break;
2834  case 10: // Verified
2835  anim_move('x', 3, 2, mesh, color, sock);
2836  anim_move('z', 1, 2, mesh, color, sock);
2837  anim_move('x', 3, 2, mesh, color, sock);
2838  anim_move('z', 1, 2, mesh, color, sock);
2839  anim_move('x', 3, 2, mesh, color, sock);
2840  break;
2841  case 11: // Verified
2842  anim_move('y', 3, 1, mesh, color, sock);
2843  permute_edges(mesh, color, sock, true);
2844  anim_move('y', 3, 3, mesh, color, sock);
2845  anim_move('z', 1, 3, mesh, color, sock);
2846  anim_move('y', 1, 3, mesh, color, sock);
2847  permute_edges(mesh, color, sock, false);
2848  anim_move('y', 1, 1, mesh, color, sock);
2849  break;
2850  }
2851  }
2852 }
2853 
2854 void
2855 move_to_e10(int i10, int o10,
2856  Mesh & mesh, GridFunction & color, socketstream & sock)
2857 {
2858  if (o10 == 0)
2859  {
2860  switch (i10)
2861  {
2862  case 0: // Verified
2863  anim_move('y', 3, 3, mesh, color, sock);
2864  anim_move('z', 1, 3, mesh, color, sock);
2865  anim_move('y', 3, 1, mesh, color, sock);
2866  anim_move('x', 3, 3, mesh, color, sock);
2867  anim_move('y', 3, 1, mesh, color, sock);
2868  anim_move('x', 3, 1, mesh, color, sock);
2869  anim_move('y', 3, 3, mesh, color, sock);
2870  break;
2871  case 1: // Verified
2872  anim_move('z', 1, 1, mesh, color, sock);
2873  anim_move('y', 3, 3, mesh, color, sock);
2874  anim_move('z', 1, 3, mesh, color, sock);
2875  anim_move('y', 3, 1, mesh, color, sock);
2876  anim_move('x', 3, 3, mesh, color, sock);
2877  anim_move('y', 3, 1, mesh, color, sock);
2878  anim_move('x', 3, 1, mesh, color, sock);
2879  anim_move('y', 3, 3, mesh, color, sock);
2880  break;
2881  case 2: // Verified
2882  anim_move('z', 1, 3, mesh, color, sock);
2883  anim_move('x', 3, 1, mesh, color, sock);
2884  anim_move('z', 1, 1, mesh, color, sock);
2885  anim_move('x', 3, 3, mesh, color, sock);
2886  anim_move('y', 3, 1, mesh, color, sock);
2887  anim_move('x', 3, 3, mesh, color, sock);
2888  anim_move('y', 3, 3, mesh, color, sock);
2889  anim_move('x', 3, 1, mesh, color, sock);
2890  break;
2891  case 3: // Verified
2892  anim_move('x', 3, 1, mesh, color, sock);
2893  anim_move('z', 1, 1, mesh, color, sock);
2894  anim_move('x', 3, 3, mesh, color, sock);
2895  anim_move('y', 3, 1, mesh, color, sock);
2896  anim_move('x', 3, 3, mesh, color, sock);
2897  anim_move('y', 3, 3, mesh, color, sock);
2898  anim_move('x', 3, 1, mesh, color, sock);
2899  break;
2900  case 11: // Verified
2901  anim_move('y', 3, 1, mesh, color, sock);
2902  permute_edges(mesh, color, sock, true);
2903  anim_move('y', 3, 3, mesh, color, sock);
2904  anim_move('z', 1, 1, mesh, color, sock);
2905  anim_move('y', 3, 3, mesh, color, sock);
2906  permute_edges(mesh, color, sock, true);
2907  anim_move('y', 3, 1, mesh, color, sock);
2908  break;
2909  }
2910  }
2911  else
2912  {
2913  switch (i10)
2914  {
2915  case 0: // Verified
2916  anim_move('z', 1, 1, mesh, color, sock);
2917  anim_move('x', 3, 1, mesh, color, sock);
2918  anim_move('z', 1, 1, mesh, color, sock);
2919  anim_move('x', 3, 3, mesh, color, sock);
2920  anim_move('y', 3, 1, mesh, color, sock);
2921  anim_move('x', 3, 3, mesh, color, sock);
2922  anim_move('y', 3, 3, mesh, color, sock);
2923  anim_move('x', 3, 1, mesh, color, sock);
2924  break;
2925  case 1: // Verified
2926  anim_move('z', 1, 2, mesh, color, sock);
2927  anim_move('x', 3, 1, mesh, color, sock);
2928  anim_move('z', 1, 1, mesh, color, sock);
2929  anim_move('x', 3, 3, mesh, color, sock);
2930  anim_move('y', 3, 1, mesh, color, sock);
2931  anim_move('x', 3, 3, mesh, color, sock);
2932  anim_move('y', 3, 3, mesh, color, sock);
2933  anim_move('x', 3, 1, mesh, color, sock);
2934  break;
2935  case 2: // Verified
2936  anim_move('z', 1, 2, mesh, color, sock);
2937  anim_move('y', 3, 3, mesh, color, sock);
2938  anim_move('z', 1, 3, mesh, color, sock);
2939  anim_move('y', 3, 1, mesh, color, sock);
2940  anim_move('x', 3, 3, mesh, color, sock);
2941  anim_move('y', 3, 1, mesh, color, sock);
2942  anim_move('x', 3, 1, mesh, color, sock);
2943  anim_move('y', 3, 3, mesh, color, sock);
2944  break;
2945  case 3: // Verified
2946  anim_move('z', 1, 3, mesh, color, sock);
2947  anim_move('y', 3, 3, mesh, color, sock);
2948  anim_move('z', 1, 3, mesh, color, sock);
2949  anim_move('y', 3, 1, mesh, color, sock);
2950  anim_move('x', 3, 3, mesh, color, sock);
2951  anim_move('y', 3, 1, mesh, color, sock);
2952  anim_move('x', 3, 1, mesh, color, sock);
2953  anim_move('y', 3, 3, mesh, color, sock);
2954  break;
2955  case 10: // Verified
2956  anim_move('x', 3, 1, mesh, color, sock);
2957  anim_move('z', 1, 1, mesh, color, sock);
2958  anim_move('x', 3, 3, mesh, color, sock);
2959  anim_move('y', 3, 1, mesh, color, sock);
2960  anim_move('x', 3, 3, mesh, color, sock);
2961  anim_move('y', 3, 3, mesh, color, sock);
2962  anim_move('x', 3, 1, mesh, color, sock);
2963  anim_move('z', 1, 1, mesh, color, sock);
2964  anim_move('x', 3, 1, mesh, color, sock);
2965  anim_move('z', 1, 1, mesh, color, sock);
2966  anim_move('x', 3, 3, mesh, color, sock);
2967  anim_move('y', 3, 1, mesh, color, sock);
2968  anim_move('x', 3, 3, mesh, color, sock);
2969  anim_move('y', 3, 3, mesh, color, sock);
2970  anim_move('x', 3, 1, mesh, color, sock);
2971  break;
2972  case 11: // Verified
2973  anim_move('y', 3, 2, mesh, color, sock);
2974  anim_move('z', 1, 2, mesh, color, sock);
2975  anim_move('y', 3, 2, mesh, color, sock);
2976  anim_move('z', 1, 2, mesh, color, sock);
2977  anim_move('y', 3, 2, mesh, color, sock);
2978  break;
2979  }
2980  }
2981 }
2982 
2983 void
2984 move_to_e11(int i11, int o11,
2985  Mesh & mesh, GridFunction & color, socketstream & sock)
2986 {
2987  if (o11 == 0)
2988  {
2989  switch (i11)
2990  {
2991  case 0: // Verified
2992  anim_move('z', 1, 3, mesh, color, sock);
2993  anim_move('x', 1, 1, mesh, color, sock);
2994  anim_move('z', 1, 3, mesh, color, sock);
2995  anim_move('x', 1, 3, mesh, color, sock);
2996  anim_move('y', 3, 3, mesh, color, sock);
2997  anim_move('x', 1, 3, mesh, color, sock);
2998  anim_move('y', 3, 1, mesh, color, sock);
2999  anim_move('x', 1, 1, mesh, color, sock);
3000  break;
3001  case 1: // Verified
3002  anim_move('x', 1, 1, mesh, color, sock);
3003  anim_move('z', 1, 3, mesh, color, sock);
3004  anim_move('x', 1, 3, mesh, color, sock);
3005  anim_move('y', 3, 3, mesh, color, sock);
3006  anim_move('x', 1, 3, mesh, color, sock);
3007  anim_move('y', 3, 1, mesh, color, sock);
3008  anim_move('x', 1, 1, mesh, color, sock);
3009  break;
3010  case 2: // Verified
3011  anim_move('z', 1, 2, mesh, color, sock);
3012  anim_move('y', 3, 1, mesh, color, sock);
3013  anim_move('z', 1, 1, mesh, color, sock);
3014  anim_move('y', 3, 3, mesh, color, sock);
3015  anim_move('x', 1, 3, mesh, color, sock);
3016  anim_move('y', 3, 3, mesh, color, sock);
3017  anim_move('x', 1, 1, mesh, color, sock);
3018  anim_move('y', 3, 1, mesh, color, sock);
3019  break;
3020  case 3: // Verified
3021  anim_move('z', 1, 3, mesh, color, sock);
3022  anim_move('y', 3, 1, mesh, color, sock);
3023  anim_move('z', 1, 1, mesh, color, sock);
3024  anim_move('y', 3, 3, mesh, color, sock);
3025  anim_move('x', 1, 3, mesh, color, sock);
3026  anim_move('y', 3, 3, mesh, color, sock);
3027  anim_move('x', 1, 1, mesh, color, sock);
3028  anim_move('y', 3, 1, mesh, color, sock);
3029  break;
3030  }
3031  }
3032  else
3033  {
3034  switch (i11)
3035  {
3036  case 0: // Verified
3037  anim_move('y', 3, 1, mesh, color, sock);
3038  anim_move('z', 1, 1, mesh, color, sock);
3039  anim_move('y', 3, 3, mesh, color, sock);
3040  anim_move('x', 1, 3, mesh, color, sock);
3041  anim_move('y', 3, 3, mesh, color, sock);
3042  anim_move('x', 1, 1, mesh, color, sock);
3043  anim_move('y', 3, 1, mesh, color, sock);
3044  break;
3045  case 1: // Verified
3046  anim_move('z', 1, 1, mesh, color, sock);
3047  anim_move('y', 3, 1, mesh, color, sock);
3048  anim_move('z', 1, 1, mesh, color, sock);
3049  anim_move('y', 3, 3, mesh, color, sock);
3050  anim_move('x', 1, 3, mesh, color, sock);
3051  anim_move('y', 3, 3, mesh, color, sock);
3052  anim_move('x', 1, 1, mesh, color, sock);
3053  anim_move('y', 3, 1, mesh, color, sock);
3054  break;
3055  case 2: // Verified
3056  anim_move('z', 1, 1, mesh, color, sock);
3057  anim_move('x', 1, 1, mesh, color, sock);
3058  anim_move('z', 1, 3, mesh, color, sock);
3059  anim_move('x', 1, 3, mesh, color, sock);
3060  anim_move('y', 3, 3, mesh, color, sock);
3061  anim_move('x', 1, 3, mesh, color, sock);
3062  anim_move('y', 3, 1, mesh, color, sock);
3063  anim_move('x', 1, 1, mesh, color, sock);
3064  break;
3065  case 3: // Verified
3066  anim_move('z', 1, 2, mesh, color, sock);
3067  anim_move('x', 1, 1, mesh, color, sock);
3068  anim_move('z', 1, 3, mesh, color, sock);
3069  anim_move('x', 1, 3, mesh, color, sock);
3070  anim_move('y', 3, 3, mesh, color, sock);
3071  anim_move('x', 1, 3, mesh, color, sock);
3072  anim_move('y', 3, 1, mesh, color, sock);
3073  anim_move('x', 1, 1, mesh, color, sock);
3074  break;
3075  case 11: // Verified
3076  anim_move('x', 1, 1, mesh, color, sock);
3077  anim_move('z', 1, 3, mesh, color, sock);
3078  anim_move('x', 1, 3, mesh, color, sock);
3079  anim_move('y', 3, 3, mesh, color, sock);
3080  anim_move('x', 1, 3, mesh, color, sock);
3081  anim_move('y', 3, 1, mesh, color, sock);
3082  anim_move('x', 1, 1, mesh, color, sock);
3083  anim_move('z', 1, 3, mesh, color, sock);
3084  anim_move('x', 1, 1, mesh, color, sock);
3085  anim_move('z', 1, 3, mesh, color, sock);
3086  anim_move('x', 1, 3, mesh, color, sock);
3087  anim_move('y', 3, 3, mesh, color, sock);
3088  anim_move('x', 1, 3, mesh, color, sock);
3089  anim_move('y', 3, 1, mesh, color, sock);
3090  anim_move('x', 1, 1, mesh, color, sock);
3091  break;
3092  }
3093  }
3094 }
3095 
3096 void
3098 {
3099  if (logging_ > 1)
3100  {
3101  cout << "Entering solve_top_edges" << endl;
3102  }
3103  if (logging_ > 2)
3104  {
3105  print_state(cout);
3106  }
3107 
3108  // Locate fourth edge in the top tier
3109  {
3110  int l4 = locate_edge(4);
3111  int i4 = max(l4,-1-l4);
3112  int o4 = (l4 >= 0) ? 0 : 1;
3113  if (logging_ > 1)
3114  {
3115  cout << "Location of 4-th edge: " << i4
3116  << " with orientation " << o4 << endl;
3117  }
3118  if (i4 < 12 && ((i4 < 4) ||
3119  (i4 > 4 && o4 == 0) ||
3120  (o4 == 1) ))
3121  {
3122  move_to_e4(i4, o4, mesh, color, sock);
3123  }
3124  }
3125 
3126  // Locate fifth edge in the top tier
3127  {
3128  int l5 = locate_edge(5);
3129  int i5 = max(l5,-1-l5);
3130  int o5 = (l5 >= 0) ? 0 : 1;
3131  if (logging_ > 1)
3132  {
3133  cout << "Location of 5-th edge: " << i5
3134  << " with orientation " << o5 << endl;
3135  }
3136  if (i5 < 12 && ((i5 < 4) ||
3137  (i5 > 5 && o5 == 0) ||
3138  (i5 > 4 && o5 == 1) ))
3139  {
3140  move_to_e5(i5, o5, mesh, color, sock);
3141  }
3142  }
3143 
3144  // Locate sixth edge in the top tier
3145  {
3146  int l6 = locate_edge(6);
3147  int i6 = max(l6,-1-l6);
3148  int o6 = (l6 >= 0) ? 0 : 1;
3149  if (logging_ > 1)
3150  {
3151  cout << "Location of 6-th edge: " << i6
3152  << " with orientation " << o6 << endl;
3153  }
3154  if (i6 < 12 && ((i6 < 4) ||
3155  (i6 > 6 && o6 == 0) ||
3156  (i6 > 5 && o6 == 1) ))
3157  {
3158  move_to_e6(i6, o6, mesh, color, sock);
3159  }
3160  }
3161 
3162  // Locate seventh edge in the top tier
3163  {
3164  int l7 = locate_edge(7);
3165  int i7 = max(l7,-1-l7);
3166  int o7 = (l7 >= 0) ? 0 : 1;
3167  if (logging_ > 1)
3168  {
3169  cout << "Location of 7-th edge: " << i7
3170  << " with orientation " << o7 << endl;
3171  }
3172  if (i7 < 12 && ((i7 < 4) ||
3173  (i7 > 7 && o7 == 0) ||
3174  (i7 > 6 && o7 == 1) ))
3175  {
3176  move_to_e7(i7, o7, mesh, color, sock);
3177  }
3178  }
3179 }
3180 
3181 void
3183 {
3184  if (logging_ > 1)
3185  {
3186  cout << "Entering solve_mid_edges" << endl;
3187  }
3188  if (logging_ > 2)
3189  {
3190  print_state(cout);
3191  }
3192 
3193  // Locate eighth edge
3194  {
3195  int l8 = locate_edge(8);
3196  int i8 = max(l8,-1-l8);
3197  int o8 = (l8 >= 0) ? 0 : 1;
3198  if (logging_ > 1)
3199  {
3200  cout << "Location of 8-th edge: " << i8
3201  << " with orientation " << o8 << endl;
3202  }
3203  if (i8 >= 4 && i8 < 8)
3204  {
3205  cout << "Moving edges from top tier to middle tier is not supported."
3206  << endl;
3207  }
3208  else if (i8 < 12 && ((i8 < 4) ||
3209  (i8 > 8 && o8 == 0) ||
3210  (i8 > 7 && o8 == 1) ))
3211  {
3212  move_to_e8(i8, o8, mesh, color, sock);
3213  }
3214  }
3215 
3216  // Locate ninth edge
3217  {
3218  int l9 = locate_edge(9);
3219  int i9 = max(l9,-1-l9);
3220  int o9 = (l9 >= 0) ? 0 : 1;
3221  if (logging_ > 1)
3222  {
3223  cout << "Location of 9-th edge: " << i9
3224  << " with orientation " << o9 << endl;
3225  }
3226  if (i9 >= 4 && i9 < 8)
3227  {
3228  cout << "Moving edges from top tier to middle tier is not supported."
3229  << endl;
3230  }
3231  else if (i9 < 12 && ((i9 < 4) ||
3232  (i9 > 9 && o9 == 0) ||
3233  (i9 > 8 && o9 == 1) ))
3234  {
3235  move_to_e9(i9, o9, mesh, color, sock);
3236  }
3237  }
3238 
3239  // Locate tenth edge
3240  {
3241  int l10 = locate_edge(10);
3242  int i10 = max(l10,-1-l10);
3243  int o10 = (l10 >= 0) ? 0 : 1;
3244  if (logging_ > 1)
3245  {
3246  cout << "Location of 10-th edge: " << i10
3247  << " with orientation " << o10 << endl;
3248  }
3249  if (i10 >= 4 && i10 < 8)
3250  {
3251  cout << "Moving edges from top tier to middle tier is not supported."
3252  << endl;
3253  }
3254  else if (i10 < 12 && ((i10 < 4) ||
3255  (i10 > 10 && o10 == 0) ||
3256  (i10 > 9 && o10 == 1) ))
3257  {
3258  move_to_e10(i10, o10, mesh, color, sock);
3259  }
3260  }
3261 
3262  // Locate eleventh edge
3263  {
3264  int l11 = locate_edge(11);
3265  int i11 = max(l11,-1-l11);
3266  int o11 = (l11 >= 0) ? 0 : 1;
3267  if (logging_ > 1)
3268  {
3269  cout << "Location of 11-th edge: " << i11
3270  << " with orientation " << o11 << endl;
3271  }
3272  if (i11 >= 4 && i11 < 8)
3273  {
3274  cout << "Moving edges from top tier to middle tier is not supported."
3275  << endl;
3276  }
3277  else if (i11 < 12 && ((i11 < 4) ||
3278  (i11 > 11 && o11 == 0) ||
3279  (i11 > 10 && o11 == 1) ))
3280  {
3281  move_to_e11(i11, o11, mesh, color, sock);
3282  }
3283  }
3284 }
3285 
3286 void
3287 swap_corners(Mesh & mesh, GridFunction & color, socketstream & sock,
3288  int * c0, int * c1)
3289 {
3290  if (logging_ > 1)
3291  {
3292  cout << "Entering swap_corners" << endl;
3293  }
3294 
3295  if (c0 != NULL)
3296  {
3297  // Locate first incorrectly filled corner location
3298  int i0 = -1;
3299  for (int i=0; i<8; i++)
3300  {
3301  if ((rubik.corn_[3 * i] == c0[0] &&
3302  rubik.corn_[3 * i + 1] == c0[1] &&
3303  rubik.corn_[3 * i + 2] == c0[2]) ||
3304  (rubik.corn_[3 * i] == c0[1] &&
3305  rubik.corn_[3 * i + 1] == c0[2] &&
3306  rubik.corn_[3 * i + 2] == c0[0]) ||
3307  (rubik.corn_[3 * i] == c0[2] &&
3308  rubik.corn_[3 * i + 1] == c0[0] &&
3309  rubik.corn_[3 * i + 2] == c0[1]) ||
3310  (rubik.corn_[3 * i] == c0[2] &&
3311  rubik.corn_[3 * i + 1] == c0[1] &&
3312  rubik.corn_[3 * i + 2] == c0[0]) ||
3313  (rubik.corn_[3 * i] == c0[1] &&
3314  rubik.corn_[3 * i + 1] == c0[0] &&
3315  rubik.corn_[3 * i + 2] == c0[2]) ||
3316  (rubik.corn_[3 * i] == c0[0] &&
3317  rubik.corn_[3 * i + 1] == c0[2] &&
3318  rubik.corn_[3 * i + 2] == c0[1]))
3319  {
3320  i0 = i;
3321  break;
3322  }
3323  }
3324  if (logging_ > 1)
3325  {
3326  cout << "Location of c0 = {"<<c0[0]<<","<<c0[1]<<","<<c0[2]<<"}: "
3327  << i0 << endl;
3328  }
3329 
3330  switch (i0)
3331  {
3332  case 0:
3333  swap_corners(mesh, color, sock, NULL, c1);
3334  break;
3335  case 1:
3336  case 2:
3337  case 3:
3338  anim_move('z', 1, i0, mesh, color, sock);
3339  swap_corners(mesh, color, sock, NULL, c1);
3340  anim_move('z', 1, 4-i0, mesh, color, sock);
3341  break;
3342  case 4:
3343  anim_move('x', 1, 3, mesh, color, sock);
3344  swap_corners(mesh, color, sock, NULL, c1);
3345  anim_move('x', 1, 1, mesh, color, sock);
3346  break;
3347  case 5:
3348  anim_move('y', 1, 2, mesh, color, sock);
3349  swap_corners(mesh, color, sock, NULL, c1);
3350  anim_move('y', 1, 2, mesh, color, sock);
3351  break;
3352  case 6:
3353  anim_move('z', 3, 2, mesh, color, sock);
3354  anim_move('x', 1, 3, mesh, color, sock);
3355  swap_corners(mesh, color, sock, NULL, c1);
3356  anim_move('x', 1, 1, mesh, color, sock);
3357  anim_move('z', 3, 2, mesh, color, sock);
3358  break;
3359  case 7:
3360  anim_move('x', 1, 2, mesh, color, sock);
3361  swap_corners(mesh, color, sock, NULL, c1);
3362  anim_move('x', 1, 2, mesh, color, sock);
3363  break;
3364  }
3365  }
3366  else if (c1 != NULL)
3367  {
3368  // Locate corner piece which belongs at i0
3369  int i1 = -1;
3370  for (int i=1; i<8; i++)
3371  {
3372  if ((rubik.corn_[3 * i] == c1[0] &&
3373  rubik.corn_[3 * i + 1] == c1[1] &&
3374  rubik.corn_[3 * i + 2] == c1[2]) ||
3375  (rubik.corn_[3 * i] == c1[1] &&
3376  rubik.corn_[3 * i + 1] == c1[2] &&
3377  rubik.corn_[3 * i + 2] == c1[0]) ||
3378  (rubik.corn_[3 * i] == c1[2] &&
3379  rubik.corn_[3 * i + 1] == c1[0] &&
3380  rubik.corn_[3 * i + 2] == c1[1]) ||
3381  (rubik.corn_[3 * i] == c1[2] &&
3382  rubik.corn_[3 * i + 1] == c1[1] &&
3383  rubik.corn_[3 * i + 2] == c1[0]) ||
3384  (rubik.corn_[3 * i] == c1[1] &&
3385  rubik.corn_[3 * i + 1] == c1[0] &&
3386  rubik.corn_[3 * i + 2] == c1[2]) ||
3387  (rubik.corn_[3 * i] == c1[0] &&
3388  rubik.corn_[3 * i + 1] == c1[2] &&
3389  rubik.corn_[3 * i + 2] == c1[1]))
3390  {
3391  i1 = i;
3392  break;
3393  }
3394  }
3395  if (logging_ > 1)
3396  {
3397  cout << "Location of piece belonging at " << 0 << " (c1) is "
3398  << i1 << endl;
3399  }
3400 
3401  switch (i1)
3402  {
3403  case 1:
3404  swap_corners(mesh, color, sock, NULL, NULL);
3405  break;
3406  case 2:
3407  anim_move('x', 3, 1, mesh, color, sock);
3408  swap_corners(mesh, color, sock, NULL, NULL);
3409  anim_move('x', 3, 3, mesh, color, sock);
3410  break;
3411  case 3:
3412  anim_move('y', 3, 1, mesh, color, sock);
3413  anim_move('x', 3, 1, mesh, color, sock);
3414  swap_corners(mesh, color, sock, NULL, NULL);
3415  anim_move('x', 3, 3, mesh, color, sock);
3416  anim_move('y', 3, 3, mesh, color, sock);
3417  break;
3418  case 4:
3419  anim_move('z', 3, 3, mesh, color, sock);
3420  anim_move('x', 3, 3, mesh, color, sock);
3421  swap_corners(mesh, color, sock, NULL, NULL);
3422  anim_move('x', 3, 1, mesh, color, sock);
3423  anim_move('z', 3, 1, mesh, color, sock);
3424  break;
3425  case 5:
3426  anim_move('x', 3, 3, mesh, color, sock);
3427  swap_corners(mesh, color, sock, NULL, NULL);
3428  anim_move('x', 3, 1, mesh, color, sock);
3429  break;
3430  case 6:
3431  anim_move('x', 3, 2, mesh, color, sock);
3432  swap_corners(mesh, color, sock, NULL, NULL);
3433  anim_move('x', 3, 2, mesh, color, sock);
3434  break;
3435  case 7:
3436  anim_move('z', 3, 2, mesh, color, sock);
3437  anim_move('x', 3, 3, mesh, color, sock);
3438  swap_corners(mesh, color, sock, NULL, NULL);
3439  anim_move('x', 3, 1, mesh, color, sock);
3440  anim_move('z', 3, 2, mesh, color, sock);
3441  break;
3442  }
3443  }
3444  else
3445  {
3446  anim_move('x', 3, 3, mesh, color, sock);
3447  anim_move('z', 1, 1, mesh, color, sock);
3448  anim_move('x', 3, 1, mesh, color, sock);
3449  anim_move('y', 1, 3, mesh, color, sock);
3450  anim_move('z', 1, 3, mesh, color, sock);
3451  anim_move('y', 1, 1, mesh, color, sock);
3452  anim_move('x', 3, 3, mesh, color, sock);
3453  anim_move('z', 1, 3, mesh, color, sock);
3454  anim_move('x', 3, 1, mesh, color, sock);
3455  anim_move('z', 1, 2, mesh, color, sock);
3456  }
3457 }
3458 
3459 void
3461 {
3462  if (logging_ > 1)
3463  {
3464  cout << "Entering solve_corner_locations" << endl;
3465  }
3466  if (logging_ > 2)
3467  {
3468  print_state(cout);
3469  }
3470 
3471  // Locate first incorrectly filled corner location
3472  int i0 = -1;
3473  for (int i=0; i<8; i++)
3474  {
3475  if (!((rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 0] &&
3476  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 1] &&
3477  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 2]) ||
3478  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 1] &&
3479  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 2] &&
3480  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 0]) ||
3481  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 2] &&
3482  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 0] &&
3483  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 1]) ||
3484  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 2] &&
3485  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 1] &&
3486  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 0]) ||
3487  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 1] &&
3488  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 0] &&
3489  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 2]) ||
3490  (rubik.corn_[3 * i + 0] == corn_colors_[3 * i + 0] &&
3491  rubik.corn_[3 * i + 1] == corn_colors_[3 * i + 2] &&
3492  rubik.corn_[3 * i + 2] == corn_colors_[3 * i + 1])))
3493  {
3494  i0 = i;
3495  break;
3496  }
3497  }
3498  if (logging_ > 1)
3499  {
3500  cout << "First incorrectly filled corner location: " << i0 << endl;
3501  }
3502 
3503  if (i0 < 0) { return; }
3504 
3505  // Locate corner piece which belongs at i0
3506  int l1 = locate_corner(i0);
3507  int i1 = l1 % 8;
3508  if (logging_ > 1)
3509  {
3510  cout << "Location of piece belonging at " << i0 << " is " << i1 << endl;
3511  }
3512 
3513  if (i1 < 0)
3514  {
3515  cout << "Invalid configuration of corners" << endl;
3516  return;
3517  }
3518 
3519  int c0[3] = {rubik.corn_[3 * i0],
3520  rubik.corn_[3 * i0 + 1],
3521  rubik.corn_[3 * i0 + 2]
3522  };
3523  int c1[3] = {rubik.corn_[3 * i1],
3524  rubik.corn_[3 * i1 + 1],
3525  rubik.corn_[3 * i1 + 2]
3526  };
3527 
3528  swap_corners(mesh, color, sock, c0, c1);
3529 
3530  solve_corner_locations(mesh, color, sock);
3531 }
3532 
3533 void
3535  socketstream & sock)
3536 {
3537  if (logging_ > 1)
3538  {
3539  cout << "Entering solve_bot_corner_locations" << endl;
3540  }
3541  if (logging_ > 2)
3542  {
3543  print_state(cout);
3544  }
3545 
3546  // Locate first corner in the bottom tier
3547  {
3548  int l0 = locate_corner(0);
3549  int i0 = l0 % 8;
3550  if (logging_ > 1)
3551  {
3552  cout << "Location of piece belonging at 0 is " << i0 << endl;
3553  }
3554  if (i0 != 0)
3555  {
3556  anim_move('z', 1, i0, mesh, color, sock);
3557  }
3558  }
3559 
3560  // Locate second corner in bottom tier
3561  {
3562  int l1 = locate_corner(1);
3563  int i1 = l1 % 8;
3564  if (logging_ > 1)
3565  {
3566  cout << "Location of piece belonging at 1 is " << i1 << endl;
3567  }
3568 
3569  if (i1 < 0)
3570  {
3571  cout << "Invalid configuration of corners" << endl;
3572  }
3573 
3574  switch (i1)
3575  {
3576  case 2:
3577  anim_move('y', 3, 3, mesh, color, sock);
3578  anim_move('z', 1, 1, mesh, color, sock);
3579  anim_move('y', 3, 1, mesh, color, sock);
3580  anim_move('x', 3, 1, mesh, color, sock);
3581  anim_move('z', 1, 3, mesh, color, sock);
3582  anim_move('x', 3, 3, mesh, color, sock);
3583  anim_move('y', 3, 3, mesh, color, sock);
3584  anim_move('z', 1, 3, mesh, color, sock);
3585  anim_move('y', 3, 1, mesh, color, sock);
3586  anim_move('z', 1, 2, mesh, color, sock);
3587  break;
3588  case 3:
3589  anim_move('y', 3, 3, mesh, color, sock);
3590  anim_move('z', 1, 1, mesh, color, sock);
3591  anim_move('y', 3, 1, mesh, color, sock);
3592  anim_move('x', 3, 1, mesh, color, sock);
3593  anim_move('z', 1, 2, mesh, color, sock);
3594  anim_move('x', 3, 3, mesh, color, sock);
3595  anim_move('y', 3, 3, mesh, color, sock);
3596  anim_move('z', 1, 3, mesh, color, sock);
3597  anim_move('y', 3, 1, mesh, color, sock);
3598  anim_move('z', 1, 3, mesh, color, sock);
3599  break;
3600  }
3601  }
3602 
3603  // Locate second corner in bottom tier
3604  {
3605  int l2 = locate_corner(2);
3606  int i2 = l2 % 8;
3607  if (logging_ > 1)
3608  {
3609  cout << "Location of piece belonging at 2 is " << i2 << endl;
3610  }
3611 
3612  if (i2 < 0)
3613  {
3614  cout << "Invalid configuration of corners" << endl;
3615  }
3616 
3617  if (i2 == 3)
3618  {
3619  anim_move('x', 1, 1, mesh, color, sock);
3620  anim_move('z', 1, 1, mesh, color, sock);
3621  anim_move('x', 1, 3, mesh, color, sock);
3622  anim_move('y', 3, 1, mesh, color, sock);
3623  anim_move('z', 1, 3, mesh, color, sock);
3624  anim_move('y', 3, 3, mesh, color, sock);
3625  anim_move('x', 1, 1, mesh, color, sock);
3626  anim_move('z', 1, 3, mesh, color, sock);
3627  anim_move('x', 1, 3, mesh, color, sock);
3628  anim_move('z', 1, 2, mesh, color, sock);
3629  }
3630  }
3631 }
3632 
3633 void
3635  bool cw, int * c0, int * c1, int * c2)
3636 {
3637  if (c0 != NULL)
3638  {
3639  // Locate corner corresponding to c0
3640  int i0 = -1;
3641  for (int i=0; i<8; i++)
3642  {
3643  if ((rubik.corn_[3 * i] == c0[0] &&
3644  rubik.corn_[3 * i + 1] == c0[1] &&
3645  rubik.corn_[3 * i + 2] == c0[2]) ||
3646  (rubik.corn_[3 * i] == c0[1] &&
3647  rubik.corn_[3 * i + 1] == c0[2] &&
3648  rubik.corn_[3 * i + 2] == c0[0]) ||
3649  (rubik.corn_[3 * i] == c0[2] &&
3650  rubik.corn_[3 * i + 1] == c0[0] &&
3651  rubik.corn_[3 * i + 2] == c0[1]) ||
3652  (rubik.corn_[3 * i] == c0[2] &&
3653  rubik.corn_[3 * i + 1] == c0[1] &&
3654  rubik.corn_[3 * i + 2] == c0[0]) ||
3655  (rubik.corn_[3 * i] == c0[1] &&
3656  rubik.corn_[3 * i + 1] == c0[0] &&
3657  rubik.corn_[3 * i + 2] == c0[2]) ||
3658  (rubik.corn_[3 * i] == c0[0] &&
3659  rubik.corn_[3 * i + 1] == c0[2] &&
3660  rubik.corn_[3 * i + 2] == c0[1]))
3661  {
3662  i0 = i;
3663  break;
3664  }
3665  }
3666  if (logging_ > 1)
3667  {
3668  cout << "Location of c0 = {"<<c0[0]<<","<<c0[1]<<","<<c0[2]<<"}: "
3669  << i0 << endl;
3670  }
3671 
3672  switch (i0)
3673  {
3674  case 0:
3675  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3676  break;
3677  case 1:
3678  case 2:
3679  case 3:
3680  anim_move('z', 1, i0, mesh, color, sock);
3681  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3682  anim_move('z', 1, 4-i0, mesh, color, sock);
3683  break;
3684  case 4:
3685  anim_move('x', 1, 3, mesh, color, sock);
3686  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3687  anim_move('x', 1, 1, mesh, color, sock);
3688  break;
3689  case 5:
3690  anim_move('y', 1, 2, mesh, color, sock);
3691  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3692  anim_move('y', 1, 2, mesh, color, sock);
3693  break;
3694  case 6:
3695  anim_move('z', 3, 2, mesh, color, sock);
3696  anim_move('x', 1, 3, mesh, color, sock);
3697  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3698  anim_move('x', 1, 1, mesh, color, sock);
3699  anim_move('z', 3, 2, mesh, color, sock);
3700  break;
3701  case 7:
3702  anim_move('x', 1, 2, mesh, color, sock);
3703  twist_corners(mesh, color, sock, cw, NULL, c1, c2);
3704  anim_move('x', 1, 2, mesh, color, sock);
3705  break;
3706  }
3707 
3708  }
3709  else if (c1 != NULL)
3710  {
3711  // Locate corner piece corresponding to c1
3712  int i1 = -1;
3713  for (int i=1; i<8; i++)
3714  {
3715  if ((rubik.corn_[3 * i] == c1[0] &&
3716  rubik.corn_[3 * i + 1] == c1[1] &&
3717  rubik.corn_[3 * i + 2] == c1[2]) ||
3718  (rubik.corn_[3 * i] == c1[1] &&
3719  rubik.corn_[3 * i + 1] == c1[2] &&
3720  rubik.corn_[3 * i + 2] == c1[0]) ||
3721  (rubik.corn_[3 * i] == c1[2] &&
3722  rubik.corn_[3 * i + 1] == c1[0] &&
3723  rubik.corn_[3 * i + 2] == c1[1]) ||
3724  (rubik.corn_[3 * i] == c1[2] &&
3725  rubik.corn_[3 * i + 1] == c1[1] &&
3726  rubik.corn_[3 * i + 2] == c1[0]) ||
3727  (rubik.corn_[3 * i] == c1[1] &&
3728  rubik.corn_[3 * i + 1] == c1[0] &&
3729  rubik.corn_[3 * i + 2] == c1[2]) ||
3730  (rubik.corn_[3 * i] == c1[0] &&
3731  rubik.corn_[3 * i + 1] == c1[2] &&
3732  rubik.corn_[3 * i + 2] == c1[1]))
3733  {
3734  i1 = i;
3735  break;
3736  }
3737  }
3738  if (logging_ > 1)
3739  {
3740  cout << "Location of c1 = {"<<c1[0]<<","<<c1[1]<<","<<c1[2]<<"}: "
3741  << i1 << endl;
3742  }
3743 
3744  if (c2 != NULL)
3745  {
3746  switch (i1)
3747  {
3748  case 1:
3749  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3750  break;
3751  case 2:
3752  anim_move('x', 3, 1, mesh, color, sock);
3753  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3754  anim_move('x', 3, 3, mesh, color, sock);
3755  break;
3756  case 3:
3757  anim_move('y', 3, 1, mesh, color, sock);
3758  anim_move('x', 3, 1, mesh, color, sock);
3759  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3760  anim_move('x', 3, 3, mesh, color, sock);
3761  anim_move('y', 3, 3, mesh, color, sock);
3762  break;
3763  case 4:
3764  anim_move('z', 3, 3, mesh, color, sock);
3765  anim_move('x', 3, 3, mesh, color, sock);
3766  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3767  anim_move('x', 3, 1, mesh, color, sock);
3768  anim_move('z', 3, 1, mesh, color, sock);
3769  break;
3770  case 5:
3771  anim_move('x', 3, 3, mesh, color, sock);
3772  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3773  anim_move('x', 3, 1, mesh, color, sock);
3774  break;
3775  case 6:
3776  anim_move('x', 3, 2, mesh, color, sock);
3777  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3778  anim_move('x', 3, 2, mesh, color, sock);
3779  break;
3780  case 7:
3781  anim_move('z', 3, 2, mesh, color, sock);
3782  anim_move('x', 3, 3, mesh, color, sock);
3783  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3784  anim_move('x', 3, 1, mesh, color, sock);
3785  anim_move('z', 3, 2, mesh, color, sock);
3786  break;
3787  }
3788  }
3789  else
3790  {
3791  switch (i1)
3792  {
3793  case 3:
3794  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3795  break;
3796  case 2:
3797  anim_move('y', 3, 3, mesh, color, sock);
3798  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3799  anim_move('y', 3, 1, mesh, color, sock);
3800  break;
3801  case 1:
3802  anim_move('x', 3, 3, mesh, color, sock);
3803  anim_move('y', 3, 3, mesh, color, sock);
3804  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3805  anim_move('y', 3, 1, mesh, color, sock);
3806  anim_move('x', 3, 1, mesh, color, sock);
3807  break;
3808  case 4:
3809  anim_move('z', 3, 1, mesh, color, sock);
3810  anim_move('y', 3, 1, mesh, color, sock);
3811  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3812  anim_move('y', 3, 3, mesh, color, sock);
3813  anim_move('z', 3, 3, mesh, color, sock);
3814  break;
3815  case 5:
3816  anim_move('z', 3, 2, mesh, color, sock);
3817  anim_move('y', 3, 1, mesh, color, sock);
3818  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3819  anim_move('y', 3, 3, mesh, color, sock);
3820  anim_move('z', 3, 2, mesh, color, sock);
3821  break;
3822  case 6:
3823  anim_move('y', 3, 2, mesh, color, sock);
3824  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3825  anim_move('y', 3, 2, mesh, color, sock);
3826  break;
3827  case 7:
3828  anim_move('y', 3, 1, mesh, color, sock);
3829  twist_corners(mesh, color, sock, cw, NULL, NULL, c2);
3830  anim_move('y', 3, 3, mesh, color, sock);
3831  break;
3832  }
3833  }
3834  }
3835  else if (c2 != NULL)
3836  {
3837  // Locate corner piece corresponding to c2
3838  int i2 = -1;
3839  for (int i=2; i<8; i++)
3840  {
3841  if ((rubik.corn_[3 * i] == c2[0] &&
3842  rubik.corn_[3 * i + 1] == c2[1] &&
3843  rubik.corn_[3 * i + 2] == c2[2]) ||
3844  (rubik.corn_[3 * i] == c2[1] &&
3845  rubik.corn_[3 * i + 1] == c2[2] &&
3846  rubik.corn_[3 * i + 2] == c2[0]) ||
3847  (rubik.corn_[3 * i] == c2[2] &&
3848  rubik.corn_[3 * i + 1] == c2[0] &&
3849  rubik.corn_[3 * i + 2] == c2[1]) ||
3850  (rubik.corn_[3 * i] == c2[2] &&
3851  rubik.corn_[3 * i + 1] == c2[1] &&
3852  rubik.corn_[3 * i + 2] == c2[0]) ||
3853  (rubik.corn_[3 * i] == c2[1] &&
3854  rubik.corn_[3 * i + 1] == c2[0] &&
3855  rubik.corn_[3 * i + 2] == c2[2]) ||
3856  (rubik.corn_[3 * i] == c2[0] &&
3857  rubik.corn_[3 * i + 1] == c2[2] &&
3858  rubik.corn_[3 * i + 2] == c2[1]))
3859  {
3860  i2 = i;
3861  break;
3862  }
3863  }
3864  if (logging_ > 1)
3865  {
3866  cout << "Location of c2 = {"<<c2[0]<<","<<c2[1]<<","<<c2[2]<<"}: "
3867  << i2 << endl;
3868  }
3869 
3870  switch (i2)
3871  {
3872  case 2:
3873  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3874  break;
3875  case 3:
3876  anim_move('y', 3, 1, mesh, color, sock);
3877  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3878  anim_move('y', 3, 3, mesh, color, sock);
3879  break;
3880  case 4:
3881  anim_move('z', 3, 2, mesh, color, sock);
3882  anim_move('y', 3, 3, mesh, color, sock);
3883  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3884  anim_move('y', 3, 1, mesh, color, sock);
3885  anim_move('z', 3, 2, mesh, color, sock);
3886  break;
3887  case 5:
3888  anim_move('z', 3, 3, mesh, color, sock);
3889  anim_move('y', 3, 3, mesh, color, sock);
3890  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3891  anim_move('y', 3, 1, mesh, color, sock);
3892  anim_move('z', 3, 1, mesh, color, sock);
3893  break;
3894  case 6:
3895  anim_move('y', 3, 3, mesh, color, sock);
3896  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3897  anim_move('y', 3, 1, mesh, color, sock);
3898  break;
3899  case 7:
3900  anim_move('y', 3, 2, mesh, color, sock);
3901  twist_corners(mesh, color, sock, cw, NULL, NULL, NULL);
3902  anim_move('y', 3, 2, mesh, color, sock);
3903  break;
3904  }
3905  }
3906  else
3907  {
3908  if (cw)
3909  {
3910  if (logging_ > 1)
3911  {
3912  cout << "twist_corners performing clockwise twist" << endl;
3913  }
3914  anim_move('x', 3, 1, mesh, color, sock);
3915  anim_move('z', 1, 3, mesh, color, sock);
3916  anim_move('x', 3, 3, mesh, color, sock);
3917  anim_move('z', 1, 3, mesh, color, sock);
3918  anim_move('x', 3, 1, mesh, color, sock);
3919  anim_move('z', 1, 2, mesh, color, sock);
3920  anim_move('x', 3, 3, mesh, color, sock);
3921  anim_move('z', 1, 2, mesh, color, sock);
3922  }
3923  else
3924  {
3925  if (logging_ > 1)
3926  {
3927  cout << "twist_corners performing counter-clockwise twist" << endl;
3928  }
3929  anim_move('y', 1, 1, mesh, color, sock);
3930  anim_move('z', 1, 1, mesh, color, sock);
3931  anim_move('y', 1, 3, mesh, color, sock);
3932  anim_move('z', 1, 1, mesh, color, sock);
3933  anim_move('y', 1, 1, mesh, color, sock);
3934  anim_move('z', 1, 2, mesh, color, sock);
3935  anim_move('y', 1, 3, mesh, color, sock);
3936  anim_move('z', 1, 2, mesh, color, sock);
3937  }
3938  }
3939 }
3940 
3941 void
3943  socketstream & sock)
3944 {
3945  if (logging_ > 1)
3946  {
3947  cout << "Entering solve_corner_orientations" << endl;
3948  }
3949  if (logging_ > 2)
3950  {
3951  print_state(cout);
3952  }
3953 
3954  // Locate first incorrectly oriented corner
3955  int i0 = -1;
3956  bool cw = true;
3957  for (int i=0; i<8; i++)
3958  {
3959  if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0])
3960  {
3961  i0 = i;
3962  switch (i0)
3963  {
3964  case 0:
3965  case 2:
3966  case 5:
3967  case 7:
3968  cw = rubik.corn_[3 * i0 + 0] == corn_colors_[3 * i0 + 1];
3969  break;
3970  case 1:
3971  case 3:
3972  case 4:
3973  case 6:
3974  cw = rubik.corn_[3 * i0 + 0] == corn_colors_[3 * i0 + 2];
3975  break;
3976  }
3977  break;
3978  }
3979  }
3980 
3981  if (i0 < 0) { return; }
3982 
3983  if (logging_ > 1)
3984  {
3985  cout << "First incorrectly oriented corner: " << i0 << endl;
3986  }
3987 
3988  // Locate second incorrectly oriented corner
3989  int i1 = -1;
3990  for (int i=i0+1; i<8; i++)
3991  {
3992  if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0])
3993  {
3994  i1 = i;
3995  break;
3996  }
3997  }
3998  if (logging_ > 1)
3999  {
4000  cout << "Second incorrectly oriented corner: " << i1 << endl;
4001  }
4002 
4003  // Locate third incorrectly oriented corner (if such exists)
4004  int i2 = -1;
4005  // int i3 = -1;
4006  for (int i=i1+1; i<8; i++)
4007  {
4008  if (rubik.corn_[3 * i + 0] != corn_colors_[3 * i + 0])
4009  {
4010  i2 = i;
4011  break;
4012  }
4013  }
4014  if (i2 > 0)
4015  {
4016  if (logging_ > 1)
4017  {
4018  cout << "Third incorrectly oriented corner: " << i2 << endl;
4019  }
4020 
4021  // Three incorrectly oriented corners were found
4022  int c0[3] = {rubik.corn_[3 * i0],
4023  rubik.corn_[3 * i0 + 1],
4024  rubik.corn_[3 * i0 + 2]
4025  };
4026  int c1[3] = {rubik.corn_[3 * i1],
4027  rubik.corn_[3 * i1 + 1],
4028  rubik.corn_[3 * i1 + 2]
4029  };
4030  int c2[3] = {rubik.corn_[3 * i2],
4031  rubik.corn_[3 * i2 + 1],
4032  rubik.corn_[3 * i2 + 2]
4033  };
4034 
4035  twist_corners(mesh, color, sock, cw, c0, c1, c2);
4036  }
4037  else
4038  {
4039  // Two incorrectly oriented corners were found
4040  int c0[3] = {rubik.corn_[3 * i0],
4041  rubik.corn_[3 * i0 + 1],
4042  rubik.corn_[3 * i0 + 2]
4043  };
4044  int c1[3] = {rubik.corn_[3 * i1],
4045  rubik.corn_[3 * i1 + 1],
4046  rubik.corn_[3 * i1 + 2]
4047  };
4048  twist_corners(mesh, color, sock, cw, c0, c1);
4049  }
4050 
4051  solve_corner_orientations(mesh, color, sock);
4052 }
4053 
4054 void
4056  int * e0, int * e1, int * e2)
4057 {
4058  if (logging_ > 1)
4059  {
4060  cout << "Entering permute_edges" << endl;
4061  }
4062 
4063  if (e0 != NULL)
4064  {
4065  // Locate first incorrectly filled edge location
4066  int i0 = -1;
4067  for (int i=0; i<12; i++)
4068  {
4069  if ((rubik.edge_[2 * i] == e0[0] &&
4070  rubik.edge_[2 * i + 1] == e0[1]) ||
4071  (rubik.edge_[2 * i] == e0[1] &&
4072  rubik.edge_[2 * i + 1] == e0[0]))
4073  {
4074  i0 = i;
4075  break;
4076  }
4077  }
4078  if (logging_ > 1)
4079  {
4080  cout << "Location of e0 = {"<<e0[0]<<","<<e0[1]<<"}: " << i0 << endl;
4081  }
4082 
4083  switch (i0)
4084  {
4085  case 0:
4086  permute_edges(mesh, color, sock, NULL, e1, e2);
4087  break;
4088  case 1:
4089  case 2:
4090  case 3:
4091  anim_move('z', 1, i0, mesh, color, sock);
4092  permute_edges(mesh, color, sock, NULL, e1, e2);
4093  anim_move('z', 1, 4-i0, mesh, color, sock);
4094  break;
4095  case 4:
4096  anim_move('x', 2, 3, mesh, color, sock);
4097  permute_edges(mesh, color, sock, NULL, e1, e2);
4098  anim_move('x', 2, 1, mesh, color, sock);
4099  break;
4100  case 5:
4101  anim_move('y', 2, 3, mesh, color, sock);
4102  permute_edges(mesh, color, sock, NULL, e1, e2);
4103  anim_move('y', 2, 1, mesh, color, sock);
4104  break;
4105  case 6:
4106  anim_move('x', 2, 2, mesh, color, sock);
4107  permute_edges(mesh, color, sock, NULL, e1, e2);
4108  anim_move('x', 2, 2, mesh, color, sock);
4109  break;
4110  case 7:
4111  anim_move('y', 2, 1, mesh, color, sock);
4112  permute_edges(mesh, color, sock, NULL, e1, e2);
4113  anim_move('y', 2, 3, mesh, color, sock);
4114  break;
4115  case 8:
4116  anim_move('y', 1, 1, mesh, color, sock);
4117  permute_edges(mesh, color, sock, NULL, e1, e2);
4118  anim_move('y', 1, 3, mesh, color, sock);
4119  break;
4120  case 9:
4121  anim_move('y', 1, 3, mesh, color, sock);
4122  permute_edges(mesh, color, sock, NULL, e1, e2);
4123  anim_move('y', 1, 1, mesh, color, sock);
4124  break;
4125  case 10:
4126  anim_move('x', 3, 1, mesh, color, sock);
4127  permute_edges(mesh, color, sock, NULL, e1, e2);
4128  anim_move('x', 3, 3, mesh, color, sock);
4129  break;
4130  case 11:
4131  anim_move('x', 1, 1, mesh, color, sock);
4132  permute_edges(mesh, color, sock, NULL, e1, e2);
4133  anim_move('x', 1, 3, mesh, color, sock);
4134  break;
4135  }
4136  }
4137  else if (e1 != NULL)
4138  {
4139  // Locate edge piece which belongs at e0
4140  int i1 = -1;
4141  for (int i=1; i<12; i++)
4142  {
4143  if ((rubik.edge_[2 * i] == e1[0] &&
4144  rubik.edge_[2 * i + 1] == e1[1]) ||
4145  (rubik.edge_[2 * i] == e1[1] &&
4146  rubik.edge_[2 * i + 1] == e1[0]))
4147  {
4148  i1 = i;
4149  break;
4150  }
4151  }
4152  if (logging_ > 1)
4153  {
4154  cout << "Location of piece belonging at " << 0 << " (e1) is "
4155  << i1 << endl;
4156  }
4157 
4158  switch (i1)
4159  {
4160  case 1:
4161  permute_edges(mesh, color, sock, NULL, NULL, e2);
4162  break;
4163  case 2:
4164  case 3:
4165  anim_move('y', 1, 1, mesh, color, sock);
4166  anim_move('z', 1, i1-1, mesh, color, sock);
4167  anim_move('y', 1, 3, mesh, color, sock);
4168  permute_edges(mesh, color, sock, NULL, NULL, e2);
4169  anim_move('y', 1, 1, mesh, color, sock);
4170  anim_move('z', 1, 5-i1, mesh, color, sock);
4171  anim_move('y', 1, 3, mesh, color, sock);
4172  break;
4173  case 4:
4174  case 5:
4175  case 6:
4176  case 7:
4177  anim_move('z', 3, (i1-1)%4, mesh, color, sock);
4178  anim_move('x', 3, 2, mesh, color, sock);
4179  permute_edges(mesh, color, sock, NULL, NULL, e2);
4180  anim_move('x', 3, 2, mesh, color, sock);
4181  anim_move('z', 3, (9-i1)%4, mesh, color, sock);
4182  break;
4183  case 8:
4184  case 9:
4185  case 10:
4186  case 11:
4187  anim_move('z', 2, (i1-5)%4, mesh, color, sock);
4188  anim_move('x', 3, 3, mesh, color, sock);
4189  permute_edges(mesh, color, sock, NULL, NULL, e2);
4190  anim_move('x', 3, 1, mesh, color, sock);
4191  anim_move('z', 2, (13-i1)%4, mesh, color, sock);
4192  break;
4193  }
4194  }
4195  else if (e2 != NULL)
4196  {
4197  // Locate a third incorrect edge
4198  int i2 = -1;
4199  for (int i=2; i<12; i++)
4200  {
4201  if ((rubik.edge_[2 * i] == e2[0] &&
4202  rubik.edge_[2 * i + 1] == e2[1]) ||
4203  (rubik.edge_[2 * i] == e2[1] &&
4204  rubik.edge_[2 * i + 1] == e2[0]))
4205  {
4206  i2 = i;
4207  break;
4208  }
4209  }
4210  if (logging_ > 1)
4211  {
4212  cout << "Location of e2: " << i2 << endl;
4213  }
4214 
4215  switch (i2)
4216  {
4217  case 2:
4218  permute_edges(mesh, color, sock, NULL, NULL, NULL);
4219  break;
4220  case 3:
4221  anim_move('x', 1, 3, mesh, color, sock);
4222  anim_move('y', 3, 1, mesh, color, sock);
4223  permute_edges(mesh, color, sock, NULL, NULL, NULL);
4224  anim_move('y', 3, 3, mesh, color, sock);
4225  anim_move('x', 1, 1, mesh, color, sock);
4226  break;
4227  case 4:
4228  case 5:
4229  case 6:
4230  case 7:
4231  anim_move('z', 3, (i2-2)%4, mesh, color, sock);
4232  anim_move('y', 3, 2, mesh, color, sock);
4233  permute_edges(mesh, color, sock, NULL, NULL, NULL);
4234  anim_move('y', 3, 2, mesh, color, sock);
4235  anim_move('z', 3, (10-i2)%4, mesh, color, sock);
4236  break;
4237  case 8:
4238  case 9:
4239  case 10:
4240  case 11:
4241  anim_move('z', 2, (i2-6)%4, mesh, color, sock);
4242  anim_move('y', 3, 3, mesh, color, sock);
4243  permute_edges(mesh, color, sock, NULL, NULL, NULL);
4244  anim_move('y', 3, 1, mesh, color, sock);
4245  anim_move('z', 2, (14-i2)%4, mesh, color, sock);
4246  break;
4247  }
4248  }
4249  else
4250  {
4251  permute_edges(mesh, color, sock, true);
4252  }
4253 }
4254 
4255 void
4256 permute_edges(Mesh & mesh, GridFunction & color, socketstream & sock, bool cw)
4257 {
4258  if (cw)
4259  {
4260  anim_move('y', 2, 1, mesh, color, sock);
4261  anim_move('z', 1, 1, mesh, color, sock);
4262  anim_move('y', 2, 3, mesh, color, sock);
4263  anim_move('z', 1, 2, mesh, color, sock);
4264  anim_move('y', 2, 1, mesh, color, sock);
4265  anim_move('z', 1, 1, mesh, color, sock);
4266  anim_move('y', 2, 3, mesh, color, sock);
4267  }
4268  else
4269  {
4270  anim_move('y', 2, 1, mesh, color, sock);
4271  anim_move('z', 1, 3, mesh, color, sock);
4272  anim_move('y', 2, 3, mesh, color, sock);
4273  anim_move('z', 1, 2, mesh, color, sock);
4274  anim_move('y', 2, 1, mesh, color, sock);
4275  anim_move('z', 1, 3, mesh, color, sock);
4276  anim_move('y', 2, 3, mesh, color, sock);
4277  }
4278 }
4279 
4280 void
4282 {
4283  if (logging_ > 1)
4284  {
4285  cout << "Entering solve_edge_locations" << endl;
4286  }
4287  if (logging_ > 2)
4288  {
4289  print_state(cout);
4290  }
4291 
4292  // Locate first incorrectly filled edge location
4293  int i0 = -1;
4294  for (int i=0; i<12; i++)
4295  {
4296  if (!((rubik.edge_[2 * i] == edge_colors_[2 * i] &&
4297  rubik.edge_[2 * i + 1] == edge_colors_[2 * i + 1]) ||
4298  (rubik.edge_[2 * i] == edge_colors_[2 * i + 1] &&
4299  rubik.edge_[2 * i + 1] == edge_colors_[2 * i])))
4300  {
4301  i0 = i;
4302  break;
4303  }
4304  }
4305  if (logging_ > 1)
4306  {
4307  cout << "First incorrectly filled edge location: " << i0 << endl;
4308  }
4309 
4310  if (i0 < 0) { return; }
4311 
4312  // Locate edge piece which belongs at e0
4313  int i1 = locate_edge(i0);
4314  if (i1 < 0 ) { i1 = -1 - i1; }
4315  if (logging_ > 1)
4316  {
4317  cout << "Location of piece belonging at " << i0 << " is " << i1 << endl;
4318  }
4319 
4320  // Locate a third incorrect edge
4321  int i2 = -1;
4322  for (int i=i0+1; i<12; i++)
4323  {
4324  if (i == i1) { continue; }
4325  if (!((rubik.edge_[2 * i + 0] == edge_colors_[2 * i + 0] &&
4326  rubik.edge_[2 * i + 1] == edge_colors_[2 * i + 1]) ||
4327  (rubik.edge_[2 * i + 0] == edge_colors_[2 * i + 1] &&
4328  rubik.edge_[2 * i + 1] == edge_colors_[2 * i + 0])))
4329  {
4330  i2 = i;
4331  break;
4332  }
4333  }
4334  if (logging_ > 1)
4335  {
4336  cout << "Another incorrectly filled edge location: " << i2 << endl;
4337  }
4338 
4339  if (i1 < 0 || i2 <0)
4340  {
4341  cout << "Invalid configuration of edges" << endl;
4342  return;
4343  }
4344 
4345  int e0[2] = {rubik.edge_[2 * i0], rubik.edge_[2 * i0 + 1]};
4346  int e1[2] = {rubik.edge_[2 * i1], rubik.edge_[2 * i1 + 1]};
4347  int e2[2] = {rubik.edge_[2 * i2], rubik.edge_[2 * i2 + 1]};
4348 
4349  permute_edges(mesh, color, sock, e0, e1, e2);
4350 
4351  solve_edge_locations(mesh, color, sock);
4352 }
4353 
4354 void
4355 flip_edges(Mesh & mesh, GridFunction & color, socketstream & sock,
4356  int n, int * e0, int * e1, int * e2, int * e3)
4357 {
4358  if (n == 2)
4359  {
4360  if (e0 != NULL)
4361  {
4362  // Locate first incorrectly oriented edge
4363  int i0 = -1;
4364  for (int i=0; i<12; i++)
4365  {
4366  if ((rubik.edge_[2 * i] == e0[0] &&
4367  rubik.edge_[2 * i + 1] == e0[1]) ||
4368  (rubik.edge_[2 * i] == e0[1] &&
4369  rubik.edge_[2 * i + 1] == e0[0]))
4370  {
4371  i0 = i;
4372  break;
4373  }
4374  }
4375  if (logging_ > 1)
4376  {
4377  cout << "Location of e0 = {"<<e0[0]<<","<<e0[1]<<"}: " << i0 << endl;
4378  }
4379 
4380  switch (i0)
4381  {
4382  case 0:
4383  flip_edges(mesh, color, sock, 2, NULL, e1);
4384  break;
4385  case 1:
4386  case 2:
4387  case 3:
4388  anim_move('z', 1, i0, mesh, color, sock);
4389  flip_edges(mesh, color, sock, 2, NULL, e1);
4390  anim_move('z', 1, 4-i0, mesh, color, sock);
4391  break;
4392  case 4:
4393  anim_move('x', 2, 3, mesh, color, sock);
4394  flip_edges(mesh, color, sock, 2, NULL, e1);
4395  anim_move('x', 2, 1, mesh, color, sock);
4396  break;
4397  case 5:
4398  anim_move('y', 2, 3, mesh, color, sock);
4399  flip_edges(mesh, color, sock, 2, NULL, e1);
4400  anim_move('y', 2, 1, mesh, color, sock);
4401  break;
4402  case 6:
4403  anim_move('x', 2, 2, mesh, color, sock);
4404  flip_edges(mesh, color, sock, 2, NULL, e1);
4405  anim_move('x', 2, 2, mesh, color, sock);
4406  break;
4407  case 7:
4408  anim_move('y', 2, 1, mesh, color, sock);
4409  flip_edges(mesh, color, sock, 2, NULL, e1);
4410  anim_move('y', 2, 3, mesh, color, sock);
4411  break;
4412  case 8:
4413  anim_move('y', 1, 1, mesh, color, sock);
4414  flip_edges(mesh, color, sock, 2, NULL, e1);
4415  anim_move('y', 1, 3, mesh, color, sock);
4416  break;
4417  case 9:
4418  anim_move('y', 1, 3, mesh, color, sock);
4419  flip_edges(mesh, color, sock, 2, NULL, e1);
4420  anim_move('y', 1, 1, mesh, color, sock);
4421  break;
4422  case 10:
4423  anim_move('x', 3, 1, mesh, color, sock);
4424  flip_edges(mesh, color, sock, 2, NULL, e1);
4425  anim_move('x', 3, 3, mesh, color, sock);
4426  break;
4427  case 11:
4428  anim_move('x', 1, 1, mesh, color, sock);
4429  flip_edges(mesh, color, sock, 2, NULL, e1);
4430  anim_move('x', 1, 3, mesh, color, sock);
4431  break;
4432  }
4433  }
4434  else if (e1 != NULL)
4435  {
4436  // Locate second incorrectly oriented edge
4437  int i1 = -1;
4438  for (int i=1; i<12; i++)
4439  {
4440  if ((rubik.edge_[2 * i] == e1[0] &&
4441  rubik.edge_[2 * i + 1] == e1[1]) ||
4442  (rubik.edge_[2 * i] == e1[1] &&
4443  rubik.edge_[2 * i + 1] == e1[0]))
4444  {
4445  i1 = i;
4446  break;
4447  }
4448  }
4449  if (logging_ > 1)
4450  {
4451  cout << "Location of e1: " << i1 << endl;
4452  }
4453 
4454  switch (i1)
4455  {
4456  case 1:
4457  anim_move('x', 3, 3, mesh, color, sock);
4458  anim_move('y', 3, 3, mesh, color, sock);
4459  flip_edges(mesh, color, sock, 2, NULL, NULL);
4460  anim_move('y', 3, 1, mesh, color, sock);
4461  anim_move('x', 3, 1, mesh, color, sock);
4462  break;
4463  case 2:
4464  flip_edges(mesh, color, sock, 2, NULL, NULL);
4465  break;
4466  case 3:
4467  anim_move('x', 1, 3, mesh, color, sock);
4468  anim_move('y', 3, 1, mesh, color, sock);
4469  flip_edges(mesh, color, sock, 2, NULL, NULL);
4470  anim_move('y', 3, 3, mesh, color, sock);
4471  anim_move('x', 1, 1, mesh, color, sock);
4472  break;
4473  case 4:
4474  case 5:
4475  case 6:
4476  case 7:
4477  anim_move('z', 3, (i1-2)%4, mesh, color, sock);
4478  anim_move('y', 3, 2, mesh, color, sock);
4479  flip_edges(mesh, color, sock, 2, NULL, NULL);
4480  anim_move('y', 3, 2, mesh, color, sock);
4481  anim_move('z', 3, (10-i1)%4, mesh, color, sock);
4482  break;
4483  case 8:
4484  case 9:
4485  case 10:
4486  case 11:
4487  anim_move('z', 2, (i1-6)%4, mesh, color, sock);
4488  anim_move('y', 3, 3, mesh, color, sock);
4489  flip_edges(mesh, color, sock, 2, NULL, NULL);
4490  anim_move('y', 3, 1, mesh, color, sock);
4491  anim_move('z', 2, (14-i1)%4, mesh, color, sock);
4492  break;
4493  }
4494  }
4495  else
4496  {
4497  anim_move('x', 2, 3, mesh, color, sock);
4498  anim_move('z', 1, 3, mesh, color, sock);
4499  anim_move('x', 2, 1, mesh, color, sock);
4500  anim_move('z', 1, 3, mesh, color, sock);
4501  anim_move('x', 2, 3, mesh, color, sock);
4502  anim_move('z', 1, 3, mesh, color, sock);
4503  anim_move('x', 2, 1, mesh, color, sock);
4504  anim_move('z', 1, 3, mesh, color, sock);
4505  anim_move('x', 2, 3, mesh, color, sock);
4506  anim_move('z', 1, 2, mesh, color, sock);
4507  anim_move('x', 2, 1, mesh, color, sock);
4508  anim_move('z', 1, 3, mesh, color, sock);
4509  anim_move('x', 2, 3, mesh, color, sock);
4510  anim_move('z', 1, 3, mesh, color, sock);
4511  anim_move('x', 2, 1, mesh, color, sock);
4512  anim_move('z', 1, 3, mesh, color, sock);
4513  anim_move('x', 2, 3, mesh, color, sock);
4514  anim_move('z', 1, 3, mesh, color, sock);
4515  anim_move('x', 2, 1, mesh, color, sock);
4516  anim_move('z', 1, 2, mesh, color, sock);
4517  }
4518  }
4519  else if (n == 4)
4520  {
4521  if (e0 != NULL)
4522  {
4523  // Locate first incorrectly oriented edge
4524  int i0 = -1;
4525  for (int i=0; i<12; i++)
4526  {
4527  if ((rubik.edge_[2 * i] == e0[0] &&
4528  rubik.edge_[2 * i + 1] == e0[1]) ||
4529  (rubik.edge_[2 * i] == e0[1] &&
4530  rubik.edge_[2 * i + 1] == e0[0]))
4531  {
4532  i0 = i;
4533  break;
4534  }
4535  }
4536  if (logging_ > 1)
4537  {
4538  cout << "Location of e0 = {"<<e0[0]<<","<<e0[1]<<"}: " << i0 << endl;
4539  }
4540 
4541  switch (i0)
4542  {
4543  case 0:
4544  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4545  break;
4546  case 1:
4547  case 2:
4548  case 3:
4549  anim_move('z', 1, i0, mesh, color, sock);
4550  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4551  anim_move('z', 1, 4-i0, mesh, color, sock);
4552  break;
4553  case 4:
4554  anim_move('x', 2, 3, mesh, color, sock);
4555  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4556  anim_move('x', 2, 1, mesh, color, sock);
4557  break;
4558  case 5:
4559  anim_move('y', 2, 3, mesh, color, sock);
4560  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4561  anim_move('y', 2, 1, mesh, color, sock);
4562  break;
4563  case 6:
4564  anim_move('x', 2, 2, mesh, color, sock);
4565  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4566  anim_move('x', 2, 2, mesh, color, sock);
4567  break;
4568  case 7:
4569  anim_move('y', 2, 1, mesh, color, sock);
4570  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4571  anim_move('y', 2, 3, mesh, color, sock);
4572  break;
4573  case 8:
4574  anim_move('y', 1, 1, mesh, color, sock);
4575  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4576  anim_move('y', 1, 3, mesh, color, sock);
4577  break;
4578  case 9:
4579  anim_move('y', 1, 3, mesh, color, sock);
4580  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4581  anim_move('y', 1, 1, mesh, color, sock);
4582  break;
4583  case 10:
4584  anim_move('x', 3, 1, mesh, color, sock);
4585  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4586  anim_move('x', 3, 3, mesh, color, sock);
4587  break;
4588  case 11:
4589  anim_move('x', 1, 1, mesh, color, sock);
4590  flip_edges(mesh, color, sock, 4, NULL, e1, e2, e3);
4591  anim_move('x', 1, 3, mesh, color, sock);
4592  break;
4593  }
4594  }
4595  else if (e1 != NULL)
4596  {
4597  // Locate second incorrectly oriented edge
4598  int i1 = -1;
4599  for (int i=1; i<12; i++)
4600  {
4601  if ((rubik.edge_[2 * i] == e1[0] &&
4602  rubik.edge_[2 * i + 1] == e1[1]) ||
4603  (rubik.edge_[2 * i] == e1[1] &&
4604  rubik.edge_[2 * i + 1] == e1[0]))
4605  {
4606  i1 = i;
4607  break;
4608  }
4609  }
4610  if (logging_ > 1)
4611  {
4612  cout << "Location of e1: " << i1 << endl;
4613  }
4614 
4615  switch (i1)
4616  {
4617  case 1:
4618  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4619  break;
4620  case 2:
4621  anim_move('y', 3, 1, mesh, color, sock);
4622  anim_move('x', 3, 1, mesh, color, sock);
4623  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4624  anim_move('x', 3, 3, mesh, color, sock);
4625  anim_move('y', 3, 3, mesh, color, sock);
4626  break;
4627  case 3:
4628  anim_move('y', 2, 1, mesh, color, sock);
4629  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4630  anim_move('y', 2, 3, mesh, color, sock);
4631  break;
4632  case 4:
4633  case 5:
4634  case 6:
4635  case 7:
4636  anim_move('z', 3, (i1-1)%4, mesh, color, sock);
4637  anim_move('x', 3, 2, mesh, color, sock);
4638  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4639  anim_move('x', 3, 2, mesh, color, sock);
4640  anim_move('z', 3, (9-i1)%4, mesh, color, sock);
4641  break;
4642  case 8:
4643  case 9:
4644  case 10:
4645  case 11:
4646  anim_move('z', 2, (i1-5)%4, mesh, color, sock);
4647  anim_move('x', 3, 3, mesh, color, sock);
4648  flip_edges(mesh, color, sock, 4, NULL, NULL, e2, e3);
4649  anim_move('x', 3, 1, mesh, color, sock);
4650  anim_move('z', 2, (13-i1)%4, mesh, color, sock);
4651  break;
4652  }
4653  }
4654  else if (e2 != NULL)
4655  {
4656  // Locate third incorrectly oriented edge
4657  int i2 = -1;
4658  for (int i=2; i<12; i++)
4659  {
4660  if ((rubik.edge_[2 * i] == e2[0] &&
4661  rubik.edge_[2 * i + 1] == e2[1]) ||
4662  (rubik.edge_[2 * i] == e2[1] &&
4663  rubik.edge_[2 * i + 1] == e2[0]))
4664  {
4665  i2 = i;
4666  break;
4667  }
4668  }
4669  if (logging_ > 1)
4670  {
4671  cout << "Location of e2: " << i2 << endl;
4672  }
4673 
4674  switch (i2)
4675  {
4676  case 2:
4677  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3);
4678  break;
4679  case 3:
4680  anim_move('x', 1, 3, mesh, color, sock);
4681  anim_move('y', 3, 1, mesh, color, sock);
4682  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3);
4683  anim_move('y', 3, 3, mesh, color, sock);
4684  anim_move('x', 1, 1, mesh, color, sock);
4685  break;
4686  case 4:
4687  case 5:
4688  case 6:
4689  case 7:
4690  anim_move('z', 3, (i2-2)%4, mesh, color, sock);
4691  anim_move('y', 3, 2, mesh, color, sock);
4692  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3);
4693  anim_move('y', 3, 2, mesh, color, sock);
4694  anim_move('z', 3, (10-i2)%4, mesh, color, sock);
4695  break;
4696  case 8:
4697  case 9:
4698  case 10:
4699  case 11:
4700  anim_move('z', 2, (i2-6)%4, mesh, color, sock);
4701  anim_move('y', 3, 3, mesh, color, sock);
4702  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, e3);
4703  anim_move('y', 3, 1, mesh, color, sock);
4704  anim_move('z', 2, (14-i2)%4, mesh, color, sock);
4705  break;
4706  }
4707  }
4708  else if (e3 != NULL)
4709  {
4710  // Locate fourth incorrectly oriented edge
4711  int i3 = -1;
4712  for (int i=3; i<12; i++)
4713  {
4714  if ((rubik.edge_[2 * i] == e3[0] &&
4715  rubik.edge_[2 * i + 1] == e3[1]) ||
4716  (rubik.edge_[2 * i] == e3[1] &&
4717  rubik.edge_[2 * i + 1] == e3[0]))
4718  {
4719  i3 = i;
4720  break;
4721  }
4722  }
4723  if (logging_ > 1)
4724  {
4725  cout << "Location of e3: " << i3 << endl;
4726  }
4727 
4728  switch (i3)
4729  {
4730  case 3:
4731  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, NULL);
4732  break;
4733  case 4:
4734  case 5:
4735  case 6:
4736  case 7:
4737  anim_move('z', 3, (i3-3)%4, mesh, color, sock);
4738  anim_move('x', 1, 2, mesh, color, sock);
4739  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, NULL);
4740  anim_move('x', 1, 2, mesh, color, sock);
4741  anim_move('z', 3, (7-i3)%4, mesh, color, sock);
4742  break;
4743  case 8:
4744  case 9:
4745  case 10:
4746  case 11:
4747  anim_move('z', 2, (i3-4)%4, mesh, color, sock);
4748  anim_move('x', 1, 3, mesh, color, sock);
4749  flip_edges(mesh, color, sock, 4, NULL, NULL, NULL, NULL);
4750  anim_move('x', 1, 1, mesh, color, sock);
4751  anim_move('z', 2, (12-i3)%4, mesh, color, sock);
4752  break;
4753  }
4754  }
4755  else
4756  {
4757  anim_move('x', 2, 3, mesh, color, sock);
4758  anim_move('z', 1, 2, mesh, color, sock);
4759  anim_move('x', 2, 1, mesh, color, sock);
4760  anim_move('z', 1, 2, mesh, color, sock);
4761  anim_move('x', 2, 3, mesh, color, sock);
4762  anim_move('z', 1, 3, mesh, color, sock);
4763  anim_move('x', 2, 1, mesh, color, sock);
4764  anim_move('z', 1, 2, mesh, color, sock);
4765  anim_move('x', 2, 3, mesh, color, sock);
4766  anim_move('z', 1, 2, mesh, color, sock);
4767  anim_move('x', 2, 1, mesh, color, sock);
4768  anim_move('z', 1, 1, mesh, color, sock);
4769  }
4770  }
4771 }
4772 
4773 void
4775 {
4776  if (logging_ > 1)
4777  {
4778  cout << "Entering solve_edge_orientations" << endl;
4779  }
4780  if (logging_ > 2)
4781  {
4782  print_state(cout);
4783  }
4784 
4785  // Locate first incorrectly oriented edge
4786  int i0 = -1;
4787  for (int i=0; i<12; i++)
4788  {
4789  if (rubik.edge_[2 * i] != edge_colors_[2 * i])
4790  {
4791  i0 = i;
4792  break;
4793  }
4794  }
4795  if (logging_ > 1)
4796  {
4797  cout << "First incorrectly oriented edge location: " << i0 << endl;
4798  }
4799 
4800  if (i0 < 0) { return; }
4801 
4802  // Locate second incorrectly oriented edge
4803  int i1 = -1;
4804  for (int i=i0+1; i<12; i++)
4805  {
4806  if (rubik.edge_[2 * i] != edge_colors_[2 * i])
4807  {
4808  i1 = i;
4809  break;
4810  }
4811  }
4812  if (logging_ > 1)
4813  {
4814  cout << "Second incorrectly oriented edge location: " << i1 << endl;
4815  }
4816 
4817  // Locate third incorrectly oriented edge (if such exists)
4818  int i2 = -1;
4819  int i3 = -1;
4820  for (int i=i1+1; i<12; i++)
4821  {
4822  if (rubik.edge_[2 * i] != edge_colors_[2 * i])
4823  {
4824  i2 = i;
4825  break;
4826  }
4827  }
4828  if (i2 > 0)
4829  {
4830  if (logging_ > 1)
4831  {
4832  cout << "Third incorrectly oriented edge location: " << i2 << endl;
4833  }
4834 
4835  // Locate fourth incorrectly oriented edge (if such exists)
4836  for (int i=i2+1; i<12; i++)
4837  {
4838  if (rubik.edge_[2 * i] != edge_colors_[2 * i])
4839  {
4840  i3 = i;
4841  break;
4842  }
4843  }
4844  if (logging_ > 1)
4845  {
4846  cout << "Fourth incorrectly oriented edge location: " << i3 << endl;
4847  }
4848  }
4849 
4850  int e0[2] = {rubik.edge_[2 * i0], rubik.edge_[2 * i0 + 1]};
4851  int e1[2] = {rubik.edge_[2 * i1], rubik.edge_[2 * i1 + 1]};
4852  int e2[2] = {rubik.edge_[2 * max(i2,0)], rubik.edge_[2 * max(i2,0) + 1]};
4853  int e3[2] = {rubik.edge_[2 * max(i3,0)], rubik.edge_[2 * max(i3,0) + 1]};
4854 
4855  if (i2 == -1)
4856  {
4857  flip_edges(mesh, color, sock, 2, e0, e1);
4858  }
4859  else
4860  {
4861  flip_edges(mesh, color, sock, 4, e0, e1, e2, e3);
4862  }
4863 
4864  solve_edge_orientations(mesh, color, sock);
4865 }
4866 
4867 void
4868 solve_top(Mesh & mesh, GridFunction & color, socketstream & sock)
4869 {
4870  count_ = 0;
4871  if (logging_ > 0)
4872  {
4873  cout << "Solving top center block..." << endl;
4874  }
4875  solve_top_center(mesh, color, sock);
4876  if (logging_ > 0)
4877  {
4878  cout << "Solving top tier edges..." << endl;
4879  }
4880  solve_top_edges(mesh, color, sock);
4881  if (logging_ > 0)
4882  {
4883  cout << "Solving center blocks..." << endl;
4884  }
4885  if (logging_ > 0)
4886  {
4887  cout << "Solving top tier corners..." << endl;
4888  }
4889  solve_top_corners(mesh, color, sock);
4890 
4891  cout << "Move count: " << count_ << endl;
4892 }
4893 
4894 void
4895 solve_mid(Mesh & mesh, GridFunction & color, socketstream & sock)
4896 {
4897  count_ = 0;
4898  if (logging_ > 0)
4899  {
4900  cout << "Solving center blocks in the middle tier..." << endl;
4901  }
4902  solve_centers(mesh, color, sock);
4903  if (logging_ > 0)
4904  {
4905  cout << "Solving edge blocks in the middle tier..." << endl;
4906  }
4907  solve_mid_edges(mesh, color, sock);
4908 
4909  cout << "Move count: " << count_ << endl;
4910 }
4911 
4912 void
4913 solve_bot(Mesh & mesh, GridFunction & color, socketstream & sock)
4914 {
4915  if (logging_ > 0)
4916  {
4917  cout << "Solving corner block locations in the bottom tier..." << endl;
4918  }
4919  solve_bot_corner_locations(mesh, color, sock);
4920  if (logging_ > 0)
4921  {
4922  cout << "Solving corner block orientations..." << endl;
4923  }
4924  solve_corner_orientations(mesh, color, sock);
4925  if (logging_ > 0)
4926  {
4927  cout << "Solving edge block locations..." << endl;
4928  }
4929  solve_edge_locations(mesh, color, sock);
4930  if (logging_ > 0)
4931  {
4932  cout << "Solving edge block orientations..." << endl;
4933  }
4934  solve_edge_orientations(mesh, color, sock);
4935 }
4936 
4937 void
4938 solve(Mesh & mesh, GridFunction & color, socketstream & sock)
4939 {
4940  count_ = 0;
4941  if (logging_ > 0)
4942  {
4943  cout << "Solving top center block..." << endl;
4944  }
4945  solve_top_center(mesh, color, sock);
4946  if (logging_ > 0)
4947  {
4948  cout << "Solving top tier edges..." << endl;
4949  }
4950  solve_top_edges(mesh, color, sock);
4951  if (logging_ > 0)
4952  {
4953  cout << "Solving top tier corners..." << endl;
4954  }
4955  solve_top_corners(mesh, color, sock);
4956  if (logging_ > 0)
4957  {
4958  cout << "Solving center blocks in the middle tier..." << endl;
4959  }
4960  solve_centers(mesh, color, sock);
4961  if (logging_ > 0)
4962  {
4963  cout << "Solving edge blocks in the middle tier..." << endl;
4964  }
4965  solve_mid_edges(mesh, color, sock);
4966  if (logging_ > 0)
4967  {
4968  cout << "Solving corner block locations in the bottom tier..." << endl;
4969  }
4970  solve_bot_corner_locations(mesh, color, sock);
4971  if (logging_ > 0)
4972  {
4973  cout << "Solving corner block orientations..." << endl;
4974  }
4975  solve_corner_orientations(mesh, color, sock);
4976  if (logging_ > 0)
4977  {
4978  cout << "Solving edge block locations..." << endl;
4979  }
4980  solve_edge_locations(mesh, color, sock);
4981  if (logging_ > 0)
4982  {
4983  cout << "Solving edge block orientations..." << endl;
4984  }
4985  solve_edge_orientations(mesh, color, sock);
4986 
4987  cout << "Move count: " << count_ << endl;
4988 }
void move_to_e7(int i7, int o7, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2463
void solve(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4938
int locate_corner(int ind)
Definition: rubik.cpp:1371
int visport
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:2552
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:2855
void PrintOptions(std::ostream &out) const
Print the options.
Definition: optparser.cpp:331
void update_centers(char axis, int incr)
Definition: rubik.cpp:560
int main(int argc, char *argv[])
Definition: rubik.cpp:187
void solve_edge_orientations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4774
void PrintUsage(std::ostream &out) const
Print the usage message.
Definition: optparser.cpp:462
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:1930
void solve_mid(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4895
void move_to_c4(int i4, int o4, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1416
void GetBdrElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of boundary element i.
Definition: mesh.hpp:1297
bool Good() const
Return true if the command line options were parsed successfully.
Definition: optparser.hpp:159
STL namespace.
void move_to_e5(int i5, int o5, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2259
int GetNBE() const
Returns number of boundary elements.
Definition: mesh.hpp:1089
void permute_edges(Mesh &mesh, GridFunction &color, socketstream &sock, int *e0, int *e1, int *e2)
Definition: rubik.cpp:4055
int GetAttribute(int i) const
Return the attribute of element i.
Definition: mesh.hpp:1190
void solve_edge_locations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4281
int AddVertex(double x, double y=0.0, double z=0.0)
Definition: mesh.cpp:1626
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
Definition: optparser.cpp:151
char vishost[]
void update_edges(char axis, int tier, int incr)
Definition: rubik.cpp:729
void move_to_e4(int i4, int o4, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2147
void solve_centers(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1250
const double * GetVertex(int i) const
Return pointer to vertex i&#39;s coordinates.
Definition: mesh.hpp:1125
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
Definition: mesh.hpp:1293
void anim_move(char axis, int tier, int increment, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1159
void solve_top(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4868
void solve_corner_orientations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3942
void init_hex_mesh(Mesh &mesh)
Definition: rubik.cpp:406
void solve_bot_corner_locations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3534
void solve_corner_locations(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3460
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:1786
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:219
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
int AddHex(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int attr=1)
Definition: mesh.cpp:1757
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:4355
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
Definition: mesh.cpp:2945
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:2366
void swap_corners(Mesh &mesh, GridFunction &color, socketstream &sock, int *c0=NULL, int *c1=NULL)
Definition: rubik.cpp:3287
void rotate_step(char axis, int incr, double *x)
Definition: rubik.cpp:1003
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:1086
void solve_top_edges(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3097
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
void interactive_help()
Definition: rubik.cpp:360
void solve_bot(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:4913
void solve_top_corners(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2059
void determine_random_moves(Array< Move > &moves)
Definition: rubik.cpp:1171
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Definition: gridfunc.cpp:2415
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:3634
int Size() const
Return the logical size of the array.
Definition: array.hpp:141
void SetAttribute(int i, int attr)
Set the attribute of element i.
Definition: mesh.hpp:1193
void move_to_c5(int i5, int o5, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1614
Vector data type.
Definition: vector.hpp:58
virtual void Print(std::ostream &os=mfem::out) const
Definition: mesh.hpp:2011
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)
void move_to_e9(int i9, int o9, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2711
void solve_top_center(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:1215
void solve_mid_edges(Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:3182
int locate_edge(int ind)
Definition: rubik.cpp:2128
void move_to_e11(int i11, int o11, Mesh &mesh, GridFunction &color, socketstream &sock)
Definition: rubik.cpp:2984
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:6600
void update_state(char axis, int tier, int incr)
Definition: rubik.cpp:856
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition: fe_coll.hpp:327