h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

cube.h (4044B)


      1 STATIC cube_t solvecube(void);
      2 STATIC cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]);
      3 STATIC bool isconsistent(cube_t);
      4 STATIC bool issolvable(cube_t);
      5 STATIC bool issolved(cube_t);
      6 STATIC bool iserror(cube_t);
      7 STATIC void getcube_fix(int64_t *, int64_t *, int64_t *, int64_t *);
      8 STATIC cube_t getcube(int64_t, int64_t, int64_t, int64_t);
      9 
     10 /* This is used only in tests, use SOLVED_CUBE directly everywhere else */
     11 STATIC cube_t
     12 solvedcube(void)
     13 {
     14 	return SOLVED_CUBE;
     15 }
     16 
     17 STATIC cube_t
     18 cubefromarray(uint8_t c[static 8], uint8_t e[static 12])
     19 {
     20 	return STATIC_CUBE(
     21 	    c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7],
     22 	    e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7],
     23 	    e[8], e[9], e[10], e[11]);
     24 }
     25 
     26 STATIC bool
     27 isconsistent(cube_t cube)
     28 {
     29 	uint8_t i, p, e, piece, corner[8], edge[12];
     30 	bool found[12];
     31 
     32 	pieces(&cube, corner, edge);
     33 
     34 	for (i = 0; i < 12; i++)
     35 		found[i] = false;
     36 	for (i = 0; i < 12; i++) {
     37 		piece = edge[i];
     38 		p = piece & PBITS;
     39 		e = piece & EOBIT;
     40 		if (p >= 12)
     41 			goto inconsistent_ep;
     42 		if (e != 0 && e != EOBIT)
     43 			goto inconsistent_eo;
     44 		found[p] = true;
     45 	}
     46 	for (i = 0; i < 12; i++)
     47 		if (!found[i])
     48 			goto inconsistent_ep;
     49 
     50 	for (i = 0; i < 8; i++)
     51 		found[i] = false;
     52 	for (i = 0; i < 8; i++) {
     53 		piece = corner[i];
     54 		p = piece & PBITS;
     55 		e = piece & COBITS;
     56 		if (p >= 8)
     57 			goto inconsistent_cp;
     58 		if (e != 0 && e != CTWIST_CW && e != CTWIST_CCW)
     59 			goto inconsistent_co;
     60 		found[p] = true;
     61 	}
     62 	for (i = 0; i < 8; i++)
     63 		if (!found[i])
     64 			goto inconsistent_co;
     65 
     66 	return true;
     67 
     68 inconsistent_ep:
     69 	LOG("Inconsistent EP\n");
     70 	return false;
     71 inconsistent_cp:
     72 	LOG("Inconsistent CP\n");
     73 	return false;
     74 inconsistent_eo:
     75 	LOG("Inconsistent EO\n");
     76 	return false;
     77 inconsistent_co:
     78 	LOG("Inconsistent CO\n");
     79 	return false;
     80 }
     81 
     82 STATIC bool
     83 issolvable(cube_t cube)
     84 {
     85 	uint8_t i, eo, co, piece, edge[12], corner[8], ep[12], cp[8];
     86 
     87 	DBG_ASSERT(isconsistent(cube), false,
     88 	    "issolvable: cube is inconsistent\n");
     89 
     90 	pieces(&cube, corner, edge);
     91 	for (i = 0; i < 12; i++)
     92 		ep[i] = edge[i] & PBITS;
     93 	for (i = 0; i < 8; i++)
     94 		cp[i] = corner[i] & PBITS;
     95 
     96 	if (permsign(ep, 12) != permsign(cp, 8))
     97 		goto issolvable_parity;
     98 
     99 	eo = 0;
    100 	for (i = 0; i < 12; i++) {
    101 		piece = edge[i];
    102 		eo += (piece & EOBIT) >> EOSHIFT;
    103 	}
    104 	if (eo % 2 != 0)
    105 		goto issolvable_eo;
    106 
    107 	co = 0;
    108 	for (i = 0; i < 8; i++) {
    109 		piece = corner[i];
    110 		co += (piece & COBITS) >> COSHIFT;
    111 	}
    112 	if (co % 3 != 0)
    113 		goto issolvable_co;
    114 
    115 	return true;
    116 
    117 issolvable_parity:
    118 	LOG("EP and CP parities are different\n");
    119 	return false;
    120 issolvable_eo:
    121 	LOG("Odd number of flipped edges\n");
    122 	return false;
    123 issolvable_co:
    124 	LOG("Sum of corner orientation is not multiple of 3\n");
    125 	return false;
    126 }
    127 
    128 bool
    129 issolved(cube_t cube)
    130 {
    131 	return equal(cube, SOLVED_CUBE);
    132 }
    133 
    134 bool
    135 iserror(cube_t cube)
    136 {
    137 	return equal(cube, ZERO_CUBE);
    138 }
    139 
    140 STATIC void
    141 getcube_fix(int64_t *ep, int64_t *eo, int64_t *cp, int64_t *co)
    142 {
    143 	uint8_t e[12], c[8], coarr[8];
    144 
    145         *ep = (*ep % FACT_12 + FACT_12) % FACT_12;
    146 	*eo = (*eo % POW_2_11 + POW_2_11) % POW_2_11;
    147 	*cp = (*cp % FACT_8 + FACT_8) % FACT_8;
    148 	*co = (*cp % POW_3_7 + POW_3_7) % POW_3_7;
    149 
    150 	indextoperm(*ep, 12, e);
    151 	indextoperm(*cp, 8, c);
    152 	if (permsign(e, 12) != permsign(c, 8)) {
    153 		SWAP(c[0], c[1]);
    154 		*cp = permtoindex(c, 8);
    155 
    156 		sumzerotodigits(*co, 8, 3, coarr);
    157 		SWAP(coarr[0], coarr[1]);
    158 		*co = digitstosumzero(coarr, 8, 3);
    159 	}
    160 }
    161 
    162 STATIC cube_t
    163 getcube(int64_t ep, int64_t eo, int64_t cp, int64_t co)
    164 {
    165 	uint8_t i, earr[12], carr[8], eoarr[12], coarr[8];
    166 
    167 	sumzerotodigits(eo, 12, 2, eoarr);
    168 	DBG_ASSERT(eoarr[0] != UINT8_ERROR, ZERO_CUBE, "Error making EO");
    169 	indextoperm(ep, 12, earr);
    170 	DBG_ASSERT(earr[0] != UINT8_ERROR, ZERO_CUBE, "Error making EP");
    171 	for (i = 0; i < 12; i++)
    172 		earr[i] |= eoarr[i] << EOSHIFT;
    173 
    174 	sumzerotodigits(co, 8, 3, coarr);
    175 	DBG_ASSERT(coarr[0] != UINT8_ERROR, ZERO_CUBE, "Error making CO");
    176 	indextoperm(cp, 8, carr);
    177 	DBG_ASSERT(carr[0] != UINT8_ERROR, ZERO_CUBE, "Error making CP");
    178 	for (i = 0; i < 8; i++)
    179 		carr[i] |= coarr[i] << COSHIFT;
    180 
    181 	return cubefromarray(carr, earr);
    182 }