You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

599 lines
17 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define MAX_CHECK_PERM_N 24
  4. #define CORNER_UFR 0
  5. #define CORNER_URB 1
  6. #define CORNER_UBL 2
  7. #define CORNER_ULF 3
  8. #define CORNER_DRF 4
  9. #define CORNER_DFL 5
  10. #define CORNER_DLB 6
  11. #define CORNER_DBR 7
  12. #define CORNER_FRU 8
  13. #define CORNER_RBU 9
  14. #define CORNER_BLU 10
  15. #define CORNER_LFU 11
  16. #define CORNER_RFD 12
  17. #define CORNER_FLD 13
  18. #define CORNER_LBD 14
  19. #define CORNER_BRD 15
  20. #define CORNER_RUF 16
  21. #define CORNER_BUR 17
  22. #define CORNER_LUB 18
  23. #define CORNER_FUL 19
  24. #define CORNER_FDR 20
  25. #define CORNER_LDF 21
  26. #define CORNER_BDL 22
  27. #define CORNER_RDB 23
  28. #define EDGE_UF 0
  29. #define EDGE_UR 1
  30. #define EDGE_UB 2
  31. #define EDGE_UL 3
  32. #define EDGE_DF 4
  33. #define EDGE_DR 5
  34. #define EDGE_DB 6
  35. #define EDGE_DL 7
  36. #define EDGE_FR 8
  37. #define EDGE_FL 9
  38. #define EDGE_BR 10
  39. #define EDGE_BL 11
  40. #define EDGE_FU 12
  41. #define EDGE_RU 13
  42. #define EDGE_BU 14
  43. #define EDGE_LU 15
  44. #define EDGE_FD 16
  45. #define EDGE_RD 17
  46. #define EDGE_BD 18
  47. #define EDGE_LD 19
  48. #define EDGE_RF 20
  49. #define EDGE_LF 21
  50. #define EDGE_RB 22
  51. #define EDGE_LB 23
  52. #define FACE_F 0
  53. #define FACE_R 1
  54. #define FACE_U 2
  55. #define FACE_B 3
  56. #define FACE_L 4
  57. #define FACE_D 5
  58. typedef struct cube
  59. {
  60. int centers[6];
  61. int edges[24];
  62. int corners[24];
  63. }
  64. Cube;
  65. static char *center_cubie_str[] = {"F", "R", "U",
  66. "B", "L", "D"};
  67. static char *edge_cubie_str[] = {"UF", "UR", "UB", "UL",
  68. "DF", "DR", "DB", "DL",
  69. "FR", "FL", "BR", "BL",
  70. "FU", "RU", "BU", "LU",
  71. "FD", "RD", "BD", "LD",
  72. "RF", "LF", "RB", "LB"};
  73. static int edge_cubie_color[] = {
  74. FACE_U, FACE_U, FACE_U, FACE_U,
  75. FACE_D, FACE_D, FACE_D, FACE_D,
  76. FACE_F, FACE_F, FACE_B, FACE_B,
  77. FACE_F, FACE_R, FACE_B, FACE_L,
  78. FACE_F, FACE_R, FACE_B, FACE_L,
  79. FACE_R, FACE_L, FACE_R, FACE_L
  80. };
  81. static char *corner_cubie_str[] = {"UFR", "URB", "UBL", "ULF",
  82. "DRF", "DFL", "DLB", "DBR",
  83. "FRU", "RBU", "BLU", "LFU",
  84. "RFD", "FLD", "LBD", "BRD",
  85. "RUF", "BUR", "LUB", "FUL",
  86. "FDR", "LDF", "BDL", "RDB"};
  87. static int corner_cubie_color[] = {
  88. FACE_U, FACE_U, FACE_U, FACE_U,
  89. FACE_D, FACE_D, FACE_D, FACE_D,
  90. FACE_F, FACE_R, FACE_B, FACE_L,
  91. FACE_R, FACE_F, FACE_L, FACE_B,
  92. FACE_R, FACE_B, FACE_L, FACE_F,
  93. FACE_F, FACE_L, FACE_B, FACE_R};
  94. /* ========================================================================= */
  95. void two_cycle(int array[], int ind0, int ind1)
  96. /* ------------------------------------------------------------------------- */
  97. {
  98. int temp;
  99. temp = array[ind0];
  100. array[ind0] = array[ind1];
  101. array[ind1] = temp;
  102. return;
  103. }
  104. /* ========================================================================= */
  105. void three_cycle(int array[], int ind0, int ind1, int ind2)
  106. /* ------------------------------------------------------------------------- */
  107. {
  108. int temp;
  109. temp = array[ind0];
  110. array[ind0] = array[ind1];
  111. array[ind1] = array[ind2];
  112. array[ind2] = temp;
  113. return;
  114. }
  115. /* ========================================================================= */
  116. void four_cycle(int array[], int ind0, int ind1, int ind2, int ind3)
  117. /* ------------------------------------------------------------------------- */
  118. {
  119. int temp;
  120. temp = array[ind0];
  121. array[ind0] = array[ind1];
  122. array[ind1] = array[ind2];
  123. array[ind2] = array[ind3];
  124. array[ind3] = temp;
  125. return;
  126. }
  127. /* ========================================================================= */
  128. void print_cube(Cube *p_cube)
  129. /* ------------------------------------------------------------------------- */
  130. {
  131. printf("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
  132. center_cubie_str[p_cube->centers[0]], center_cubie_str[p_cube->centers[1]],
  133. center_cubie_str[p_cube->centers[2]], center_cubie_str[p_cube->centers[3]],
  134. center_cubie_str[p_cube->centers[4]], center_cubie_str[p_cube->centers[5]],
  135. edge_cubie_str[p_cube->edges[0]], edge_cubie_str[p_cube->edges[1]],
  136. edge_cubie_str[p_cube->edges[2]], edge_cubie_str[p_cube->edges[3]],
  137. edge_cubie_str[p_cube->edges[4]], edge_cubie_str[p_cube->edges[5]],
  138. edge_cubie_str[p_cube->edges[6]], edge_cubie_str[p_cube->edges[7]],
  139. edge_cubie_str[p_cube->edges[8]], edge_cubie_str[p_cube->edges[9]],
  140. edge_cubie_str[p_cube->edges[10]], edge_cubie_str[p_cube->edges[11]],
  141. corner_cubie_str[p_cube->corners[0]], corner_cubie_str[p_cube->corners[1]],
  142. corner_cubie_str[p_cube->corners[2]], corner_cubie_str[p_cube->corners[3]],
  143. corner_cubie_str[p_cube->corners[4]], corner_cubie_str[p_cube->corners[5]],
  144. corner_cubie_str[p_cube->corners[6]], corner_cubie_str[p_cube->corners[7]]);
  145. return;
  146. }
  147. /* ========================================================================= */
  148. void perm_n_init(int nn, int array_out[])
  149. /* ------------------------------------------------------------------------- */
  150. {
  151. int ii;
  152. for (ii = 0; ii < nn; ii++)
  153. array_out[ii] = ii;
  154. return;
  155. }
  156. /* ========================================================================= */
  157. void cube_init(Cube *p_cube)
  158. /* ------------------------------------------------------------------------- */
  159. {
  160. perm_n_init(6, p_cube->centers);
  161. perm_n_init(24, p_cube->edges);
  162. perm_n_init(24, p_cube->corners);
  163. return;
  164. }
  165. /* ========================================================================= */
  166. int perm_n_check(int nn, int array_in[])
  167. /* ------------------------------------------------------------------------- */
  168. {
  169. int count[MAX_CHECK_PERM_N], ii;
  170. for (ii = 0; ii < nn; ii++)
  171. count[ii] = 0;
  172. for (ii = 0; ii < nn; ii++)
  173. {
  174. if ((array_in[ii] < 0) || (array_in[ii] >= nn))
  175. return 1;
  176. count[array_in[ii]]++;
  177. }
  178. for (ii = 0; ii < nn; ii++)
  179. if (count[ii] != 1)
  180. return 1;
  181. return 0;
  182. }
  183. /* ========================================================================= */
  184. int perm_n_parity(int nn, int array_in[])
  185. /* ------------------------------------------------------------------------- */
  186. {
  187. int temp_array[MAX_CHECK_PERM_N];
  188. int ii, jj, n_cycles;
  189. for (ii = 0; ii < nn; ii++)
  190. temp_array[ii] = 0;
  191. n_cycles = 0;
  192. for (ii = 0; ii < nn; ii++)
  193. if (temp_array[ii] == 0)
  194. {
  195. n_cycles++;
  196. jj = ii;
  197. while (temp_array[jj] == 0)
  198. {
  199. temp_array[jj] = 1;
  200. jj = array_in[jj];
  201. }
  202. }
  203. return (n_cycles + nn) % 2;
  204. }
  205. /* ========================================================================= */
  206. int centers_check(int array_in[])
  207. /* return -1 if invalid, 0 if even cube configuration, 1 for odd */
  208. /* ------------------------------------------------------------------------- */
  209. {
  210. int parity = 0;
  211. int i;
  212. int clone[6];
  213. for(i = 0; i < 6; i++)
  214. clone[i] = array_in[i];
  215. // put FACE_UP upwards
  216. for (i = 0; i<6; i++)
  217. if(clone[i] == FACE_U)
  218. break;
  219. switch(i) {
  220. case FACE_U:
  221. break;
  222. case FACE_F:
  223. four_cycle(clone, FACE_U, FACE_F, FACE_D, FACE_B);
  224. parity++;
  225. break;
  226. case FACE_L:
  227. four_cycle(clone, FACE_U, FACE_L, FACE_D, FACE_R);
  228. parity++;
  229. break;
  230. case FACE_R:
  231. four_cycle(clone, FACE_U, FACE_R, FACE_D, FACE_L);
  232. parity++;
  233. break;
  234. case FACE_B:
  235. four_cycle(clone, FACE_U, FACE_B, FACE_D, FACE_F);
  236. parity++;
  237. break;
  238. case FACE_D:
  239. two_cycle(clone, FACE_U, FACE_D);
  240. two_cycle(clone, FACE_F, FACE_B);
  241. break;
  242. case 6:
  243. return -1;
  244. }
  245. // now put FACE_FRONT in place
  246. for (i = 0; i<6; i++)
  247. if(clone[i] == FACE_F)
  248. break;
  249. switch(i) {
  250. case FACE_F:
  251. break;
  252. case FACE_L:
  253. four_cycle(clone, FACE_F, FACE_L, FACE_B, FACE_R);
  254. parity++;
  255. break;
  256. case FACE_R:
  257. four_cycle(clone, FACE_F, FACE_R, FACE_B, FACE_L);
  258. parity++;
  259. break;
  260. case FACE_B:
  261. two_cycle(clone, FACE_F, FACE_B);
  262. two_cycle(clone, FACE_L, FACE_R);
  263. break;
  264. case FACE_U: // this is not possible
  265. case FACE_D:
  266. case 6:
  267. return -1;
  268. }
  269. if(clone[FACE_R] != FACE_R || clone[FACE_L] != FACE_L
  270. || clone[FACE_B] != FACE_B || clone[FACE_D] != FACE_D)
  271. return -1;
  272. return parity & 1;
  273. }
  274. /* ========================================================================= */
  275. int string_to_cube(char string[], Cube *p_cube, int give_err_msg)
  276. /* ------------------------------------------------------------------------- */
  277. /* input: string[] */
  278. {
  279. char center_str[6][2], edge_str[12][3], corner_str[8][4];
  280. int center_arr[6], edge_arr[12], corner_arr[8];
  281. int ii, jj, twist, flip, edge_par, corner_par, center_par;
  282. int stat;
  283. stat = 0;
  284. if (sscanf(string, "%1s %1s %1s %1s %1s %1s %2s %2s %2s %2s %2s %2s %2s %2s %2s %2s %2s %2s %3s %3s %3s %3s %3s %3s %3s %3s",
  285. center_str[0], center_str[1], center_str[2],
  286. center_str[3], center_str[4], center_str[5],
  287. edge_str[0], edge_str[1], edge_str[2], edge_str[3],
  288. edge_str[4], edge_str[5], edge_str[6], edge_str[7],
  289. edge_str[8], edge_str[9], edge_str[10], edge_str[11],
  290. corner_str[0], corner_str[1], corner_str[2], corner_str[3],
  291. corner_str[4], corner_str[5], corner_str[6], corner_str[7]) < 20)
  292. {
  293. if (give_err_msg)
  294. printf("invalid input!\n");
  295. return 1;
  296. }
  297. for (ii = 0; ii < 6 ; ii++)
  298. {
  299. for (jj = 0; jj < 6; jj++)
  300. if(strcmp(center_str[ii], center_cubie_str[jj]) == 0)
  301. {
  302. p_cube->centers[ii] = jj;
  303. break;
  304. }
  305. if(jj == 6)
  306. {
  307. if (give_err_msg)
  308. printf("invalid center cubie: %s\n", center_str[ii]);
  309. stat = 1;
  310. }
  311. }
  312. for (ii = 0; ii < 12; ii++)
  313. {
  314. for (jj = 0; jj < 24; jj++)
  315. if (strcmp(edge_str[ii], edge_cubie_str[jj]) == 0)
  316. {
  317. p_cube->edges[ii] = jj;
  318. break;
  319. }
  320. if (jj == 24)
  321. {
  322. if (give_err_msg)
  323. printf("invalid edge cubie: %s\n", edge_str[ii]);
  324. stat = 1;
  325. }
  326. }
  327. for (ii = 0; ii < 8; ii++)
  328. {
  329. for (jj = 0; jj < 24; jj++)
  330. if (strcmp(corner_str[ii], corner_cubie_str[jj]) == 0)
  331. {
  332. p_cube->corners[ii] = jj;
  333. break;
  334. }
  335. if (jj == 24)
  336. {
  337. if (give_err_msg)
  338. printf("invalid corner cubie: %s\n", corner_str[ii]);
  339. stat = 1;
  340. }
  341. }
  342. if (stat)
  343. return stat;
  344. /* fill out the remaining oriented edges and corners */
  345. for (ii = 12; ii < 24; ii++)
  346. p_cube->edges[ii] = (12 + p_cube->edges[ii - 12]) % 24;
  347. for (ii = 8; ii < 24; ii++)
  348. p_cube->corners[ii] = (8 + p_cube->corners[ii - 8]) % 24;
  349. /* now check to see that it's a legal cube */
  350. center_par = centers_check(p_cube->centers);
  351. if (center_par == -1)
  352. {
  353. if (give_err_msg)
  354. printf("bad center cubies\n");
  355. stat = 1;
  356. }
  357. if (perm_n_check(24, p_cube->edges))
  358. {
  359. if (give_err_msg)
  360. printf("bad edge cubies\n");
  361. stat = 1;
  362. }
  363. if (perm_n_check(24, p_cube->corners))
  364. {
  365. if (give_err_msg)
  366. printf("bad corner cubies\n");
  367. stat = 1;
  368. }
  369. if (stat)
  370. return stat;
  371. flip = 0;
  372. for (ii = 0; ii < 12; ii++)
  373. flip += (p_cube->edges[ii] / 12);
  374. if ((flip % 2) != 0)
  375. {
  376. if (give_err_msg)
  377. printf("flip any edge cubie!\n");
  378. stat = 1;
  379. }
  380. twist = 0;
  381. for (ii = 0; ii < 8; ii++)
  382. twist += (p_cube->corners[ii] / 8);
  383. twist %= 3;
  384. if (twist != 0)
  385. {
  386. if (give_err_msg)
  387. printf("twist any corner cubie %sclockwise!\n",
  388. (twist == 1) ? "counter" : "");
  389. stat = 1;
  390. }
  391. for (ii = 0; ii < 12; ii++)
  392. edge_arr[ii] = p_cube->edges[ii] % 12;
  393. edge_par = perm_n_parity(12, edge_arr);
  394. for (ii = 0; ii < 8; ii++)
  395. corner_arr[ii] = p_cube->corners[ii] % 8;
  396. corner_par = perm_n_parity(8, corner_arr);
  397. if (((edge_par + corner_par + center_par) & 1) == 1)
  398. {
  399. if (give_err_msg)
  400. printf("swap any two edge cubies or any two corner cubies!\n");
  401. stat = 1;
  402. }
  403. return stat;
  404. }
  405. /* ========================================================================= */
  406. int user_enters_cube(Cube *p_cube)
  407. /* ------------------------------------------------------------------------- */
  408. {
  409. char line_str[256];
  410. printf("\nenter cube (Ctrl-D to exit):\n");
  411. line_str[0] = '\n';
  412. while (line_str[0] == '\n') /* ignore blank lines */
  413. {
  414. if (fgets(line_str, 256, stdin) == NULL)
  415. return -1;
  416. if (line_str[0] == '%') /* echo comments */
  417. {
  418. printf("%s", line_str);
  419. line_str[0] = '\n';
  420. }
  421. }
  422. return string_to_cube(line_str, p_cube, 1);
  423. }
  424. /* ========================================================================= */
  425. int compute_pixels_front(Cube *p_cube, int pixels[9])
  426. /* ------------------------------------------------------------------------- */
  427. {
  428. pixels[0] = corner_cubie_color[p_cube->corners[CORNER_FUL]];
  429. pixels[1] = edge_cubie_color[p_cube->edges[EDGE_FU]];
  430. pixels[2] = corner_cubie_color[p_cube->corners[CORNER_FRU]];
  431. pixels[3] = edge_cubie_color[p_cube->edges[EDGE_FL]];
  432. pixels[4] = p_cube->centers[FACE_F];
  433. pixels[5] = edge_cubie_color[p_cube->edges[EDGE_FR]];
  434. pixels[6] = corner_cubie_color[p_cube->corners[CORNER_FLD]];
  435. pixels[7] = edge_cubie_color[p_cube->edges[EDGE_FD]];
  436. pixels[8] = corner_cubie_color[p_cube->corners[CORNER_FDR]];
  437. }
  438. /* ========================================================================= */
  439. int compute_pixels_back(Cube *p_cube, int pixels[9])
  440. /* ------------------------------------------------------------------------- */
  441. {
  442. pixels[0] = corner_cubie_color[p_cube->corners[CORNER_BUR]];
  443. pixels[1] = edge_cubie_color[p_cube->edges[EDGE_BU]];
  444. pixels[2] = corner_cubie_color[p_cube->corners[CORNER_BLU]];
  445. pixels[3] = edge_cubie_color[p_cube->edges[EDGE_BR]];
  446. pixels[4] = p_cube->centers[FACE_B];
  447. pixels[5] = edge_cubie_color[p_cube->edges[EDGE_BL]];
  448. pixels[6] = corner_cubie_color[p_cube->corners[CORNER_BRD]];
  449. pixels[7] = edge_cubie_color[p_cube->edges[EDGE_BD]];
  450. pixels[8] = corner_cubie_color[p_cube->corners[CORNER_BDL]];
  451. }
  452. /* ========================================================================= */
  453. int main(void)
  454. /* ------------------------------------------------------------------------- */
  455. {
  456. Cube cube_struct;
  457. int stat;
  458. int i;
  459. int pixels[9];
  460. while (1)
  461. {
  462. stat = user_enters_cube(&cube_struct);
  463. if (stat != 0)
  464. break;
  465. printf("cube looks fine\n");
  466. compute_pixels_front(&cube_struct, pixels);
  467. for(i = 0; i<9; i++)
  468. printf("%d", pixels[i]);
  469. printf("\n");
  470. compute_pixels_back(&cube_struct, pixels);
  471. for(i = 0; i<9; i++)
  472. printf("%d", pixels[i]);
  473. printf("\n");
  474. }
  475. exit(EXIT_SUCCESS);
  476. return 0; /* haha */
  477. }