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

io_cube.h (6497B)


      1 STATIC uint8_t readco(const char *);
      2 STATIC uint8_t readcp(const char *);
      3 STATIC uint8_t readeo(const char *);
      4 STATIC uint8_t readep(const char *);
      5 STATIC cube_t readcube_B32(const char *);
      6 STATIC cube_t readcube_H48(const char *);
      7 STATIC uint8_t readpiece_LST(const char **);
      8 STATIC cube_t readcube_LST(const char *);
      9 
     10 STATIC int writepiece_LST(uint8_t, char *);
     11 STATIC void writecube_B32(cube_t, char *);
     12 STATIC void writecube_H48(cube_t, char *);
     13 STATIC void writecube_LST(cube_t, char *);
     14 
     15 STATIC uint8_t b32toedge(char);
     16 STATIC uint8_t b32tocorner(char);
     17 STATIC char edgetob32(uint8_t);
     18 STATIC char cornertob32(uint8_t);
     19 
     20 STATIC struct {
     21 	const char *name;
     22 	cube_t (*read)(const char *);
     23 	void (*write)(cube_t, char *);
     24 } ioformat[] =
     25 {
     26 	{ .name = "B32", .read = readcube_B32, .write = writecube_B32 },
     27 	{ .name = "LST", .read = readcube_LST, .write = writecube_LST },
     28 	{ .name = "H48", .read = readcube_H48, .write = writecube_H48 },
     29 	{ .name = "NONE", .read = NULL, .write = NULL },
     30 };
     31 
     32 cube_t
     33 readcube(const char *format, const char *buf)
     34 {
     35 	int i;
     36 
     37 	for (i = 0; ioformat[i].read != NULL; i++)
     38 		if (!strcmp(format, ioformat[i].name))
     39 			return ioformat[i].read(buf);
     40 
     41 	LOG("Cannot read cube in the given format\n");
     42 	return ZERO_CUBE;
     43 }
     44 
     45 void
     46 writecube(const char *format, cube_t cube, char *buf)
     47 {
     48 	char *errormsg;
     49 	size_t len;
     50 
     51 	if (!isconsistent(cube)) {
     52 		errormsg = "ERROR: inconsistent";
     53 		goto writecube_error;
     54 	}
     55 
     56 	int i;
     57 
     58 	for (i = 0; ioformat[i].write != NULL; i++) {
     59 		if (!strcmp(format, ioformat[i].name)) {
     60 			ioformat[i].write(cube, buf);
     61 			return;
     62 		}
     63 	}
     64 
     65 	errormsg = "ERROR: format";
     66 
     67 writecube_error:
     68 	LOG("writecube error, see stdout for details\n");
     69 	len = strlen(errormsg);
     70 	memcpy(buf, errormsg, len);
     71 	buf[len] = '\n';
     72 	buf[len+1] = '\0';
     73 }
     74 
     75 STATIC uint8_t
     76 readco(const char *str)
     77 {
     78 	if (*str == '0')
     79 		return 0;
     80 	if (*str == '1')
     81 		return CTWIST_CW;
     82 	if (*str == '2')
     83 		return CTWIST_CCW;
     84 
     85 	LOG("Error reading CO\n");
     86 	return UINT8_ERROR;
     87 }
     88 
     89 STATIC uint8_t
     90 readcp(const char *str)
     91 {
     92 	uint8_t c;
     93 
     94 	for (c = 0; c < 8; c++)
     95 		if (!strncmp(str, cornerstr[c], 3) ||
     96 		    !strncmp(str, cornerstralt[c], 3))
     97 			return c;
     98 
     99 	LOG("Error reading CP\n");
    100 	return UINT8_ERROR;
    101 }
    102 
    103 STATIC uint8_t
    104 readeo(const char *str)
    105 {
    106 	if (*str == '0')
    107 		return 0;
    108 	if (*str == '1')
    109 		return EFLIP;
    110 
    111 	LOG("Error reading EO\n");
    112 	return UINT8_ERROR;
    113 }
    114 
    115 STATIC uint8_t
    116 readep(const char *str)
    117 {
    118 	uint8_t e;
    119 
    120 	for (e = 0; e < 12; e++)
    121 		if (!strncmp(str, edgestr[e], 2))
    122 			return e;
    123 
    124 	LOG("Error reading EP\n");
    125 	return UINT8_ERROR;
    126 }
    127 
    128 STATIC cube_t
    129 readcube_B32(const char *buf)
    130 {
    131 	int i;
    132 	uint8_t c[8], e[12];
    133 
    134 	for (i = 0; i < 8; i++) {
    135 		c[i] = b32tocorner(buf[i]);
    136 		DBG_ASSERT(c[i] < 255, ZERO_CUBE,
    137 		    "Error reading B32 corner %d (char %d)\n", i, i);
    138 	}
    139 
    140 	for (i = 0; i < 12; i++) {
    141 		e[i] = b32toedge(buf[i+9]);
    142 		DBG_ASSERT(e[i] < 255, ZERO_CUBE,
    143 		    "Error reading B32 edge %d (char %d)\n", i, i+9);
    144 	}
    145 
    146 	return cubefromarray(c, e);
    147 }
    148 
    149 STATIC cube_t
    150 readcube_H48(const char *buf)
    151 {
    152 	int i;
    153 	uint8_t piece, orient, c[8], e[12];
    154 	const char *b;
    155 	
    156 	b = buf;
    157 
    158 	for (i = 0; i < 12; i++) {
    159 		while (*b == ' ' || *b == '\t' || *b == '\n')
    160 			b++;
    161 		if ((piece = readep(b)) == UINT8_ERROR)
    162 			return ZERO_CUBE;
    163 		b += 2;
    164 		if ((orient = readeo(b)) == UINT8_ERROR)
    165 			return ZERO_CUBE;
    166 		b++;
    167 		e[i] = piece | orient;
    168 	}
    169 	for (i = 0; i < 8; i++) {
    170 		while (*b == ' ' || *b == '\t' || *b == '\n')
    171 			b++;
    172 		if ((piece = readcp(b)) == UINT8_ERROR)
    173 			return ZERO_CUBE;
    174 		b += 3;
    175 		if ((orient = readco(b)) == UINT8_ERROR)
    176 			return ZERO_CUBE;
    177 		b++;
    178 		c[i] = piece | orient;
    179 	}
    180 
    181 	return cubefromarray(c, e);
    182 }
    183 
    184 STATIC uint8_t
    185 readpiece_LST(const char **b)
    186 {
    187 	uint8_t ret;
    188 	bool read;
    189 
    190 	while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n')
    191 		(*b)++;
    192 
    193 	for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) {
    194 		read = true;
    195 		ret = ret * 10 + (**b) - '0';
    196 	}
    197 
    198 	return read ? ret : UINT8_ERROR;
    199 }
    200 
    201 STATIC cube_t
    202 readcube_LST(const char *buf)
    203 {
    204 	int i;
    205 	uint8_t c[8], e[12];
    206 
    207 	for (i = 0; i < 8; i++)
    208 		c[i] = readpiece_LST(&buf);
    209 
    210 	for (i = 0; i < 12; i++)
    211 		e[i] = readpiece_LST(&buf);
    212 
    213 	return cubefromarray(c, e);
    214 }
    215 
    216 STATIC int
    217 writepiece_LST(uint8_t piece, char *buf)
    218 {
    219 	char digits[3];
    220 	int i, len;
    221 
    222 	len = 0;
    223 	while (piece != 0) {
    224 		digits[len++] = (piece % 10) + '0';
    225 		piece /= 10;
    226 	}
    227 
    228 	if (len == 0)
    229 		digits[len++] = '0';
    230 
    231 	for (i = 0; i < len; i++)
    232 		buf[i] = digits[len-i-1];
    233 
    234 	buf[len] = ',';
    235 	buf[len+1] = ' ';
    236 
    237 	return len+2;
    238 }
    239 
    240 STATIC void
    241 writecube_B32(cube_t cube, char *buf)
    242 {
    243 	int i;
    244 	uint8_t corner[8], edge[12];
    245 
    246 	pieces(&cube, corner, edge);
    247 
    248 	for (i = 0; i < 8; i++)
    249 		buf[i] = cornertob32(corner[i]);
    250 
    251 	buf[8] = '=';
    252 
    253 	for (i = 0; i < 12; i++)
    254 		buf[i+9] = edgetob32(edge[i]);
    255 
    256 	buf[21] = '\0';
    257 }
    258 
    259 STATIC void
    260 writecube_H48(cube_t cube, char *buf)
    261 {
    262 	uint8_t piece, perm, orient, corner[8], edge[12];
    263 	int i;
    264 
    265 	pieces(&cube, corner, edge);
    266 
    267 	for (i = 0; i < 12; i++) {
    268 		piece = edge[i];
    269 		perm = piece & PBITS;
    270 		orient = (piece & EOBIT) >> EOSHIFT;
    271 		buf[4*i    ] = edgestr[perm][0];
    272 		buf[4*i + 1] = edgestr[perm][1];
    273 		buf[4*i + 2] = orient + '0';
    274 		buf[4*i + 3] = ' ';
    275 	}
    276 	for (i = 0; i < 8; i++) {
    277 		piece = corner[i];
    278 		perm = piece & PBITS;
    279 		orient = (piece & COBITS) >> COSHIFT;
    280 		buf[48 + 5*i    ] = cornerstr[perm][0];
    281 		buf[48 + 5*i + 1] = cornerstr[perm][1];
    282 		buf[48 + 5*i + 2] = cornerstr[perm][2];
    283 		buf[48 + 5*i + 3] = orient + '0';
    284 		buf[48 + 5*i + 4] = ' ';
    285 	}
    286 
    287 	buf[48+39] = '\0';
    288 }
    289 
    290 STATIC void
    291 writecube_LST(cube_t cube, char *buf)
    292 {
    293 	int i;
    294 	size_t ptr;
    295 	uint8_t piece, corner[8], edge[12];
    296 
    297 	ptr = 0;
    298 	pieces(&cube, corner, edge);
    299 
    300 	for (i = 0; i < 8; i++) {
    301 		piece = corner[i];
    302 		ptr += writepiece_LST(piece, buf + ptr);
    303 	}
    304 
    305 	for (i = 0; i < 12; i++) {
    306 		piece = edge[i];
    307 		ptr += writepiece_LST(piece, buf + ptr);
    308 	}
    309 
    310 	*(buf+ptr-2) = 0;
    311 }
    312 
    313 STATIC uint8_t
    314 b32toedge(char c)
    315 {
    316 	if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
    317 		return 255;
    318 
    319 	return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
    320 }
    321 
    322 STATIC uint8_t
    323 b32tocorner(char c) {
    324 	uint8_t val;
    325 
    326 	if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
    327 		return 255;
    328 
    329 	val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
    330 
    331 	return (val & 7) | ((val & 24) << 2);
    332 }
    333 
    334 STATIC char
    335 edgetob32(uint8_t edge)
    336 {
    337 	return edge < 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26);
    338 }
    339 
    340 STATIC char
    341 cornertob32(uint8_t corner)
    342 {
    343 	uint8_t val;
    344 
    345 	val = (corner & 7) | ((corner & 96) >> 2);
    346 
    347 	return val < 26 ? 'A' + (char)val : 'a' + (char)(val - 26);
    348 }