1 /*
2 * cubex.cpp
3 * Cubex .505 by Eric Dietz (c) 2003 (26 Dec 03, 21 Jan 05) % 0
4 * Cube Puzzle and Universal Solver.
5 * Notes: readme.txt Email: root@wrongway.org
6 * NOTE: This program is unaffiliated with the Rubik's Cube Trademark.
7 * This program MAY NOT be reproduced or modified outside the licensing terms
8 * set forth in the readme.
9 */
10
11 #include <cstdio>
12 #include <string>
13 using namespace std;
14 #include "cubex.h"
15
16 // definition of cube class
17 // Cubex constructor & destructor & count
Cubex()18 Cubex::Cubex()
19 {
20 shorten = true;
21 cenfix = 0;
22 erval = 0;
23 cubeinit = false;
24 solution = "";
25 ResetCube();
26 numcubes++;
27 }
~Cubex()28 Cubex::~Cubex()
29 {
30 numcubes--;
31 }
32 int Cubex::numcubes = 0;
33 // version & author of the solver
34 const char* Cubex::ver = ".505";
35 const char* Cubex::author = "Eric Dietz (root@wrongway.org)";
36 // test the (in)eqaulity of two cubes
operator ==(const Cubex & q)37 const bool Cubex::operator==(const Cubex &q)
38 {
39 if (!(q.cubeinit) || !(this->cubeinit)) return false;
40 bool n = true;
41 for (int i = 1; i <= N; i++) {
42 for (int j = 1; j <= N; j++) {
43 if
44 (q.Cub[i][N+1][j] != this->Cub[i][N+1][j] ||
45 q.Cub[i][j][0] != this->Cub[i][j][0] ||
46 q.Cub[0][i][j] != this->Cub[0][i][j] ||
47 q.Cub[i][j][N+1] != this->Cub[i][j][N+1] ||
48 q.Cub[N+1][i][j] != this->Cub[N+1][i][j] ||
49 q.Cub[i][0][j] != this->Cub[i][0][j] )
50 n = false;
51 }
52 }
53 if (q.cenfix && this->cenfix) {
54 for (int i = 2; i <= N-1; i++) {
55 for (int j = 2; j <= N-1; j++) {
56 if
57 (q.Cub[i][N][j] != this->Cub[i][N][j] ||
58 q.Cub[i][j][1] != this->Cub[i][j][1] ||
59 q.Cub[1][i][j] != this->Cub[1][i][j] ||
60 q.Cub[i][j][N] != this->Cub[i][j][N] ||
61 q.Cub[N][i][j] != this->Cub[N][i][j] ||
62 q.Cub[i][1][j] != this->Cub[i][1][j])
63 n = false;
64 }
65 }
66 }
67 return n;
68 }
operator !=(const Cubex & a)69 const bool Cubex::operator!=(const Cubex &a) { return !(operator==(a)); }
70 // point a pretty cube value to an ugly array value
face(int x,int y,int z)71 int *Cubex::face(int x, int y, int z)
72 {
73 if (x+2 < 0 || x+2 > N+1 || y+2 < 0 || y+2 > N+1 || z+2 < 0 || z+2 > N+1)
74 return NULL;
75 return &Cub[x+2][y+2][z+2];
76 }
77 // show cube on the screen (e.g., for debugging)
RenderScreen()78 const void Cubex::RenderScreen()
79 {
80 /*
81 for (int i = 1; i <= N; i++) {
82 for (int j = 1; j <= N; j++) printf(" ");
83 printf(" ");
84 for (int j = 1; j <= N; j++)
85 printf(" %i", Cub[j][N+1][N+1-i]);
86 printf("\n");
87 }
88 for (int i = 1; i <= N; i++) {
89 for (int j = 1; j <= N; j++)
90 printf(" %i", Cub[0][N+1-i][N+1-j]);
91 printf(" ");
92 for (int j = 1; j <= N; j++)
93 printf(" %i", Cub[j][N+1-i][0]);
94 printf(" ");
95 for (int j = 1; j <= N; j++)
96 printf(" %i", Cub[N+1][N+1-i][j]);
97 printf(" ");
98 for (int j = 1; j <= N; j++)
99 printf(" %i", Cub[N+1-j][N+1-i][N+1]);
100 printf("\n");
101 }
102 for (int i = 1; i <= N; i++) {
103 for (int j = 1; j <= N; j++) printf(" ");
104 printf(" ");
105 for (int j = 1; j <= N; j++)
106 printf(" %i", Cub[j][0][i]);
107 printf("\n");
108 }
109 */
110 printf(
111 "\
112 %i %i %i %i %i\n\
113 %i %i %i %i %i %i %i\n\
114 %i %i %i %i\n\
115 %i %i %i %i %i %i %i %i %i %i %i %i\n\
116 %i %i %i %i %i %i %i %i %i %i %i %i\n\
117 %i %i %i %i %i %i %i %i %i %i %i %i\n\
118 %i %i %i\n\
119 %i %i %i\n\
120 %i %i %i\n\
121 ",
122 Cub[-1+2][ 2+2][ 1+2], Cub[ 0+2][ 2+2][ 1+2], Cub[ 1+2][ 2+2][ 1+2],
123 Cub[ 0+2][ 1+2][ 0+2], cenfix,
124 Cub[-1+2][ 2+2][ 0+2], Cub[ 0+2][ 2+2][ 0+2], Cub[ 1+2][ 2+2][ 0+2],
125 Cub[-1+2][ 0+2][ 0+2], Cub[ 0+2][ 0+2][-1+2], Cub[ 1+2][ 0+2][ 0+2], Cub[ 0+2][ 0+2][ 1+2],
126 Cub[-1+2][ 2+2][-1+2], Cub[ 0+2][ 2+2][-1+2], Cub[ 1+2][ 2+2][-1+2],
127 Cub[ 0+2][-1+2][ 0+2],
128 Cub[-2+2][ 1+2][ 1+2], Cub[-2+2][ 1+2][ 0+2], Cub[-2+2][ 1+2][-1+2],
129 Cub[-1+2][ 1+2][-2+2], Cub[ 0+2][ 1+2][-2+2], Cub[ 1+2][ 1+2][-2+2],
130 Cub[ 2+2][ 1+2][-1+2], Cub[ 2+2][ 1+2][ 0+2], Cub[ 2+2][ 1+2][ 1+2],
131 Cub[ 1+2][ 1+2][ 2+2], Cub[ 0+2][ 1+2][ 2+2], Cub[-1+2][ 1+2][ 2+2],
132 Cub[-2+2][ 0+2][ 1+2], Cub[-2+2][ 0+2][ 0+2], Cub[-2+2][ 0+2][-1+2],
133 Cub[-1+2][ 0+2][-2+2], Cub[ 0+2][ 0+2][-2+2], Cub[ 1+2][ 0+2][-2+2],
134 Cub[ 2+2][ 0+2][-1+2], Cub[ 2+2][ 0+2][ 0+2], Cub[ 2+2][ 0+2][ 1+2],
135 Cub[ 1+2][ 0+2][ 2+2], Cub[ 0+2][ 0+2][ 2+2], Cub[-1+2][ 0+2][ 2+2],
136 Cub[-2+2][-1+2][ 1+2], Cub[-2+2][-1+2][ 0+2], Cub[-2+2][-1+2][-1+2],
137 Cub[-1+2][-1+2][-2+2], Cub[ 0+2][-1+2][-2+2], Cub[ 1+2][-1+2][-2+2],
138 Cub[ 2+2][-1+2][-1+2], Cub[ 2+2][-1+2][ 0+2], Cub[ 2+2][-1+2][ 1+2],
139 Cub[ 1+2][-1+2][ 2+2], Cub[ 0+2][-1+2][ 2+2], Cub[-1+2][-1+2][ 2+2],
140 Cub[-1+2][-2+2][-1+2], Cub[ 0+2][-2+2][-1+2], Cub[ 1+2][-2+2][-1+2],
141 Cub[-1+2][-2+2][ 0+2], Cub[ 0+2][-2+2][ 0+2], Cub[ 1+2][-2+2][ 0+2],
142 Cub[-1+2][-2+2][ 1+2], Cub[ 0+2][-2+2][ 1+2], Cub[ 1+2][-2+2][ 1+2]
143 );
144 }
145 // return true if cube is solved
IsSolved()146 const bool Cubex::IsSolved()
147 {
148 if (!cubeinit) return false;
149 int c[7], d; bool n = true;
150 c[1] = Cub[2][N+1][2]; c[2] = Cub[2][2][0];
151 c[3] = Cub[0][2][2]; c[4] = Cub[2][2][N+1];
152 c[5] = Cub[N+1][2][2]; c[6] = Cub[2][0][2];
153 for (int i = 1; i <= 6 && n == true; i++) {
154 d = 0;
155 for (int j = 1; j <= 6 && n == true; j++) {
156 if (c[i] == j) d++;
157 }
158 if (d != 1)
159 n = false;
160 }
161 for (int i = 1; i <= N && n == true; i++) {
162 for (int j = 1; j <= N && n == true; j++) {
163 if
164 (Cub[i][N+1][j] != c[1] ||
165 Cub[i][j][0] != c[2] ||
166 Cub[0][i][j] != c[3] ||
167 Cub[i][j][N+1] != c[4] ||
168 Cub[N+1][i][j] != c[5] ||
169 Cub[i][0][j] != c[6])
170 n = false;
171 }
172 }
173 if (cenfix) {
174 for (int i = 2; i <= N-1; i++) {
175 for (int j = 2; j <= N-1; j++) {
176 if
177 (Cub[i][N][j] != 0 ||
178 Cub[i][j][1] != 0 ||
179 Cub[1][i][j] != 0 ||
180 Cub[i][j][N] != 0 ||
181 Cub[N][i][j] != 0 ||
182 Cub[i][1][j] != 0)
183 n = false;
184 }
185 }
186 }
187 return n;
188 }
189 // create default (solved) cube model and put it in Cub[]
ResetCube()190 const void Cubex::ResetCube()
191 {
192 solution = "";
193 for (int i = 0; i <= MOV; i++) mov[i] = 0;
194 for (int i = 0; i <= N+1; i++) {
195 for (int j = 0; j <= N+1; j++) {
196 for (int k = 0; k <= N+1; k++) {
197 if (!(i-2 == 0 && j-2 == 0 && k-2 == 0))
198 Cub[i][j][k] = 0;
199 }
200 }
201 }
202 for (int i = 1; i <= N; i++) {
203 for (int j = 1; j <= N; j++) {
204 Cub[i][N+1][j] = 1;
205 Cub[i][j][0] = 2;
206 Cub[0][i][j] = 3;
207 Cub[i][j][N+1] = 4;
208 Cub[N+1][i][j] = 5;
209 Cub[i][0][j] = 6;
210 }
211 }
212 cubeinit = true;
213 erval = 0;
214 }
215 // this is the series of cube rotation functions
216 // copy cube model so we can change it and remember the original
Ctemp()217 const void Cubex::Ctemp()
218 {
219 for (int i = 0; i <= N+1; i++) {
220 for (int j = 0; j <= N+1; j++) {
221 for (int k = 0; k <= N+1; k++) {
222 Tmp[i][j][k] = Cub[i][j][k];
223 }
224 }
225 }
226 }
227 // rotate given slice left
XML(int a,bool n=true)228 const bool Cubex::XML(int a, bool n = true)
229 {
230 if (a < 1 || a > N) return false;
231 Ctemp();
232 for (int i = 1; i <= N; i++) {
233 if (a == 1)
234 for (int j = 1; j <= N; j++)
235 Cub[i][0][j] = Tmp[N+1-j][0][i];
236 else if (a == N)
237 for (int j = 1; j <= N; j++)
238 Cub[i][N+1][j] = Tmp[N+1-j][N+1][i];
239 Cub[i][a][0] = Tmp[N+1][a][i];
240 Cub[i][a][N+1] = Tmp[0][a][i];
241 Cub[0][a][i] = Tmp[N+1-i][a][0];
242 Cub[N+1][a][i] = Tmp[N+1-i][a][N+1];
243 }
244 if (a == 1) {
245 for (int i = 2; i <= N-1; i++) {
246 for (int j = 2; j <= N-1; j++) {
247 Cub[i][1][j] = Tmp[N+1-j][1][i];
248 if (n) {
249 Cub[i][1][j]--;
250 if (Cub[i][1][j] < 0) Cub[i][1][j] += 4;
251 }
252 }
253 }
254 }
255 else if (a == N) {
256 for (int i = 2; i <= N-1; i++) {
257 for (int j = 2; j <= N-1; j++) {
258 Cub[i][N][j] = Tmp[N+1-j][N][i];
259 if (n) {
260 Cub[i][N][j]++;
261 if (Cub[i][N][j] > 3) Cub[i][N][j] -= 4;
262 }
263 }
264 }
265 }
266 else {
267 for (int i = 2; i <= N-1; i++) {
268 Cub[i][a][1] = Tmp[N][a][i];
269 Cub[i][a][N] = Tmp[1][a][i];
270 Cub[1][a][i] = Tmp[N+1-i][a][1];
271 Cub[N][a][i] = Tmp[N+1-i][a][N];
272 }
273 }
274 return true;
275 }
276 // rotate given slice right
XMR(int a,bool n=true)277 const bool Cubex::XMR(int a, bool n = true)
278 {
279 if (a < 1 || a > N) return false;
280 Ctemp();
281 for (int i = 1; i <= N; i++) {
282 if (a == 1)
283 for (int j = 1; j <= N; j++)
284 Cub[i][0][j] = Tmp[j][0][N+1-i];
285 else if (a == N)
286 for (int j = 1; j <= N; j++)
287 Cub[i][N+1][j] = Tmp[j][N+1][N+1-i];
288 Cub[i][a][0] = Tmp[0][a][N+1-i];
289 Cub[i][a][N+1] = Tmp[N+1][a][N+1-i];
290 Cub[0][a][i] = Tmp[i][a][N+1];
291 Cub[N+1][a][i] = Tmp[i][a][0];
292 }
293 if (a == 1) {
294 for (int i = 2; i <= N-1; i++) {
295 for (int j = 2; j <= N-1; j++) {
296 Cub[i][1][j] = Tmp[j][1][N+1-i];
297 if (n) {
298 Cub[i][1][j]++;
299 if (Cub[i][1][j] > 3) Cub[i][1][j] -= 4;
300 }
301 }
302 }
303 }
304 else if (a == N) {
305 for (int i = 2; i <= N-1; i++) {
306 for (int j = 2; j <= N-1; j++) {
307 Cub[i][N][j] = Tmp[j][N][N+1-i];
308 if (n) {
309 Cub[i][N][j]--;
310 if (Cub[i][N][j] < 0) Cub[i][N][j] += 4;
311 }
312 }
313 }
314 }
315 else {
316 for (int i = 2; i <= N-1; i++) {
317 Cub[i][a][1] = Tmp[1][a][N+1-i];
318 Cub[i][a][N] = Tmp[N][a][N+1-i];
319 Cub[1][a][i] = Tmp[i][a][N];
320 Cub[N][a][i] = Tmp[i][a][1];
321 }
322 }
323 return true;
324 }
325 // rotate given slice up
XMU(int a,bool n=true)326 const bool Cubex::XMU(int a, bool n = true)
327 {
328 if (a < 1 || a > N) return false;
329 Ctemp();
330 for (int i = 1; i <= N; i++) {
331 if (a == 1)
332 for (int j = 1; j <= N; j++)
333 Cub[0][i][j] = Tmp[0][j][N+1-i];
334 if (a == N)
335 for (int j = 1; j <= N; j++)
336 Cub[N+1][i][j] = Tmp[N+1][j][N+1-i];
337 Cub[a][i][0] = Tmp[a][0][N+1-i];
338 Cub[a][i][N+1] = Tmp[a][N+1][N+1-i];
339 Cub[a][0][i] = Tmp[a][i][N+1];
340 Cub[a][N+1][i] = Tmp[a][i][0];
341 }
342 if (a == 1) {
343 for (int i = 2; i <= N-1; i++) {
344 for (int j = 2; j <= N-1; j++) {
345 Cub[1][i][j] = Tmp[1][j][N+1-i];
346 if (n) {
347 Cub[1][i][j]--;
348 if (Cub[1][i][j] < 0) Cub[1][i][j] += 4;
349 }
350 }
351 }
352 }
353 else if (a == N) {
354 for (int i = 2; i <= N-1; i++) {
355 for (int j = 2; j <= N-1; j++) {
356 Cub[N][i][j] = Tmp[N][j][N+1-i];
357 if (n) {
358 Cub[N][i][j]++;
359 if (Cub[N][i][j] > 3) Cub[N][i][j] -= 4;
360 }
361 }
362 }
363 }
364 else {
365 for (int i = 2; i <= N-1; i++) {
366 Cub[a][i][1] = Tmp[a][1][N+1-i];
367 Cub[a][i][N] = Tmp[a][N][N+1-i];
368 Cub[a][1][i] = Tmp[a][i][N];
369 Cub[a][N][i] = Tmp[a][i][1];
370 }
371 }
372 return true;
373 }
374 // rotate given slice down
XMD(int a,bool n=true)375 const bool Cubex::XMD(int a, bool n = true)
376 {
377 if (a < 1 || a > N) return false;
378 Ctemp();
379 for (int i = 1; i <= N; i++) {
380 if (a == 1)
381 for (int j = 1; j <= N; j++)
382 Cub[0][i][j] = Tmp[0][N+1-j][i];
383 if (a == N)
384 for (int j = 1; j <= N; j++)
385 Cub[N+1][i][j] = Tmp[N+1][N+1-j][i];
386 Cub[a][i][0] = Tmp[a][N+1][i];
387 Cub[a][i][N+1] = Tmp[a][0][i];
388 Cub[a][0][i] = Tmp[a][N+1-i][0];
389 Cub[a][N+1][i] = Tmp[a][N+1-i][N+1];
390 }
391 if (a == 1) {
392 for (int i = 2; i <= N-1; i++) {
393 for (int j = 2; j <= N-1; j++) {
394 Cub[1][i][j] = Tmp[1][N+1-j][i];
395 if (n) {
396 Cub[1][i][j]++;
397 if (Cub[1][i][j] > 3) Cub[1][i][j] -= 4;
398 }
399 }
400 }
401 }
402 else if (a == N) {
403 for (int i = 2; i <= N-1; i++) {
404 for (int j = 2; j <= N-1; j++) {
405 Cub[N][i][j] = Tmp[N][N+1-j][i];
406 if (n) {
407 Cub[N][i][j]--;
408 if (Cub[N][i][j] < 0) Cub[N][i][j] += 4;
409 }
410 }
411 }
412 }
413 else {
414 for (int i = 2; i <= N-1; i++) {
415 Cub[a][i][1] = Tmp[a][N][i];
416 Cub[a][i][N] = Tmp[a][1][i];
417 Cub[a][1][i] = Tmp[a][N+1-i][1];
418 Cub[a][N][i] = Tmp[a][N+1-i][N];
419 }
420 }
421 return true;
422 }
423 // rotate given slice clockwise
XMC(int a,bool n=true)424 const bool Cubex::XMC(int a, bool n = true)
425 {
426 if (a < 1 || a > N) return false;
427 Ctemp();
428 for (int i = 1; i <= N; i++) {
429 if (a == 1)
430 for (int j = 1; j <= N; j++)
431 Cub[i][j][0] = Tmp[N+1-j][i][0];
432 if (a == N)
433 for (int j = 1; j <= N; j++)
434 Cub[i][j][N+1] = Tmp[N+1-j][i][N+1];
435 Cub[i][0][a] = Tmp[N+1][i][a];
436 Cub[i][N+1][a] = Tmp[0][i][a];
437 Cub[0][i][a] = Tmp[N+1-i][0][a];
438 Cub[N+1][i][a] = Tmp[N+1-i][N+1][a];
439 }
440 if (a == 1) {
441 for (int i = 2; i <= N-1; i++) {
442 for (int j = 2; j <= N-1; j++) {
443 Cub[i][j][1] = Tmp[N+1-j][i][1];
444 if (n) {
445 Cub[i][j][1]++;
446 if (Cub[i][j][1] > 3) Cub[i][j][1] -= 4;
447 }
448 }
449 }
450 }
451 else if (a == N) {
452 for (int i = 2; i <= N-1; i++) {
453 for (int j = 2; j <= N-1; j++) {
454 Cub[i][j][N] = Tmp[N+1-j][i][N];
455 if (n) {
456 Cub[i][j][N]--;
457 if (Cub[i][j][N] < 0) Cub[i][j][N] += 4;
458 }
459 }
460 }
461 }
462 else {
463 for (int i = 2; i <= N-1; i++) {
464 Cub[i][1][a] = Tmp[N][i][a];
465 Cub[i][N][a] = Tmp[1][i][a];
466 Cub[1][i][a] = Tmp[N+1-i][1][a];
467 Cub[N][i][a] = Tmp[N+1-i][N][a];
468 }
469 }
470 return true;
471 }
472 // rotate given slice anticlockwise (looking from the front)
XMA(int a,bool n=true)473 const bool Cubex::XMA(int a, bool n = true)
474 {
475 if (a < 1 || a > N) return false;
476 Ctemp();
477 for (int i = 1; i <= N; i++) {
478 if (a == 1)
479 for (int j = 1; j <= N; j++)
480 Cub[i][j][0] = Tmp[j][N+1-i][0];
481 if (a == N)
482 for (int j = 1; j <= N; j++)
483 Cub[i][j][N+1] = Tmp[j][N+1-i][N+1];
484 Cub[i][0][a] = Tmp[0][N+1-i][a];
485 Cub[i][N+1][a] = Tmp[N+1][N+1-i][a];
486 Cub[0][i][a] = Tmp[i][N+1][a];
487 Cub[N+1][i][a] = Tmp[i][0][a];
488 }
489 if (a == 1) {
490 for (int i = 2; i <= N-1; i++) {
491 for (int j = 2; j <= N-1; j++) {
492 Cub[i][j][1] = Tmp[j][N+1-i][1];
493 if (n) {
494 Cub[i][j][1]--;
495 if (Cub[i][j][1] < 0) Cub[i][j][1] += 4;
496 }
497 }
498 }
499 }
500 else if (a == N) {
501 for (int i = 2; i <= N-1; i++) {
502 for (int j = 2; j <= N-1; j++) {
503 Cub[i][j][N] = Tmp[j][N+1-i][N];
504 if (n) {
505 Cub[i][j][N]++;
506 if (Cub[i][j][N] > 3) Cub[i][j][N] -= 4;
507 }
508 }
509 }
510 }
511 else {
512 for (int i = 2; i <= N-1; i++) {
513 Cub[i][1][a] = Tmp[1][N+1-i][a];
514 Cub[i][N][a] = Tmp[N][N+1-i][a];
515 Cub[1][i][a] = Tmp[i][N][a];
516 Cub[N][i][a] = Tmp[i][1][a];
517 }
518 }
519 return true;
520 }
521 // the remaining rotation functions are aliases to the above rotators (with nicer names)
UL()522 const void Cubex::UL() { XML(N); } // rotate top left
UR()523 const void Cubex::UR() { XMR(N); } // rotate top right
DL()524 const void Cubex::DL() { XML(1); } // rotate bottom left
DR()525 const void Cubex::DR() { XMR(1); } // rotate bottom right
LU()526 const void Cubex::LU() { XMU(1); } // rotate left up
LD()527 const void Cubex::LD() { XMD(1); } // rotate left down
RU()528 const void Cubex::RU() { XMU(N); } // rotate right up
RD()529 const void Cubex::RD() { XMD(N); } // rotate right down
FC()530 const void Cubex::FC() { XMC(1); } // rotate front clockwise
FA()531 const void Cubex::FA() { XMA(1); } // rotate front anticlockwise
BC()532 const void Cubex::BC() { XMC(N); } // rotate back clockwise (looking from front)
BA()533 const void Cubex::BA() { XMA(N); } // rotate back anticlockwise (looking from front)
ML()534 const void Cubex::ML() { XML(2); } // rotate middle left
MR()535 const void Cubex::MR() { XMR(2); } // rotate middle right
MU()536 const void Cubex::MU() { XMU(2); } // rotate middle up
MD()537 const void Cubex::MD() { XMD(2); } // rotate middle down
MC()538 const void Cubex::MC() { XMC(2); } // rotate middle clockwise
MA()539 const void Cubex::MA() { XMA(2); } // rotate middle anticlockwise
CL()540 const void Cubex::CL() { for (int i = 1; i <= N; i++) XML(i); } // rotate whole cube left
CR()541 const void Cubex::CR() { for (int i = 1; i <= N; i++) XMR(i); } // rotate whole cube right
CU()542 const void Cubex::CU() { for (int i = 1; i <= N; i++) XMU(i); } // rotate whole cube up
CD()543 const void Cubex::CD() { for (int i = 1; i <= N; i++) XMD(i); } // rotate whole cube down
CC()544 const void Cubex::CC() { for (int i = 1; i <= N; i++) XMC(i); } // rotate whole cube clockwise
CA()545 const void Cubex::CA() { for (int i = 1; i <= N; i++) XMA(i); } // rotate whole cube anticlockwise
XCL()546 const void Cubex::XCL() { for (int i = 1; i <= N; i++) XML(i, false); } // rotate whole cube left w/o altering centers
XCR()547 const void Cubex::XCR() { for (int i = 1; i <= N; i++) XMR(i, false); } // rotate whole cube right w/o altering centers
XCU()548 const void Cubex::XCU() { for (int i = 1; i <= N; i++) XMU(i, false); } // rotate whole cube up w/o altering centers
XCD()549 const void Cubex::XCD() { for (int i = 1; i <= N; i++) XMD(i, false); } // rotate whole cube down w/o altering centers
XCC()550 const void Cubex::XCC() { for (int i = 1; i <= N; i++) XMC(i, false); } // rotate whole cube clockwise w/o altering centers
XCA()551 const void Cubex::XCA() { for (int i = 1; i <= N; i++) XMA(i, false); } // rotate whole cube anticlockwise w/o altering centers
552 // scramble up the cube model
ScrambleCube()553 const void Cubex::ScrambleCube()
554 {
555 // come up with a better calculation for a good number of random moves based on cube size later
556 int a = (N-2)*25+10;
557 int n, o; string s = "";
558 a += rand() % a;
559 ResetCube();
560 for (int i = 1; i <= a; i++) {
561 n = rand() % 6 + 1; // which dimension & direction
562 o = rand() % N + 1; // which layer
563 switch (n) {
564 case 1: XML(o); break;
565 case 2: XMR(o); break;
566 case 3: XMU(o); break;
567 case 4: XMD(o); break;
568 case 5: XMC(o); break;
569 case 6: XMA(o); break;
570 }
571 }
572 cubeinit = true;
573 }
574 // execute solution
DoSolution()575 const void Cubex::DoSolution()
576 {
577 if (!cubeinit) return;
578 string a = "";
579 for (int i = 1; i <= mov[0]; i++) {
580 a = solution.substr(i * 3 - 3, 3);
581 if (a == "UL.") UL();
582 else if (a == "UR.") UR();
583 else if (a == "DL.") DL();
584 else if (a == "DR.") DR();
585 else if (a == "LU.") LU();
586 else if (a == "LD.") LD();
587 else if (a == "RU.") RU();
588 else if (a == "RD.") RD();
589 else if (a == "FC.") FC();
590 else if (a == "FA.") FA();
591 else if (a == "BC.") BC();
592 else if (a == "BA.") BA();
593 else if (a == "ML.") ML();
594 else if (a == "MR.") MR();
595 else if (a == "MU.") MU();
596 else if (a == "MD.") MD();
597 else if (a == "MC.") MC();
598 else if (a == "MA.") MA();
599 else if (a == "CL.") CL();
600 else if (a == "CR.") CR();
601 else if (a == "CU.") CU();
602 else if (a == "CD.") CD();
603 else if (a == "CC.") CC();
604 else if (a == "CA.") CA();
605 }
606 }
607 // return adjacent axis on which given center is found
FindCent(int a)608 const int Cubex::FindCent(int a)
609 {
610 int f = 0, x, y, z; fx = 0; fy = 0; fz = 0;
611 for (int i = -1; i <= 1; i = i + 2) {
612 x = Cub[i*2+2][0+2][0+2];
613 y = Cub[0+2][i*2+2][0+2];
614 z = Cub[0+2][0+2][i*2+2];
615 if (x == a) {
616 f = i * 1; fx = i * 2; return f;
617 }
618 else if (y == a) {
619 f = i * 2; fy = i * 2; return f;
620 }
621 else if (z == a) {
622 f = i * 3; fz = i * 2; return f;
623 }
624 }
625 return f;
626 }
627 // return adjacent axis on which given edge is found
FindEdge(int a,int b)628 const int Cubex::FindEdge(int a, int b)
629 {
630 int f = 0, x, y, z; fx = 0; fy = 0; fz = 0;
631 for (int i = -1; i <= 1; i = i + 2) {
632 for (int j = -1; j <= 1; j = j + 2) {
633 x = Cub[i*2+2][j+2][0+2];
634 y = Cub[i+2][j*2+2][0+2];
635 if (x == a && y == b) {
636 f = i * 1; fx = i * 2; fy = j; return f;
637 }
638 else if (y == a && x == b) {
639 f = j * 2; fx = i; fy = j * 2; return f;
640 }
641 x = Cub[i*2+2][0+2][j+2];
642 z = Cub[i+2][0+2][j*2+2];
643 if (x == a && z == b) {
644 f = i * 1; fx = i * 2; fz = j; return f;
645 }
646 else if (z == a && x == b) {
647 f = j * 3; fx = i; fz = j * 2; return f;
648 }
649 y = Cub[0+2][i*2+2][j+2];
650 z = Cub[0+2][i+2][j*2+2];
651 if (y == a && z == b) {
652 f = i * 2; fy = i * 2; fz = j; return f;
653 }
654 else if (z == a && y == b) {
655 f = j * 3; fy = i; fz = j * 2; return f;
656 }
657 }
658 }
659 return f;
660 }
661 // return adjacent axis on which given corner is found
FindCorn(int a,int b,int c)662 const int Cubex::FindCorn(int a, int b, int c)
663 {
664 int f = 0, x, y, z; fx = 0; fy = 0; fz = 0;
665 for (int i = -1; i <= 1; i = i + 2) {
666 for (int j = -1; j <= 1; j = j + 2) {
667 for (int k = -1; k <= 1; k = k + 2) {
668 x = Cub[i*2+2][j+2][k+2];
669 y = Cub[i+2][j*2+2][k+2];
670 z = Cub[i+2][j+2][k*2+2];
671 if (x == a && (y == b || y == c) && (z == b || z == c)) {
672 f = i * 1; fx = i * 2; fy = j; fz = k; return f;
673 }
674 else if (y == a && (x == b || x == c) && (z == b || z == c)) {
675 f = j * 2; fx = i; fy = j * 2; fz = k; return f;
676 }
677 else if (z == a && (x == b || x == c) && (y == b || y == c)) {
678 f = k * 3; fx = i; fy = j; fz = k * 2; return f;
679 }
680 }
681 }
682 }
683 return f;
684 }
685 // routine for condensing redundant redundancies (a joke)
686 // this is undoubtedly the most complex routine in this class
Concise(string a)687 const string Cubex::Concise(string a)
688 {
689 // initialize stuff
690 string s = a; string t = "";
691 string s1 = ""; string s2 = ""; string s3 = "";
692 string t1 = ""; string t2 = ""; string t3 = "";
693 string zz = ""; string yy = ""; string xx = "";
694 string ww = ""; string vv = ""; string uu = "";
695 string mm = ""; string ll = ""; string kk = "";
696 string jj = ""; string ii = ""; string hh = "";
697 int b, c, g, h[2], mvs[MOV+1];
698 if (mov[0] == -1) {
699 mvs[0] = 0;
700 for (int i = 1; i <= MOV; i++) {
701 mvs[i] = 0;
702 for (int j = 1; j <= i; j++) mvs[i] += mov[j];
703 }
704 }
705 // part 1: remove middle, and whole cube moves by interpolating them
706 // part 1a - getting rid of middle slice moves
707 for (int i = 1; i <= s.length() / 3; i++) {
708 s1 = s.substr(i * 3 - 3, 1);
709 s2 = s.substr(i * 3 - 2, 1);
710 if (s1 == "M") {
711 if (s2 == "U") { t += "CU.LD.RD."; }
712 else if (s2 == "D") { t += "CD.LU.RU."; }
713 else if (s2 == "L") { t += "CL.UR.DR."; }
714 else if (s2 == "R") { t += "CR.UL.DL."; }
715 else if (s2 == "C") { t += "CC.FA.BA."; }
716 else if (s2 == "A") { t += "CA.FC.BC."; }
717 }
718 else {
719 t += s1; t += s2; t += ".";
720 }
721 }
722 s = t;
723 // part 1b - interpolating whole cube moves
724 c = 1;
725 while (c <= s.length() / 3) {
726 s1 = s.substr(c * 3 - 3, 1);
727 s2 = s.substr(c * 3 - 2, 1);
728 if (s1 == "C") {
729 zz = "U"; yy = "D"; xx = "L"; ww = "R"; vv = "F"; uu = "B";
730 mm = "L"; ll = "R"; kk = "U"; jj = "D"; ii = "C"; hh = "A";
731 if (s2 == "U") {
732 zz = "F"; yy = "B"; vv = "D"; uu = "U";
733 mm = "C"; ll = "A"; ii = "R"; hh = "L";
734 }
735 else if (s2 == "D") {
736 zz = "B"; yy = "F"; vv = "U"; uu = "D";
737 mm = "A"; ll = "C"; ii = "L"; hh = "R";
738 }
739 else if (s2 == "L") {
740 xx = "F"; ww = "B"; vv = "R"; uu = "L";
741 kk = "A"; jj = "C"; ii = "U"; hh = "D";
742 }
743 else if (s2 == "R") {
744 xx = "B"; ww = "F"; vv = "L"; uu = "R";
745 kk = "C"; jj = "A"; ii = "D"; hh = "U";
746 }
747 else if (s2 == "C") {
748 xx = "D"; ww = "U"; zz = "L"; yy = "R";
749 kk = "L"; jj = "R"; mm = "D"; ll = "U";
750 }
751 else if (s2 == "A") {
752 xx = "U"; ww = "D"; zz = "R"; yy = "L";
753 kk = "R"; jj = "L"; mm = "U"; ll = "D";
754 }
755 t = "";
756 for (int i = c + 1; i <= s.length() / 3; i++) {
757 t1 = s.substr(i * 3 - 3, 1);
758 t2 = s.substr(i * 3 - 2, 1);
759 if (t1 == "U") { t += zz; }
760 else if (t1 == "D") { t += yy; }
761 else if (t1 == "L") { t += xx; }
762 else if (t1 == "R") { t += ww; }
763 else if (t1 == "F") { t += vv; }
764 else if (t1 == "B") { t += uu; }
765 else if (t1 == "C") { t += "C"; }
766 if (t2 == "L") { t += mm; }
767 else if (t2 == "R") { t += ll; }
768 else if (t2 == "U") { t += kk; }
769 else if (t2 == "D") { t += jj; }
770 else if (t2 == "C") { t += ii; }
771 else if (t2 == "A") { t += hh; }
772 t += ".";
773 }
774 c--;
775 s = s.substr(0, c * 3); s += t;
776 }
777 c++;
778 }
779 // parts 2-4 are nested in this while, so that it will keep stripping out
780 // moves until it goes through an entire cycle without stripping anything.
781 g = 1;
782 while (g > 0) {
783 g = 0;
784 // part 2: unshuffle possible opposite face groups, e.g., "UL.DR.UR.DL." to "UL.UR.DR.DL."
785 // this will make it much easier to identify redundancies like "top left, top right" later on
786 b = 0;
787 while (b <= s.length() / 3 - 1 && s.length() / 3 > 0) {
788 s1 = s.substr(b * 3, 2);
789 t1 = s1.substr(0, 1);
790 if (t1 == "U") { t3 = "D"; }
791 else if (t1 == "D") { t3 = "U"; }
792 else if (t1 == "L") { t3 = "R"; }
793 else if (t1 == "R") { t3 = "L"; }
794 else if (t1 == "F") { t3 = "B"; }
795 else if (t1 == "B") { t3 = "F"; }
796 c = 0;
797 s2 = s.substr(b * 3 + 3, 2);
798 t2 = s2.substr(0, 1);
799 while ((t2 == t1 || t2 == t3) && c <= s.length() / 3 - b - 2 && s != "") {
800 if (t2 == t1 && c > 0) {
801 t = s.substr(0, b * 3 + 3);
802 t += s.substr(b * 3 + c * 3 + 3, 3);
803 t += s.substr(b * 3 + 3, c * 3);
804 t += s.substr(b * 3 + c * 3 + 6, s.length() - (b * 3 + c * 3 + 6));
805 s = t;
806 c = s.length() / 3;
807 }
808 else if (t2 == t3) {
809 c++;
810 }
811 else {
812 c = s.length() / 3;
813 }
814 if (c < s.length() / 3) {
815 s2 = s.substr(b * 3 + c * 3 + 3, 2);
816 t2 = s2.substr(0, 1);
817 }
818 }
819 b++;
820 }
821 // part 3: change things like "top left, top left, top left" to simply "top right"
822 b = 0;
823 while (b <= s.length() / 3 - 2 && s.length() / 3 >= 3) {
824 s1 = s.substr(b * 3, 2);
825 s2 = s.substr(b * 3 + 3, 2);
826 s3 = s.substr(b * 3 + 6, 2);
827 t1 = s1.substr(0, 1);
828 t2 = s1.substr(1, 1);
829 if (s1 == s2 && s2 == s3) {
830 if (t2 == "L") { t3 = "R"; }
831 else if (t2 == "R") { t3 = "L"; }
832 else if (t2 == "U") { t3 = "D"; }
833 else if (t2 == "D") { t3 = "U"; }
834 else if (t2 == "C") { t3 = "A"; }
835 else if (t2 == "A") { t3 = "C"; }
836 g = 1;
837 t = s.substr(0, b * 3);
838 t += t1 + t3 + ".";
839 t += s.substr(b * 3 + 9, s.length() - (b * 3 + 9));
840 // change the mov[] array if necessary
841 if (mov[0] == -1) {
842 h[0] = 0; h[1] = 0;
843 for (int i = 1; i <= MOV; i++) {
844 for (int k = 0; k <= 1; k++) {
845 if ((b+k+2) <= mvs[i] && (b+k+2) > mvs[i-1] && h[k] == 0) {
846 mov[i]--; h[k] = 1;
847 for (int j = i; j <= MOV; j++) mvs[j]--;
848 }
849 }
850 }
851 }
852 //
853 s = t;
854 b = b - 3; if (b < -1) b = -1;
855 }
856 b++;
857 }
858 // part 4: remove explicit redundancies like "top left, top right"
859 b = 0;
860 while (b <= s.length() / 3 - 2 && s.length() / 3 >= 2) {
861 t1 = s.substr(b * 3, 1);
862 t2 = s.substr(b * 3 + 3, 1);
863 s1 = s.substr(b * 3 + 1, 1);
864 s2 = s.substr(b * 3 + 4, 1);
865 if ((t1 == t2) &&
866 ((s1 == "L" && s2 == "R") ||
867 (s1 == "R" && s2 == "L") ||
868 (s1 == "U" && s2 == "D") ||
869 (s1 == "D" && s2 == "U") ||
870 (s1 == "C" && s2 == "A") ||
871 (s1 == "A" && s2 == "C"))) {
872 g = 1;
873 t = s.substr(0, b * 3);
874 t += s.substr(b * 3 + 6, s.length() - (b * 3 + 6));
875 // change the mov[] array if necessary
876 if (mov[0] == -1) {
877 h[0] = 0; h[1] = 0;
878 for (int i = 1; i <= MOV; i++) {
879 for (int k = 0; k <= 1; k++) {
880 if ((b+k+1) <= mvs[i] && (b+k+1) > mvs[i-1] && h[k] == 0) {
881 mov[i]--; h[k] = 1;
882 for (int j = i; j <= MOV; j++) mvs[j]--;
883 }
884 }
885 }
886 }
887 //
888 s = t;
889 b = b - 2; if (b < -1) b = -1;
890 }
891 b++;
892 }
893 // ok now it will run again if necessary, and then return the new concise string.
894 }
895 return s;
896 }
897 // complicated string analysis to shorten solution...
Efficient(string a)898 const string Cubex::Efficient(string a)
899 {
900 string s = a;
901 // to be continued some day..........
902 return s;
903 }
904 // Top Edges (step 1)
TopEdges()905 const string Cubex::TopEdges()
906 {
907 string s = "";
908 if (!cubeinit) return s;
909 string a = ""; int b = 0, e, f, f1, m = 0;
910 while (!(FindEdge(1, 2) == 2 && FindEdge(2, 1) == -3 &&
911 FindEdge(1, 3) == 2 && FindEdge(3, 1) == -1 &&
912 FindEdge(1, 4) == 2 && FindEdge(4, 1) == 3 &&
913 FindEdge(1, 5) == 2 && FindEdge(5, 1) == 1)) {
914 for (int i = 2; i <= b; i++) CR();
915 if (b > 0) { s += "CR."; CR(); }
916 b++; if (b > 4) b = 1;
917 switch (b) {
918 case 1: e = 2; break;
919 case 2: e = 3; break;
920 case 3: e = 4; break;
921 case 4: e = 5; break;
922 }
923 f = FindEdge(1, e); f1 = FindEdge(e, 1);
924 switch (f) {
925 case 2:
926 switch (f1) {
927 case 3:
928 s += "BC.BC.DL.DL.FC.FC.";
929 BC(); BC(); DL(); DL(); FC(); FC(); break;
930 case -1:
931 s += "LD.LD.DR.FC.FC.";
932 LD(); LD(); DR(); FC(); FC(); break;
933 case 1:
934 s += "RD.RD.DL.FC.FC.";
935 RD(); RD(); DL(); FC(); FC(); break;
936 }
937 break;
938 case -2:
939 switch (f1) {
940 case 3:
941 s += "DL.DL.";
942 DL(); DL(); break;
943 case -1:
944 s += "DR.";
945 DR(); break;
946 case 1:
947 s += "DL.";
948 DL(); break;
949 }
950 s += "FC.FC.";
951 FC(); FC();
952 break;
953 case 1:
954 switch (f1) {
955 case -3:
956 s += "FA.";
957 FA(); break;
958 case 3:
959 s += "RU.RU.FA.RD.RD.";
960 RU(); RU(); FA(); RD(); RD(); break;
961 case -2:
962 s += "RU.FA.RD.";
963 RU(); FA(); RD(); break;
964 case 2:
965 s += "RD.FA.";
966 RD(); FA(); break;
967 }
968 break;
969 case -1:
970 switch (f1) {
971 case -3:
972 s += "FC.";
973 FC(); break;
974 case 3:
975 s += "LU.LU.FC.LD.LD.";
976 LU(); LU(); FC(); LD(); LD(); break;
977 case -2:
978 s += "LU.FC.LD.";
979 LU(); FC(); LD(); break;
980 case 2:
981 s += "LD.FC.";
982 LD(); FC(); break;
983 }
984 break;
985 case 3:
986 switch (f1) {
987 case -2:
988 s += "DL.RU.FA.RD.";
989 DL(); RU(); FA(); RD(); break;
990 case 2:
991 s += "BC.BC.DL.RU.FA.RD.";
992 BC(); BC(); DL(); RU(); FA(); RD(); break;
993 case -1:
994 s += "LU.DR.FC.FC.LD.";
995 LU(); DR(); FC(); FC(); LD(); break;
996 case 1:
997 s += "RU.DL.FC.FC.RD.";
998 RU(); DL(); FC(); FC(); RD(); break;
999 }
1000 break;
1001 case -3:
1002 switch (f1) {
1003 case -2:
1004 s += "DR.RU.FA.RD.";
1005 DR(); RU(); FA(); RD(); break;
1006 case 2:
1007 s += "FC.RD.DL.FC.FC.RU.";
1008 FC(); RD(); DL(); FC(); FC(); RU(); break;
1009 case -1:
1010 s += "LD.DR.FC.FC.LU.";
1011 LD(); DR(); FC(); FC(); LU(); break;
1012 case 1:
1013 s += "RD.DL.FC.FC.RU.";
1014 RD(); DL(); FC(); FC(); RU(); break;
1015 }
1016 break;
1017 }
1018 switch (b) {
1019 case 1: a = ""; break;
1020 case 2: a = "CL."; CL(); break;
1021 case 3: a = "CL.CL."; CL(); CL(); break;
1022 case 4: a = "CR."; CR(); break;
1023 }
1024 m++; if (m > 255) { cubeinit = false; s = ""; return s; }
1025 }
1026 s += a;
1027 if (shorten) s = Concise(s);
1028 mov[1] = s.length() / 3;
1029 return s;
1030 }
1031 // Top Corners (step 2)
TopCorners()1032 const string Cubex::TopCorners()
1033 {
1034 string s = "";
1035 if (!cubeinit) return s;
1036 string a = ""; int b = 0, c, c1, f, f1, f2, m = 0;
1037 while (!(FindCorn(1, 2, 5) == 2 && FindCorn(2, 1, 5) == -3 &&
1038 FindCorn(1, 3, 2) == 2 && FindCorn(3, 1, 2) == -1 &&
1039 FindCorn(1, 4, 3) == 2 && FindCorn(4, 1, 3) == 3 &&
1040 FindCorn(1, 5, 4) == 2 && FindCorn(5, 1, 4) == 1)) {
1041 for (int i = 2; i <= b; i++) CR();
1042 if (b > 0) { s += "CR."; CR(); }
1043 b++; if (b > 4) b = 1;
1044 switch (b) {
1045 case 1: c = 2; c1 = 5; break;
1046 case 2: c = 3; c1 = 2; break;
1047 case 3: c = 4; c1 = 3; break;
1048 case 4: c = 5; c1 = 4; break;
1049 }
1050 f = FindCorn(1, c, c1); f1 = FindCorn(c, 1, c1); f2 = FindCorn(c1, 1, c);
1051 switch (f) {
1052 case 2:
1053 switch (f1) {
1054 case 3:
1055 s += "BA.DL.BC.DR.RD.DR.RU.";
1056 BA(); DL(); BC(); DR(); RD(); DR(); RU(); break;
1057 case -1:
1058 s += "LD.DR.LU.RD.DL.RU.";
1059 LD(); DR(); LU(); RD(); DL(); RU(); break;
1060 case 1:
1061 s += "BC.DL.BA.FC.DR.FA.";
1062 BC(); DL(); BA(); FC(); DR(); FA(); break;
1063 }
1064 break;
1065 case -2:
1066 switch (f1) {
1067 case -3:
1068 s += "DR.";
1069 DR(); break;
1070 case 3:
1071 s += "DL.";
1072 DL(); break;
1073 case -1:
1074 s += "DL.DL.";
1075 DL(); DL(); break;
1076 }
1077 s += "FC.DL.FA.DR.RD.DR.RU.";
1078 FC(); DL(); FA(); DR(); RD(); DR(); RU();
1079 break;
1080 case 1:
1081 switch (f1) {
1082 case -3:
1083 s += "RD.DL.RU.";
1084 RD(); DL(); RU(); break;
1085 case 3:
1086 s += "RU.DR.RD.DR.RD.DR.RU.";
1087 RU(); DR(); RD(); DR(); RD(); DR(); RU(); break;
1088 case -2:
1089 s += "DL.FC.DR.FA.";
1090 DL(); FC(); DR(); FA(); break;
1091 case 2:
1092 s += "RD.DL.RU.DR.RD.DL.RU.";
1093 RD(); DL(); RU(); DR(); RD(); DL(); RU(); break;
1094 }
1095 break;
1096 case -1:
1097 switch (f1) {
1098 case -3:
1099 s += "LD.DR.LU.FC.DR.FA.";
1100 LD(); DR(); LU(); FC(); DR(); FA(); break;
1101 case 3:
1102 s += "DL.FC.DL.FA.";
1103 DL(); FC(); DL(); FA(); break;
1104 case -2:
1105 s += "RD.DR.RU.";
1106 RD(); DR(); RU(); break;
1107 case 2:
1108 s += "LU.DL.LD.FC.DL.FA.";
1109 LU(); DL(); LD(); FC(); DL(); FA(); break;
1110 }
1111 break;
1112 case 3:
1113 switch (f1) {
1114 case -2:
1115 s += "DR.RD.DR.RU.";
1116 DR(); RD(); DR(); RU(); break;
1117 case 2:
1118 s += "BC.FC.DL.BA.FA.";
1119 BC(); FC(); DL(); BA(); FA(); break;
1120 case -1:
1121 s += "BA.DR.BC.RD.DR.RU.";
1122 BA(); DR(); BC(); RD(); DR(); RU(); break;
1123 case 1:
1124 s += "FC.DL.FA.";
1125 FC(); DL(); FA(); break;
1126 }
1127 break;
1128 case -3:
1129 switch (f1) {
1130 case -2:
1131 s += "FC.DR.FA.";
1132 FC(); DR(); FA(); break;
1133 case 2:
1134 s += "FA.DL.FC.DL.FC.DL.FA.";
1135 FA(); DL(); FC(); DL(); FC(); DL(); FA(); break;
1136 case -1:
1137 s += "DR.RD.DL.RU.";
1138 DR(); RD(); DL(); RU(); break;
1139 case 1:
1140 s += "FC.DR.FA.DL.FC.DR.FA.";
1141 FC(); DR(); FA(); DL(); FC(); DR(); FA(); break;
1142 }
1143 break;
1144 }
1145 switch (b) {
1146 case 1: a = ""; break;
1147 case 2: a = "CL."; CL(); break;
1148 case 3: a = "CL.CL."; CL(); CL(); break;
1149 case 4: a = "CR."; CR(); break;
1150 }
1151 m++; if (m > 255) { cubeinit = false; s = ""; return s; }
1152 }
1153 s += a;
1154 if (shorten) s = Concise(s);
1155 mov[2] = s.length() / 3;
1156 return s;
1157 }
1158 // Middle Edges (step 3)
MiddleEdges()1159 const string Cubex::MiddleEdges()
1160 {
1161 string s = "";
1162 if (!cubeinit) return s;
1163 string a = ""; int b = 0, e, e1, f, f1, m = 0;
1164 while (!(FindEdge(2, 5) == -3 && FindEdge(5, 2) == 1 &&
1165 FindEdge(3, 2) == -1 && FindEdge(2, 3) == -3 &&
1166 FindEdge(4, 3) == 3 && FindEdge(3, 4) == -1 &&
1167 FindEdge(5, 4) == 1 && FindEdge(4, 5) == 3)) {
1168 for (int i = 2; i <= b; i++) CR();
1169 if (b > 0) { s += "CR."; CR(); }
1170 b++; if (b > 4) b = 1;
1171 switch (b) {
1172 case 1: e = 2; e1 = 5; break;
1173 case 2: e = 3; e1 = 2; break;
1174 case 3: e = 4; e1 = 3; break;
1175 case 4: e = 5; e1 = 4; break;
1176 }
1177 a = "";
1178 f = FindEdge(e, e1); f1 = FindEdge(e1, e);
1179 while (!(f == -2 || f1 == -2)) {
1180 if (f == -1 && f1 == -3) { a = "CR."; CR(); }
1181 if (f == -1 && f1 == 3) { a = "CL.CL."; CL(); CL(); }
1182 if (f == 1 && f1 == 3) { a = "CL."; CL(); }
1183 if (f == -3 && f1 == -1) { a = "CR."; CR(); }
1184 if (f == 3 && f1 == -1) { a = "CL.CL."; CL(); CL(); }
1185 if (f == 3 && f1 == 1) { a = "CL."; CL(); }
1186 s += a; s += "RD.DR.RU.DR.FC.DL.FA.";
1187 RD(); DR(); RU(); DR(); FC(); DL(); FA();
1188 if (a == "CL.") { s += "CR."; CR(); }
1189 if (a == "CL.CL.") { s += "CR.CR."; CR(); CR(); }
1190 if (a == "CR.") { s += "CL."; CL(); }
1191 a = "";
1192 f = FindEdge(e, e1); f1 = FindEdge(e1, e);
1193 }
1194 if (f == -2) {
1195 switch (f1) {
1196 case -3:
1197 s += "DL.DL."; DL(); DL(); break;
1198 case -1:
1199 s += "DL."; DL(); break;
1200 case 1:
1201 s += "DR."; DR(); break;
1202 }
1203 s += "FC.DL.FA.DL.RD.DR.RU.";
1204 FC(); DL(); FA(); DL(); RD(); DR(); RU();
1205 }
1206 else if (f1 == -2) {
1207 switch (f) {
1208 case -3:
1209 s += "DL."; DL(); break;
1210 case 3:
1211 s += "DR."; DR(); break;
1212 case 1:
1213 s += "DL.DL."; DL(); DL(); break;
1214 }
1215 s += "RD.DR.RU.DR.FC.DL.FA.";
1216 RD(); DR(); RU(); DR(); FC(); DL(); FA();
1217 }
1218 switch (b) {
1219 case 1: a = ""; break;
1220 case 2: a = "CL."; CL(); break;
1221 case 3: a = "CL.CL."; CL(); CL(); break;
1222 case 4: a = "CR."; CR(); break;
1223 }
1224 m++; if (m > 255) { cubeinit = false; s = ""; return s; }
1225 }
1226 s += a;
1227 if (shorten) s = Concise(s);
1228 mov[3] = s.length() / 3;
1229 return s;
1230 }
1231 // Bottom Edges Orient (step 4)
BottomEdgesOrient()1232 const string Cubex::BottomEdgesOrient()
1233 {
1234 string s = "";
1235 if (!cubeinit) return s;
1236 int eo[4], a = 0, b, m = 0, r;
1237 while (a != 4) {
1238 eo[0] = Cub[0+2][-2+2][-1+2];
1239 eo[1] = Cub[-1+2][-2+2][0+2];
1240 eo[2] = Cub[0+2][-2+2][1+2];
1241 eo[3] = Cub[1+2][-2+2][0+2];
1242 a = 0; r = 0;
1243 for (int i = 0; i <= 3; i++) {
1244 b = i + 1; if (b > 3) b = 0;
1245 if (eo[i] == 6) {
1246 a++;
1247 if (eo[b] == 6) r = i;
1248 }
1249 }
1250 if (a == 0) {
1251 s += "RD.BC.DL.BA.DR.RU.";
1252 RD(); BC(); DL(); BA(); DR(); RU();
1253 }
1254 else if (a == 2) {
1255 switch (r) {
1256 case 1:
1257 s += "CR."; CR(); break;
1258 case 2:
1259 s += "CL.CL."; CL(); CL(); break;
1260 case 3:
1261 s += "CL."; CL(); break;
1262 }
1263 s += "RD.DL.BC.DR.BA.RU.";
1264 RD(); DL(); BC(); DR(); BA(); RU();
1265 switch (r) {
1266 case 1:
1267 s += "CL."; CL(); break;
1268 case 2:
1269 s += "CR.CR."; CR(); CR(); break;
1270 case 3:
1271 s += "CR."; CR(); break;
1272 }
1273 }
1274 m++; if (m > 255) { cubeinit = false; s = ""; return s; }
1275 }
1276 if (shorten) s = Concise(s);
1277 mov[4] = s.length() / 3;
1278 return s;
1279 }
1280 // Bottom Edges Position (step 5)
BottomEdgesPosition()1281 const string Cubex::BottomEdgesPosition()
1282 {
1283 string s = "";
1284 if (!cubeinit) return s;
1285 int ep[4][2], a = 0, b, l, m = 0, t = 0;
1286 while (a != 4) {
1287 ep[0][0] = Cub[0+2][0+2][-2+2]; ep[0][1] = Cub[0+2][-1+2][-2+2];
1288 ep[1][0] = Cub[-2+2][0+2][0+2]; ep[1][1] = Cub[-2+2][-1+2][0+2];
1289 ep[2][0] = Cub[0+2][0+2][2+2]; ep[2][1] = Cub[0+2][-1+2][2+2];
1290 ep[3][0] = Cub[2+2][0+2][0+2]; ep[3][1] = Cub[2+2][-1+2][0+2];
1291 a = 0; l = 0;
1292 for (int i = 0; i <= 3; i++) {
1293 b = i - 1; if (b < 0) b = 3;
1294 if (ep[i][0] == ep[i][1]) {
1295 a++;
1296 }
1297 else {
1298 if (ep[b][0] != ep[b][1]) l = i;
1299 }
1300 }
1301 if (a < 2) {
1302 t++; if (t > 3) t = 0;
1303 DL();
1304 }
1305 else {
1306 switch (t) {
1307 case 1:
1308 s += "DL."; break;
1309 case 2:
1310 s += "DL.DL."; break;
1311 case 3:
1312 s += "DR."; break;
1313 }
1314 t = 0;
1315 }
1316 if (a == 2) {
1317 switch (l) {
1318 case 1:
1319 s += "CR."; CR(); break;
1320 case 2:
1321 s += "CL.CL."; CL(); CL(); break;
1322 case 3:
1323 s += "CL."; CL(); break;
1324 }
1325 s += "RD.DL.DL.RU.DR.RD.DR.RU.";
1326 RD(); DL(); DL(); RU(); DR(); RD(); DR(); RU();
1327 switch (l) {
1328 case 1:
1329 s += "CL."; CL(); break;
1330 case 2:
1331 s += "CR.CR."; CR(); CR(); break;
1332 case 3:
1333 s += "CR."; CR(); break;
1334 }
1335 }
1336 m++; if (m > 255) { cubeinit = false; s = ""; return s; }
1337 }
1338 if (shorten) s = Concise(s);
1339 mov[5] = s.length() / 3;
1340 return s;
1341 }
1342 // Bottom Corners Position (step 6)
BottomCornersPosition()1343 const string Cubex::BottomCornersPosition()
1344 {
1345 string s = "";
1346 if (!cubeinit) return s;
1347 int cp[4][2], a = 0, l, m = 0;
1348 while (a != 4) {
1349 cp[0][0] = FindCorn(6, 2, 3); cp[0][1] = (fx < 0 && fy < 0 && fz < 0);
1350 cp[1][0] = FindCorn(6, 3, 4); cp[1][1] = (fx < 0 && fy < 0 && fz > 0);
1351 cp[2][0] = FindCorn(6, 4, 5); cp[2][1] = (fx > 0 && fy < 0 && fz > 0);
1352 cp[3][0] = FindCorn(6, 5, 2); cp[3][1] = (fx > 0 && fy < 0 && fz < 0);
1353 a = 0; l = 0;
1354 for (int i = 0; i <= 3; i++) {
1355 if (cp[i][1] == 1) {
1356 a++; l = i;
1357 }
1358 }
1359 if (a < 4) {
1360 switch (l) {
1361 case 1:
1362 s += "CR."; CR(); break;
1363 case 2:
1364 s += "CL.CL."; CL(); CL(); break;
1365 case 3:
1366 s += "CL."; CL(); break;
1367 }
1368 s += "RD.DR.LD.DL.RU.DR.LU.DL.";
1369 RD(); DR(); LD(); DL(); RU(); DR(); LU(); DL();
1370 switch (l) {
1371 case 1:
1372 s += "CL."; CL(); break;
1373 case 2:
1374 s += "CR.CR."; CR(); CR(); break;
1375 case 3:
1376 s += "CR."; CR(); break;
1377 }
1378 m++; if (m > 255) { cubeinit = false; s = ""; return s; }
1379 }
1380 }
1381 if (shorten) s = Concise(s);
1382 mov[6] = s.length() / 3;
1383 return s;
1384 }
1385 // Bottom Corners Orient (step 7)
BottomCornersOrient()1386 const string Cubex::BottomCornersOrient()
1387 {
1388 string s = "";
1389 if (!cubeinit) return s;
1390 int co[4], a = -1, b, b1, b2, d, m = 0, r;
1391 while (a != 0) {
1392 co[0] = FindCorn(6, 2, 5);
1393 co[1] = FindCorn(6, 3, 2);
1394 co[2] = FindCorn(6, 4, 3);
1395 co[3] = FindCorn(6, 5, 4);
1396 a = 0; r = 0; d = 0;
1397 for (int i = 0; i <= 3; i++) {
1398 if (co[i] != -2) a++;
1399 }
1400 if (a > 0) {
1401 for (int i = 0; i <= 3; i++) {
1402 b = i + 2; if (b > 3) b = b - 4;
1403 b1 = i - 1; if (b1 < 0) b1 = 3;
1404 b2 = i + 1; if (b2 > 3) b2 = 0;
1405 if (co[i] != -2) {
1406 switch (a) {
1407 case 2:
1408 if (co[b1] != -2) r = i;
1409 if (co[b] != -2 && (co[i] == 1 || co[i] == -1)) {
1410 d = 1; if (i == 0) r = 0; else r = i - 1;
1411 }
1412 break;
1413 case 3:
1414 if (co[b1] != -2 && co[b2] != -2) r = i;
1415 break;
1416 case 4:
1417 if (co[i] == 1 && co[b1] == 1 && i < 2) r = i;
1418 break;
1419 }
1420 }
1421 }
1422 switch (r) {
1423 case 1:
1424 s += "CR."; CR(); break;
1425 case 2:
1426 s += "CL.CL."; CL(); CL(); break;
1427 case 3:
1428 s += "CL."; CL(); break;
1429 }
1430 if (a == 4) {
1431 s += "RD.DL.DL.RU.DR.RD.DR.RU.";
1432 s += "LD.DR.DR.LU.DL.LD.";
1433 s += "DR.LU.DL.LD.DL.LU.";
1434 s += "RD.DL.DL.RU.DR.RD.DR.RU.";
1435 RD(); DL(); DL(); RU(); DR(); RD(); DR(); RU();
1436 LD(); DR(); DR(); LU(); DL(); LD();
1437 DR(); LU(); DL(); LD(); DL(); LU();
1438 RD(); DL(); DL(); RU(); DR(); RD(); DR(); RU();
1439 }
1440 else if (a == 3 && Cub[2+2][-1+2][-1+2] == 6) {
1441 s += "FC.DR.DR.FA.DL.FC.DL.FA.";
1442 s += "BC.DL.DL.BA.DR.BC.DR.BA.";
1443 FC(); DR(); DR(); FA(); DL(); FC(); DL(); FA();
1444 BC(); DL(); DL(); BA(); DR(); BC(); DR(); BA();
1445 }
1446 else if (a == 2 && d == 0 && Cub[1+2][-1+2][-2+2] == 6) {
1447 s += "LD.DR.LU.DR.LD.DL.DL.LU.";
1448 s += "RD.DL.RU.DL.RD.DR.DR.RU.";
1449 LD(); DR(); LU(); DR(); LD(); DL(); DL(); LU();
1450 RD(); DL(); RU(); DL(); RD(); DR(); DR(); RU();
1451 }
1452 else {
1453 s += "RD.DL.DL.RU.DR.RD.DR.RU.";
1454 s += "LD.DR.DR.LU.DL.LD.DL.LU.";
1455 RD(); DL(); DL(); RU(); DR(); RD(); DR(); RU();
1456 LD(); DR(); DR(); LU(); DL(); LD(); DL(); LU();
1457 }
1458 switch (r) {
1459 case 1:
1460 s += "CL."; CL(); break;
1461 case 2:
1462 s += "CR.CR."; CR(); CR(); break;
1463 case 3:
1464 s += "CR."; CR(); break;
1465 }
1466 m++; if (m > 255) { cubeinit = false; s = ""; return s; }
1467 }
1468 }
1469 if (shorten) s = Concise(s);
1470 mov[7] = s.length() / 3;
1471 return s;
1472 }
1473 // Centers Rotation (for bitmapped/picture cubes) (step 8)
CentersRotate()1474 const string Cubex::CentersRotate()
1475 {
1476 string s = "";
1477 if (!cubeinit) return s;
1478 mov[8] = 0;
1479 if (!cenfix) return s;
1480 int a = 0, b, c, d, p;
1481 for (int q = 1; q <= 6; q++) {
1482 a += Cub[0+2][1+2][0+2];
1483 if (q % 2 == 0) XCU(); else XCA();
1484 }
1485 if (a % 2 != 0) { cubeinit = false; s = ""; return s; }
1486 for (int q = 1; q <= 6; q++) {
1487 b = Cub[0+2][1+2][0+2];
1488 switch (b) {
1489 case 2:
1490 // top = 2
1491 s += "UL.RU.LD.UR.UR.RD.LU.";
1492 s += "UL.RU.LD.UR.UR.RD.LU.";
1493 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1494 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1495 break;
1496 case 1:
1497 d = 0;
1498 for (p = 1; p <= 4; p++) {
1499 if (d == 0) {
1500 c = Cub[-1+2][0+2][0+2];
1501 if (c == 3) {
1502 // top = 1, left = 3
1503 s += "MD.MR.MU.UL.MD.ML.MU.UR.";
1504 MD(); MR(); MU(); UL(); MD(); ML(); MU(); UR();
1505 d = 1;
1506 }
1507 }
1508 s += "CL."; XCL();
1509 }
1510 if (d == 0) {
1511 for (p = 1; p <= 4; p++) {
1512 if (d == 0) {
1513 c = Cub[-1+2][0+2][0+2];
1514 if (c == 1) {
1515 // top = 1, left = 1
1516 s += "CC.";
1517 s += "UL.RU.LD.UR.UR.RD.LU.";
1518 s += "UL.RU.LD.UR.UR.RD.LU.";
1519 s += "CA.";
1520 s += "MD.MR.MU.UL.MD.ML.MU.UR.";
1521 CC();
1522 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1523 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1524 CA();
1525 MD(); MR(); MU(); UL(); MD(); ML(); MU(); UR();
1526 d = 1;
1527 }
1528 }
1529 s += "CL."; XCL();
1530 }
1531 }
1532 if (d == 0) {
1533 c = Cub[0+2][-1+2][0+2];
1534 switch (c) {
1535 case 3:
1536 // top = 1, bottom = 3
1537 s += "CC.";
1538 s += "MD.MR.MU.UL.MD.ML.MU.UR.";
1539 s += "CA.";
1540 s += "MD.MR.MU.UL.MD.ML.MU.UR.";
1541 CC();
1542 MD(); MR(); MU(); UL(); MD(); ML(); MU(); UR();
1543 CA();
1544 MD(); MR(); MU(); UL(); MD(); ML(); MU(); UR();
1545 break;
1546 case 1:
1547 // top = 1, bottom = 1
1548 s += "CC.CC.";
1549 s += "UL.RU.LD.UR.UR.RD.LU.";
1550 s += "UL.RU.LD.UR.UR.RD.LU.";
1551 s += "CA.";
1552 s += "MD.MR.MU.UL.MD.ML.MU.UR.";
1553 s += "CA.";
1554 s += "MD.MR.MU.UL.MD.ML.MU.UR.";
1555 CC(); CC();
1556 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1557 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1558 CA();
1559 MD(); MR(); MU(); UL(); MD(); ML(); MU(); UR();
1560 CA();
1561 MD(); MR(); MU(); UL(); MD(); ML(); MU(); UR();
1562 break;
1563 }
1564 }
1565 break;
1566 case 3:
1567 d = 0;
1568 for (p = 1; p <= 4; p++) {
1569 if (d == 0) {
1570 c = Cub[1+2][0+2][0+2];
1571 if (c == 1) {
1572 // top = 3, right = 1
1573 s += "MD.ML.MU.UR.MD.MR.MU.UL.";
1574 MD(); ML(); MU(); UR(); MD(); MR(); MU(); UL();
1575 d = 1;
1576 }
1577 }
1578 s += "CL."; XCL();
1579 }
1580 if (d == 0) {
1581 for (p = 1; p <= 4; p++) {
1582 if (d == 0) {
1583 c = Cub[1+2][0+2][0+2];
1584 if (c == 3) {
1585 // top = 3, right = 3
1586 s += "CA.";
1587 s += "UL.RU.LD.UR.UR.RD.LU.";
1588 s += "UL.RU.LD.UR.UR.RD.LU.";
1589 s += "CC.";
1590 s += "MD.ML.MU.UR.MD.MR.MU.UL.";
1591 CA();
1592 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1593 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1594 CC();
1595 MD(); ML(); MU(); UR(); MD(); MR(); MU(); UL();
1596 d = 1;
1597 }
1598 }
1599 s += "CL."; XCL();
1600 }
1601 }
1602 if (d == 0) {
1603 c = Cub[0+2][-1+2][0+2];
1604 switch (c) {
1605 case 1:
1606 // top = 3, bottom = 1
1607 s += "CA.";
1608 s += "MD.ML.MU.UR.MD.MR.MU.UL.";
1609 s += "CC.";
1610 s += "MD.ML.MU.UR.MD.MR.MU.UL.";
1611 CA();
1612 MD(); ML(); MU(); UR(); MD(); MR(); MU(); UL();
1613 CC();
1614 MD(); ML(); MU(); UR(); MD(); MR(); MU(); UL();
1615 break;
1616 case 3:
1617 // top = 3, bottom = 3
1618 s += "CA.CA.";
1619 s += "UL.RU.LD.UR.UR.RD.LU.";
1620 s += "UL.RU.LD.UR.UR.RD.LU.";
1621 s += "CC.";
1622 s += "MD.ML.MU.UR.MD.MR.MU.UL.";
1623 s += "CC.";
1624 s += "MD.ML.MU.UR.MD.MR.MU.UL.";
1625 CA(); CA();
1626 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1627 UL(); RU(); LD(); UR(); UR(); RD(); LU();
1628 CC();
1629 MD(); ML(); MU(); UR(); MD(); MR(); MU(); UL();
1630 CC();
1631 MD(); ML(); MU(); UR(); MD(); MR(); MU(); UL();
1632 break;
1633 }
1634 }
1635 break;
1636 }
1637 if (q % 2 == 0) {
1638 s += "CU."; XCU();
1639 }
1640 else {
1641 s += "CA."; XCA();
1642 }
1643 }
1644 if (shorten) s = Concise(s);
1645 mov[8] = s.length() / 3;
1646 return s;
1647 }
1648 // solve the cube (uses many other routines also)
1649 // slightly complicated...
SolveCube()1650 const int Cubex::SolveCube()
1651 {
1652 // make sure cube was initialized
1653 if (!cubeinit) return 1;
1654 // set up buffers and counters and such...
1655 int Rub[5][5][5], Fac[7][2], mvs[MOV+1], m = -1, n;
1656 string s = ""; string t = ""; string p = "";
1657 // make sure that the cube has the proper cubelets...
1658 cubeinit = false;
1659 // check that all the centers are present
1660 for (int i = 1; i <= 6; i++) {
1661 if (FindCent(i) == 0) {
1662 erval = 1; return erval;
1663 }
1664 }
1665 // buffer the cube so we can interpolate it to a specific color arrangement to check for edges and corners...
1666 for (int i = -2; i <= 2; i++) {
1667 for (int j = -2; j <= 2; j++) {
1668 for (int k = -2; k <= 2; k++) {
1669 Rub[i+2][j+2][k+2] = Cub[i+2][j+2][k+2];
1670 }
1671 }
1672 }
1673 // interpolate the cube...
1674 Fac[0][0] = 0;
1675 Fac[1][0] = Cub[0+2][2+2][0+2]; Fac[2][0] = Cub[0+2][0+2][-2+2];
1676 Fac[3][0] = Cub[-2+2][0+2][0+2]; Fac[4][0] = Cub[0+2][0+2][2+2];
1677 Fac[5][0] = Cub[2+2][0+2][0+2]; Fac[6][0] = Cub[0+2][-2+2][0+2];
1678 for (int i = 0; i <= 6; i++) {
1679 Fac[Fac[i][0]][1] = i;
1680 }
1681 // apply interpolation
1682 for (int i = -1; i <= 1; i++) {
1683 for (int j = -1; j <= 1; j++) {
1684 Cub[i+2][2+2][j+2] = Fac[Cub[i+2][2+2][j+2]][1];
1685 Cub[i+2][j+2][-2+2] = Fac[Cub[i+2][j+2][-2+2]][1];
1686 Cub[-2+2][i+2][j+2] = Fac[Cub[-2+2][i+2][j+2]][1];
1687 Cub[i+2][j+2][2+2] = Fac[Cub[i+2][j+2][2+2]][1];
1688 Cub[2+2][i+2][j+2] = Fac[Cub[2+2][i+2][j+2]][1];
1689 Cub[i+2][-2+2][j+2] = Fac[Cub[i+2][-2+2][j+2]][1];
1690 }
1691 }
1692 // check that all edges and corners are present
1693 for (int i = 1; i <= 4; i++) {
1694 int j = 1;
1695 if (i < 4) j = i + 1;
1696 if (FindEdge(1, i + 1) == 0 ||
1697 FindEdge(6, i + 1) == 0 ||
1698 FindEdge(i + 1, j + 1) == 0 ||
1699 FindCorn(1, i + 1, j + 1) == 0 ||
1700 FindCorn(6, i + 1, j + 1) == 0) {
1701 m = 0;
1702 }
1703 }
1704 // return cube to pre-interpolated status
1705 for (int i = -2; i <= 2; i++) {
1706 for (int j = -2; j <= 2; j++) {
1707 for (int k = -2; k <= 2; k++) {
1708 Cub[i+2][j+2][k+2] = Rub[i+2][j+2][k+2];
1709 }
1710 }
1711 }
1712 // if any flags went off during checking then return error 1 (improper cubelets)
1713 if (m == 0) { erval = 1; return erval; }
1714 cubeinit = true;
1715 // cube seems to have ok cubelets, so try to solve it...
1716 for (int i = 1; i <= MOV; i++) mvs[i] = 0;
1717 // try to solve the cube from each possible starting orientation (to find the fastest solution)...
1718 for (int q = 1; q <= 24; q++) {
1719 // buffer old cube
1720 for (int i = -2; i <= 2; i++) {
1721 for (int j = -2; j <= 2; j++) {
1722 for (int k = -2; k <= 2; k++) {
1723 Rub[i+2][j+2][k+2] = Cub[i+2][j+2][k+2];
1724 }
1725 }
1726 }
1727 // interpolate so that centers are in order...
1728 Fac[0][0] = 0;
1729 Fac[1][0] = Cub[0+2][2+2][0+2]; Fac[2][0] = Cub[0+2][0+2][-2+2];
1730 Fac[3][0] = Cub[-2+2][0+2][0+2]; Fac[4][0] = Cub[0+2][0+2][2+2];
1731 Fac[5][0] = Cub[2+2][0+2][0+2]; Fac[6][0] = Cub[0+2][-2+2][0+2];
1732 for (int i = 0; i <= 6; i++) {
1733 Fac[Fac[i][0]][1] = i;
1734 }
1735 // apply interpolation
1736 for (int i = -1; i <= 1; i++) {
1737 for (int j = -1; j <= 1; j++) {
1738 Cub[i+2][2+2][j+2] = Fac[Cub[i+2][2+2][j+2]][1];
1739 Cub[i+2][j+2][-2+2] = Fac[Cub[i+2][j+2][-2+2]][1];
1740 Cub[-2+2][i+2][j+2] = Fac[Cub[-2+2][i+2][j+2]][1];
1741 Cub[i+2][j+2][2+2] = Fac[Cub[i+2][j+2][2+2]][1];
1742 Cub[2+2][i+2][j+2] = Fac[Cub[2+2][i+2][j+2]][1];
1743 Cub[i+2][-2+2][j+2] = Fac[Cub[i+2][-2+2][j+2]][1];
1744 }
1745 }
1746 // if we dont care about centers, we can imply their orientation liberally
1747 if (!cenfix) {
1748 Cub[0+2][1+2][0+2] = 0;
1749 Cub[0+2][0+2][-1+2] = 0;
1750 Cub[-1+2][0+2][0+2] = 0;
1751 Cub[0+2][0+2][1+2] = 0;
1752 Cub[1+2][0+2][0+2] = 0;
1753 Cub[0+2][-1+2][0+2] = 0;
1754 }
1755 // solve the cube...
1756 t = TopEdges();
1757 t += TopCorners();
1758 t += MiddleEdges();
1759 if (!cubeinit && erval == 0) { erval = 4; }
1760 t += BottomEdgesOrient();
1761 if (!cubeinit && erval == 0) { erval = 5; }
1762 t += BottomEdgesPosition();
1763 if (!cubeinit && erval == 0) { erval = 2; }
1764 t += BottomCornersPosition();
1765 if (!cubeinit && erval == 0) { erval = 6; }
1766 t += BottomCornersOrient();
1767 if (!cubeinit && erval == 0) { erval = 7; }
1768 t += CentersRotate();
1769 if (!cubeinit && erval == 0) { erval = 3; }
1770 // errors above:
1771 // 2-nondescript parity, 3-center orientation, 4-backward centers or corners,
1772 // 5-edge flip parity, 6-edge swap parity, 7-corner rotation parity
1773 if (shorten) {
1774 mov[0] = -1; t = Concise(p + t); mov[0] = 0;
1775 }
1776 t = Efficient(t);
1777 n = t.length() / 3;
1778 // if this was shortest solution found so far, run with it...
1779 if (n < m || m < 0) {
1780 m = n; s = t;
1781 for (int i = 1; i <= MOV; i++) {
1782 mvs[i] = mov[i];
1783 }
1784 // if we dont care about centers, apply the implied orientations
1785 if (!cenfix) {
1786 Rub[0+2][1+2][0+2] = (4 - Cub[0+2][1+2][0+2]) % 4;
1787 Rub[0+2][0+2][-1+2] = (4 - Cub[0+2][0+2][-1+2]) % 4;
1788 Rub[-1+2][0+2][0+2] = (4 - Cub[-1+2][0+2][0+2]) % 4;
1789 Rub[0+2][0+2][1+2] = (4 - Cub[0+2][0+2][1+2]) % 4;
1790 Rub[1+2][0+2][0+2] = (4 - Cub[1+2][0+2][0+2]) % 4;
1791 Rub[0+2][-1+2][0+2] = (4 - Cub[0+2][-1+2][0+2]) % 4;
1792 }
1793 }
1794 // restore old (pre-interpolated) cube
1795 for (int i = -2; i <= 2; i++) {
1796 for (int j = -2; j <= 2; j++) {
1797 for (int k = -2; k <= 2; k++) {
1798 Cub[i+2][j+2][k+2] = Rub[i+2][j+2][k+2];
1799 }
1800 }
1801 }
1802 // rotate to next orientation and try again to see if we get a shorter solution
1803 if (q % 4 == 0) {
1804 p += "CU."; XCU();
1805 }
1806 else {
1807 p += "CL."; XCL();
1808 }
1809 if (q == 12) {
1810 p = "CU.CU.CR."; XCU(); XCU(); XCR();
1811 }
1812 else if (q == 24) {
1813 XCD(); XCD(); XCR();
1814 }
1815 }
1816 // set mov array...
1817 for (int i = 1; i <= MOV; i++) {
1818 mov[i] = mvs[i];
1819 }
1820 // return error if one was found
1821 if (!cubeinit) return erval;
1822 mov[0] = m;
1823 // set solution and return...
1824 solution = s;
1825 return 0;
1826 }
1827 // end of cube class definitions
1828