|
- #include <stdio.h>
- #include <stdlib.h>
-
- #define MAX_CHECK_PERM_N 24
-
- #define CORNER_UFR 0
- #define CORNER_URB 1
- #define CORNER_UBL 2
- #define CORNER_ULF 3
- #define CORNER_DRF 4
- #define CORNER_DFL 5
- #define CORNER_DLB 6
- #define CORNER_DBR 7
-
- #define CORNER_FRU 8
- #define CORNER_RBU 9
- #define CORNER_BLU 10
- #define CORNER_LFU 11
- #define CORNER_RFD 12
- #define CORNER_FLD 13
- #define CORNER_LBD 14
- #define CORNER_BRD 15
-
- #define CORNER_RUF 16
- #define CORNER_BUR 17
- #define CORNER_LUB 18
- #define CORNER_FUL 19
- #define CORNER_FDR 20
- #define CORNER_LDF 21
- #define CORNER_BDL 22
- #define CORNER_RDB 23
-
- #define EDGE_UF 0
- #define EDGE_UR 1
- #define EDGE_UB 2
- #define EDGE_UL 3
- #define EDGE_DF 4
- #define EDGE_DR 5
- #define EDGE_DB 6
- #define EDGE_DL 7
- #define EDGE_FR 8
- #define EDGE_FL 9
- #define EDGE_BR 10
- #define EDGE_BL 11
-
- #define EDGE_FU 12
- #define EDGE_RU 13
- #define EDGE_BU 14
- #define EDGE_LU 15
- #define EDGE_FD 16
- #define EDGE_RD 17
- #define EDGE_BD 18
- #define EDGE_LD 19
- #define EDGE_RF 20
- #define EDGE_LF 21
- #define EDGE_RB 22
- #define EDGE_LB 23
-
- #define FACE_F 0
- #define FACE_R 1
- #define FACE_U 2
- #define FACE_B 3
- #define FACE_L 4
- #define FACE_D 5
-
-
- typedef struct cube
- {
- int centers[6];
- int edges[24];
- int corners[24];
- }
- Cube;
-
-
- static char *center_cubie_str[] = {"F", "R", "U",
- "B", "L", "D"};
-
- static char *edge_cubie_str[] = {"UF", "UR", "UB", "UL",
- "DF", "DR", "DB", "DL",
- "FR", "FL", "BR", "BL",
- "FU", "RU", "BU", "LU",
- "FD", "RD", "BD", "LD",
- "RF", "LF", "RB", "LB"};
-
- static int edge_cubie_color[] = {
- FACE_U, FACE_U, FACE_U, FACE_U,
- FACE_D, FACE_D, FACE_D, FACE_D,
- FACE_F, FACE_F, FACE_B, FACE_B,
- FACE_F, FACE_R, FACE_B, FACE_L,
- FACE_F, FACE_R, FACE_B, FACE_L,
- FACE_R, FACE_L, FACE_R, FACE_L
- };
-
- static char *corner_cubie_str[] = {"UFR", "URB", "UBL", "ULF",
- "DRF", "DFL", "DLB", "DBR",
- "FRU", "RBU", "BLU", "LFU",
- "RFD", "FLD", "LBD", "BRD",
- "RUF", "BUR", "LUB", "FUL",
- "FDR", "LDF", "BDL", "RDB"};
-
- static int corner_cubie_color[] = {
- FACE_U, FACE_U, FACE_U, FACE_U,
- FACE_D, FACE_D, FACE_D, FACE_D,
- FACE_F, FACE_R, FACE_B, FACE_L,
- FACE_R, FACE_F, FACE_L, FACE_B,
- FACE_R, FACE_B, FACE_L, FACE_F,
- FACE_F, FACE_L, FACE_B, FACE_R};
-
- /* ========================================================================= */
- void two_cycle(int array[], int ind0, int ind1)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp;
-
-
- temp = array[ind0];
- array[ind0] = array[ind1];
- array[ind1] = temp;
-
- return;
- }
-
-
- /* ========================================================================= */
- void three_cycle(int array[], int ind0, int ind1, int ind2)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp;
-
-
- temp = array[ind0];
- array[ind0] = array[ind1];
- array[ind1] = array[ind2];
- array[ind2] = temp;
-
- return;
- }
-
-
- /* ========================================================================= */
- void four_cycle(int array[], int ind0, int ind1, int ind2, int ind3)
- /* ------------------------------------------------------------------------- */
-
- {
- int temp;
-
-
- temp = array[ind0];
- array[ind0] = array[ind1];
- array[ind1] = array[ind2];
- array[ind2] = array[ind3];
- array[ind3] = temp;
-
- return;
- }
-
-
- /* ========================================================================= */
- void print_cube(Cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- 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",
- center_cubie_str[p_cube->centers[0]], center_cubie_str[p_cube->centers[1]],
- center_cubie_str[p_cube->centers[2]], center_cubie_str[p_cube->centers[3]],
- center_cubie_str[p_cube->centers[4]], center_cubie_str[p_cube->centers[5]],
- edge_cubie_str[p_cube->edges[0]], edge_cubie_str[p_cube->edges[1]],
- edge_cubie_str[p_cube->edges[2]], edge_cubie_str[p_cube->edges[3]],
- edge_cubie_str[p_cube->edges[4]], edge_cubie_str[p_cube->edges[5]],
- edge_cubie_str[p_cube->edges[6]], edge_cubie_str[p_cube->edges[7]],
- edge_cubie_str[p_cube->edges[8]], edge_cubie_str[p_cube->edges[9]],
- edge_cubie_str[p_cube->edges[10]], edge_cubie_str[p_cube->edges[11]],
- corner_cubie_str[p_cube->corners[0]], corner_cubie_str[p_cube->corners[1]],
- corner_cubie_str[p_cube->corners[2]], corner_cubie_str[p_cube->corners[3]],
- corner_cubie_str[p_cube->corners[4]], corner_cubie_str[p_cube->corners[5]],
- corner_cubie_str[p_cube->corners[6]], corner_cubie_str[p_cube->corners[7]]);
-
- return;
- }
-
- /* ========================================================================= */
- void perm_n_init(int nn, int array_out[])
- /* ------------------------------------------------------------------------- */
-
- {
- int ii;
-
-
- for (ii = 0; ii < nn; ii++)
- array_out[ii] = ii;
-
- return;
- }
-
-
- /* ========================================================================= */
- void cube_init(Cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- perm_n_init(6, p_cube->centers);
- perm_n_init(24, p_cube->edges);
- perm_n_init(24, p_cube->corners);
-
- return;
- }
-
- /* ========================================================================= */
- int perm_n_check(int nn, int array_in[])
- /* ------------------------------------------------------------------------- */
-
- {
- int count[MAX_CHECK_PERM_N], ii;
-
-
- for (ii = 0; ii < nn; ii++)
- count[ii] = 0;
-
- for (ii = 0; ii < nn; ii++)
- {
- if ((array_in[ii] < 0) || (array_in[ii] >= nn))
- return 1;
-
- count[array_in[ii]]++;
- }
-
- for (ii = 0; ii < nn; ii++)
- if (count[ii] != 1)
- return 1;
-
- return 0;
- }
-
- /* ========================================================================= */
- int perm_n_parity(int nn, int array_in[])
- /* ------------------------------------------------------------------------- */
-
- {
- int temp_array[MAX_CHECK_PERM_N];
- int ii, jj, n_cycles;
-
-
- for (ii = 0; ii < nn; ii++)
- temp_array[ii] = 0;
-
- n_cycles = 0;
-
- for (ii = 0; ii < nn; ii++)
- if (temp_array[ii] == 0)
- {
- n_cycles++;
- jj = ii;
- while (temp_array[jj] == 0)
- {
- temp_array[jj] = 1;
- jj = array_in[jj];
- }
- }
-
- return (n_cycles + nn) % 2;
- }
-
-
-
- /* ========================================================================= */
- int centers_check(int array_in[])
- /* return -1 if invalid, 0 if even cube configuration, 1 for odd */
- /* ------------------------------------------------------------------------- */
-
- {
- int parity = 0;
- int i;
-
- int clone[6];
- for(i = 0; i < 6; i++)
- clone[i] = array_in[i];
-
- // put FACE_UP upwards
- for (i = 0; i<6; i++)
- if(clone[i] == FACE_U)
- break;
-
- switch(i) {
- case FACE_U:
- break;
- case FACE_F:
- four_cycle(clone, FACE_U, FACE_F, FACE_D, FACE_B);
- parity++;
- break;
- case FACE_L:
- four_cycle(clone, FACE_U, FACE_L, FACE_D, FACE_R);
- parity++;
- break;
- case FACE_R:
- four_cycle(clone, FACE_U, FACE_R, FACE_D, FACE_L);
- parity++;
- break;
- case FACE_B:
- four_cycle(clone, FACE_U, FACE_B, FACE_D, FACE_F);
- parity++;
- break;
- case FACE_D:
- two_cycle(clone, FACE_U, FACE_D);
- two_cycle(clone, FACE_F, FACE_B);
- break;
- case 6:
- return -1;
- }
-
- // now put FACE_FRONT in place
- for (i = 0; i<6; i++)
- if(clone[i] == FACE_F)
- break;
- switch(i) {
- case FACE_F:
- break;
- case FACE_L:
- four_cycle(clone, FACE_F, FACE_L, FACE_B, FACE_R);
- parity++;
- break;
- case FACE_R:
- four_cycle(clone, FACE_F, FACE_R, FACE_B, FACE_L);
- parity++;
- break;
- case FACE_B:
- two_cycle(clone, FACE_F, FACE_B);
- two_cycle(clone, FACE_L, FACE_R);
- break;
- case FACE_U: // this is not possible
- case FACE_D:
- case 6:
- return -1;
- }
-
- if(clone[FACE_R] != FACE_R || clone[FACE_L] != FACE_L
- || clone[FACE_B] != FACE_B || clone[FACE_D] != FACE_D)
- return -1;
-
- return parity & 1;
- }
-
- /* ========================================================================= */
- int string_to_cube(char string[], Cube *p_cube, int give_err_msg)
- /* ------------------------------------------------------------------------- */
-
- /* input: string[] */
-
- {
- char center_str[6][2], edge_str[12][3], corner_str[8][4];
- int center_arr[6], edge_arr[12], corner_arr[8];
- int ii, jj, twist, flip, edge_par, corner_par, center_par;
- int stat;
-
-
- stat = 0;
-
- 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",
- center_str[0], center_str[1], center_str[2],
- center_str[3], center_str[4], center_str[5],
- edge_str[0], edge_str[1], edge_str[2], edge_str[3],
- edge_str[4], edge_str[5], edge_str[6], edge_str[7],
- edge_str[8], edge_str[9], edge_str[10], edge_str[11],
- corner_str[0], corner_str[1], corner_str[2], corner_str[3],
- corner_str[4], corner_str[5], corner_str[6], corner_str[7]) < 20)
- {
- if (give_err_msg)
- printf("invalid input!\n");
- return 1;
- }
-
- for (ii = 0; ii < 6 ; ii++)
- {
- for (jj = 0; jj < 6; jj++)
- if(strcmp(center_str[ii], center_cubie_str[jj]) == 0)
- {
- p_cube->centers[ii] = jj;
- break;
- }
- if(jj == 6)
- {
- if (give_err_msg)
- printf("invalid center cubie: %s\n", center_str[ii]);
- stat = 1;
- }
- }
-
- for (ii = 0; ii < 12; ii++)
- {
- for (jj = 0; jj < 24; jj++)
- if (strcmp(edge_str[ii], edge_cubie_str[jj]) == 0)
- {
- p_cube->edges[ii] = jj;
- break;
- }
- if (jj == 24)
- {
- if (give_err_msg)
- printf("invalid edge cubie: %s\n", edge_str[ii]);
- stat = 1;
- }
- }
-
- for (ii = 0; ii < 8; ii++)
- {
- for (jj = 0; jj < 24; jj++)
- if (strcmp(corner_str[ii], corner_cubie_str[jj]) == 0)
- {
- p_cube->corners[ii] = jj;
- break;
- }
- if (jj == 24)
- {
- if (give_err_msg)
- printf("invalid corner cubie: %s\n", corner_str[ii]);
- stat = 1;
- }
- }
-
- if (stat)
- return stat;
-
- /* fill out the remaining oriented edges and corners */
-
- for (ii = 12; ii < 24; ii++)
- p_cube->edges[ii] = (12 + p_cube->edges[ii - 12]) % 24;
-
- for (ii = 8; ii < 24; ii++)
- p_cube->corners[ii] = (8 + p_cube->corners[ii - 8]) % 24;
-
- /* now check to see that it's a legal cube */
-
- center_par = centers_check(p_cube->centers);
- if (center_par == -1)
- {
- if (give_err_msg)
- printf("bad center cubies\n");
- stat = 1;
- }
-
- if (perm_n_check(24, p_cube->edges))
- {
- if (give_err_msg)
- printf("bad edge cubies\n");
- stat = 1;
- }
-
- if (perm_n_check(24, p_cube->corners))
- {
- if (give_err_msg)
- printf("bad corner cubies\n");
- stat = 1;
- }
-
- if (stat)
- return stat;
-
- flip = 0;
- for (ii = 0; ii < 12; ii++)
- flip += (p_cube->edges[ii] / 12);
-
- if ((flip % 2) != 0)
- {
- if (give_err_msg)
- printf("flip any edge cubie!\n");
- stat = 1;
- }
-
- twist = 0;
- for (ii = 0; ii < 8; ii++)
- twist += (p_cube->corners[ii] / 8);
-
- twist %= 3;
-
- if (twist != 0)
- {
- if (give_err_msg)
- printf("twist any corner cubie %sclockwise!\n",
- (twist == 1) ? "counter" : "");
- stat = 1;
- }
-
- for (ii = 0; ii < 12; ii++)
- edge_arr[ii] = p_cube->edges[ii] % 12;
-
- edge_par = perm_n_parity(12, edge_arr);
-
- for (ii = 0; ii < 8; ii++)
- corner_arr[ii] = p_cube->corners[ii] % 8;
-
- corner_par = perm_n_parity(8, corner_arr);
-
- if (((edge_par + corner_par + center_par) & 1) == 1)
- {
- if (give_err_msg)
- printf("swap any two edge cubies or any two corner cubies!\n");
- stat = 1;
- }
-
- return stat;
- }
-
-
- /* ========================================================================= */
- int user_enters_cube(Cube *p_cube)
- /* ------------------------------------------------------------------------- */
-
- {
- char line_str[256];
-
-
- printf("\nenter cube (Ctrl-D to exit):\n");
-
- line_str[0] = '\n';
-
- while (line_str[0] == '\n') /* ignore blank lines */
- {
- if (fgets(line_str, 256, stdin) == NULL)
- return -1;
-
- if (line_str[0] == '%') /* echo comments */
- {
- printf("%s", line_str);
- line_str[0] = '\n';
- }
- }
-
- return string_to_cube(line_str, p_cube, 1);
- }
-
- /* ========================================================================= */
- int compute_pixels_front(Cube *p_cube, int pixels[9])
- /* ------------------------------------------------------------------------- */
-
- {
- pixels[0] = corner_cubie_color[p_cube->corners[CORNER_FUL]];
- pixels[1] = edge_cubie_color[p_cube->edges[EDGE_FU]];
- pixels[2] = corner_cubie_color[p_cube->corners[CORNER_FRU]];
-
- pixels[3] = edge_cubie_color[p_cube->edges[EDGE_FL]];
- pixels[4] = p_cube->centers[FACE_F];
- pixels[5] = edge_cubie_color[p_cube->edges[EDGE_FR]];
-
- pixels[6] = corner_cubie_color[p_cube->corners[CORNER_FLD]];
- pixels[7] = edge_cubie_color[p_cube->edges[EDGE_FD]];
- pixels[8] = corner_cubie_color[p_cube->corners[CORNER_FDR]];
- }
-
-
- /* ========================================================================= */
- int compute_pixels_back(Cube *p_cube, int pixels[9])
- /* ------------------------------------------------------------------------- */
-
- {
- pixels[0] = corner_cubie_color[p_cube->corners[CORNER_BUR]];
- pixels[1] = edge_cubie_color[p_cube->edges[EDGE_BU]];
- pixels[2] = corner_cubie_color[p_cube->corners[CORNER_BLU]];
-
- pixels[3] = edge_cubie_color[p_cube->edges[EDGE_BR]];
- pixels[4] = p_cube->centers[FACE_B];
- pixels[5] = edge_cubie_color[p_cube->edges[EDGE_BL]];
-
- pixels[6] = corner_cubie_color[p_cube->corners[CORNER_BRD]];
- pixels[7] = edge_cubie_color[p_cube->edges[EDGE_BD]];
- pixels[8] = corner_cubie_color[p_cube->corners[CORNER_BDL]];
- }
-
- /* ========================================================================= */
- int main(void)
- /* ------------------------------------------------------------------------- */
-
- {
- Cube cube_struct;
- int stat;
- int i;
- int pixels[9];
-
- while (1)
- {
- stat = user_enters_cube(&cube_struct);
- if (stat != 0)
- break;
- printf("cube looks fine\n");
- compute_pixels_front(&cube_struct, pixels);
- for(i = 0; i<9; i++)
- printf("%d", pixels[i]);
- printf("\n");
- compute_pixels_back(&cube_struct, pixels);
- for(i = 0; i<9; i++)
- printf("%d", pixels[i]);
- printf("\n");
- }
- exit(EXIT_SUCCESS);
-
- return 0; /* haha */
- }
|