aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--experiments/cube.c (renamed from src/cube.c)0
-rw-r--r--experiments/cube.h27
-rw-r--r--src/array_cube.c712
-rw-r--r--src/cube.h42
-rw-r--r--test/00_basic/all.out3
-rw-r--r--test/00_basic/basic_tests.c27
-rw-r--r--test/01_io/io_tests.c2
-rw-r--r--test/02_move/move_tests.c2
-rw-r--r--test/03_inverse/00_solved.in1
-rw-r--r--test/03_inverse/00_solved.out1
-rw-r--r--test/03_inverse/01_scrambled.in1
-rw-r--r--test/03_inverse/01_scrambled.out1
-rw-r--r--test/03_inverse/inverse_tests.c27
-rwxr-xr-xtest/test.sh2
14 files changed, 830 insertions, 18 deletions
diff --git a/src/cube.c b/experiments/cube.c
index 4372b5e..4372b5e 100644
--- a/src/cube.c
+++ b/experiments/cube.c
diff --git a/experiments/cube.h b/experiments/cube.h
new file mode 100644
index 0000000..b916f96
--- /dev/null
+++ b/experiments/cube.h
@@ -0,0 +1,27 @@
1typedef enum {
2 U, U2, U3, D, D2, D3,
3 R, R2, R3, L, L2, L3,
4 F, F2, F3, B, B2, B3
5} move_t;
6typedef struct {
7 uint64_t e;
8 uint64_t c;
9} cube_t;
10
11extern cube_t solvedcube;
12extern cube_t errorcube;
13
14bool isconsistent(cube_t);
15bool issolved(cube_t);
16
17cube_t readcube(char *);
18void writecube(cube_t, char *);
19
20int readmoves(char *, move_t *);
21void writemoves(move_t *, int, char *);
22
23cube_t move(cube_t, move_t);
24
25/*
26cube_t inverse(cube_t);
27*/
diff --git a/src/array_cube.c b/src/array_cube.c
new file mode 100644
index 0000000..3445658
--- /dev/null
+++ b/src/array_cube.c
@@ -0,0 +1,712 @@
1/*
2In this implementation of the cube.h interface, the cube is represented
3by two arrays of 8-bit unsigned integers, one for centers and one for
4corners. The 4 leas-significant digits of each bit determine the piece,
5the other 4 are used for orientation or kept to 0.
6
7Edges:
8 xxxopppp (x = unused, o = orientation, p = piece)
9
10Corners:
11 xooxpppp (x = unused, o = orientation, p = piece)
12
13The two bits for CO are shifted to make it possible to perform mod 3
14operations (sum, inverse) using only addition and bitwise operators.
15See below for details.
16
17The third bit is needed because x+y+1 can exceed 4.
18*/
19
20#include <inttypes.h>
21#include <stdbool.h>
22#include <string.h>
23
24#ifdef DEBUG
25#include <stdio.h>
26#endif
27
28#include "cube.h"
29
30#define _c_ufr 0U
31#define _c_ubl 1U
32#define _c_dfl 2U
33#define _c_dbr 3U
34#define _c_ufl 4U
35#define _c_ubr 5U
36#define _c_dfr 6U
37#define _c_dbl 7U
38
39#define _e_uf 0U
40#define _e_ub 1U
41#define _e_db 2U
42#define _e_df 3U
43#define _e_ur 4U
44#define _e_ul 5U
45#define _e_dl 6U
46#define _e_dr 7U
47#define _e_fr 8U
48#define _e_fl 9U
49#define _e_bl 10U
50#define _e_br 11U
51
52#define _eoshift 4U
53#define _coshift 5U
54
55#define _pbits 0xFU
56#define _eobit 0x10U
57#define _cobits 0xF0U
58#define _cobits2 0x60U
59#define _ctwist_cw 0x20U
60#define _ctwist_ccw 0x40U
61#define _eflip 0x10U
62#define _error 0xFFU
63
64static char *cornerstr[] = {
65 [_c_ufr] = "UFR",
66 [_c_ubl] = "UBL",
67 [_c_dfl] = "DFL",
68 [_c_dbr] = "DBR",
69 [_c_ufl] = "UFL",
70 [_c_ubr] = "UBR",
71 [_c_dfr] = "DFR",
72 [_c_dbl] = "DBL"
73};
74
75static char *cornerstralt[] = {
76 [_c_ufr] = "URF",
77 [_c_ubl] = "ULB",
78 [_c_dfl] = "DLF",
79 [_c_dbr] = "DRB",
80 [_c_ufl] = "ULF",
81 [_c_ubr] = "URB",
82 [_c_dfr] = "DRF",
83 [_c_dbl] = "DLB"
84};
85
86static char *edgestr[] = {
87 [_e_uf] = "UF",
88 [_e_ub] = "UB",
89 [_e_db] = "DB",
90 [_e_df] = "DF",
91 [_e_ur] = "UR",
92 [_e_ul] = "UL",
93 [_e_dl] = "DL",
94 [_e_dr] = "DR",
95 [_e_fr] = "FR",
96 [_e_fl] = "FL",
97 [_e_bl] = "BL",
98 [_e_br] = "BR"
99};
100
101static char *movestr[] = {
102 [U] = "U",
103 [U2] = "U2",
104 [U3] = "U'",
105 [D] = "D",
106 [D2] = "D2",
107 [D3] = "D'",
108 [R] = "R",
109 [R2] = "R2",
110 [R3] = "R'",
111 [L] = "L",
112 [L2] = "L2",
113 [L3] = "L'",
114 [F] = "F",
115 [F2] = "F2",
116 [F3] = "F'",
117 [B] = "B",
118 [B2] = "B2",
119 [B3] = "B'",
120};
121
122cube_t solvedcube = {
123 .c = {
124 [_c_ufr] = _c_ufr,
125 [_c_ubl] = _c_ubl,
126 [_c_dfl] = _c_dfl,
127 [_c_dbr] = _c_dbr,
128 [_c_ufl] = _c_ufl,
129 [_c_ubr] = _c_ubr,
130 [_c_dfr] = _c_dfr,
131 [_c_dbl] = _c_dbl
132 },
133 .e = {
134 [_e_uf] = _e_uf,
135 [_e_ub] = _e_ub,
136 [_e_db] = _e_db,
137 [_e_df] = _e_df,
138 [_e_ur] = _e_ur,
139 [_e_ul] = _e_ul,
140 [_e_dl] = _e_dl,
141 [_e_dr] = _e_dr,
142 [_e_fr] = _e_fr,
143 [_e_fl] = _e_fl,
144 [_e_bl] = _e_bl,
145 [_e_br] = _e_br
146 }
147};
148
149static cube_t errorcube = { .e = {0}, .c = {0} };
150
151static uint8_t readco(char *);
152static uint8_t readcp(char *);
153static uint8_t readeo(char *);
154static uint8_t readep(char *);
155static uint8_t readmove(char);
156static uint8_t readmodifier(char);
157static int permsign(uint8_t *, int);
158static cube_t compose(cube_t, cube_t);
159
160static uint8_t
161readco(char *str)
162{
163 if (*str == '0')
164 return 0;
165 if (*str == '1')
166 return _ctwist_cw;
167 if (*str == '2')
168 return _ctwist_ccw;
169
170#ifdef DEBUG
171 fprintf(stderr, "Error reading CO\n");
172#endif
173 return _error;
174}
175
176static uint8_t
177readcp(char *str)
178{
179 uint8_t c;
180
181 for (c = 0; c < 8; c++)
182 if (!strncmp(str, cornerstr[c], 3) ||
183 !strncmp(str, cornerstralt[c], 3))
184 return c;
185
186#ifdef DEBUG
187 fprintf(stderr, "Error reading CP\n");
188#endif
189 return _error;
190}
191
192static uint8_t
193readeo(char *str)
194{
195 if (*str == '0')
196 return 0;
197 if (*str == '1')
198 return _eflip;
199
200#ifdef DEBUG
201 fprintf(stderr, "Error reading EO\n");
202#endif
203 return _error;
204}
205
206static uint8_t
207readep(char *str)
208{
209 uint8_t e;
210
211 for (e = 0; e < 12; e++)
212 if (!strncmp(str, edgestr[e], 2))
213 return e;
214
215#ifdef DEBUG
216 fprintf(stderr, "Error reading EP\n");
217#endif
218 return _error;
219}
220
221cube_t
222readcube(char *buf)
223{
224 int i;
225 uint8_t piece, orient;
226 cube_t ret = {0};
227 char *b = buf;
228
229 for (i = 0; i < 12; i++) {
230 while (*b == ' ' || *b == '\t' || *b == '\n')
231 b++;
232 if ((piece = readep(b)) == _error)
233 goto readcube_error;
234 b += 2;
235 if ((orient = readeo(b)) == _error)
236 goto readcube_error;
237 b++;
238 ret.e[i] = piece | orient;
239 }
240 for (i = 0; i < 8; i++) {
241 while (*b == ' ' || *b == '\t' || *b == '\n')
242 b++;
243 if ((piece = readcp(b)) == _error)
244 goto readcube_error;
245 b += 3;
246 if ((orient = readco(b)) == _error)
247 goto readcube_error;
248 b++;
249 ret.c[i] = piece | orient;
250 }
251
252 return ret;
253
254readcube_error:
255#ifdef DEBUG
256 fprintf(stderr, "readcube error\n");
257#endif
258 return errorcube;
259}
260
261void
262writecube(cube_t cube, char *buf)
263{
264 char *errormsg;
265 uint8_t piece, orient;
266 size_t len;
267 int i;
268
269 if (!isconsistent(cube)) {
270 errormsg = "ERROR: cannot write inconsistent cube";
271 goto writecube_error;
272 }
273
274 for (i = 0; i < 12; i++) {
275 piece = cube.e[i] & _pbits;
276 orient = (cube.e[i] & _eobit) >> _eoshift;
277 buf[4*i ] = edgestr[piece][0];
278 buf[4*i + 1] = edgestr[piece][1];
279 buf[4*i + 2] = orient + '0';
280 buf[4*i + 3] = ' ';
281 }
282 for (i = 0; i < 8; i++) {
283 piece = cube.c[i] & _pbits;
284 orient = (cube.c[i] & _cobits) >> _coshift;
285 buf[48 + 5*i ] = cornerstr[piece][0];
286 buf[48 + 5*i + 1] = cornerstr[piece][1];
287 buf[48 + 5*i + 2] = cornerstr[piece][2];
288 buf[48 + 5*i + 3] = orient + '0';
289 buf[48 + 5*i + 4] = ' ';
290 }
291
292 buf[48+39] = '\0';
293
294 return;
295
296writecube_error:
297#ifdef DEBUG
298 fprintf(stderr, "writecube error, see stdout for details\n");
299#endif
300 len = strlen(errormsg);
301 memcpy(buf, errormsg, len);
302 buf[len] = '\n';
303 buf[len+1] = '\0';
304}
305
306
307static uint8_t
308readmove(char c)
309{
310 switch (c) {
311 case 'U':
312 return U;
313 case 'D':
314 return D;
315 case 'R':
316 return R;
317 case 'L':
318 return L;
319 case 'F':
320 return F;
321 case 'B':
322 return B;
323 default:
324 return _error;
325 }
326}
327
328static uint8_t
329readmodifier(char c)
330{
331 switch (c) {
332 case '1': /* Fallthrough */
333 case '2': /* Fallthrough */
334 case '3':
335 return c - '0' - 1;
336 case '\'':
337 return 2;
338 default:
339 return 0;
340 }
341}
342
343int
344readmoves(char *buf, move_t *m)
345{
346 int n;
347 uint64_t r;
348 char *b;
349
350 for (b = buf, n = 0; *b != '\0'; b++) {
351 while (*b == ' ' || *b == '\t' || *b == '\n')
352 b++;
353 if (*b == '\0')
354 return n;
355 if ((r = readmove(*b)) == _error)
356 goto readmoves_error;
357 m[n] = (move_t)r;
358 if ((r = readmodifier(*(b+1))) != 0) {
359 b++;
360 m[n] += r;
361 }
362 n++;
363 }
364
365 return n;
366
367readmoves_error:
368#ifdef DEBUG
369 fprintf(stderr, "readmoves error\n");
370#endif
371 return -1;
372}
373
374void
375writemoves(move_t *m, int n, char *buf)
376{
377 int i;
378 size_t len;
379 char *b, *s;
380
381 for (i = 0, b = buf; i < n; i++, b++) {
382 s = movestr[m[i]];
383 len = strlen(s);
384 memcpy(b, s, len);
385 b += len;
386 *b = ' ';
387 }
388 *b = '\0';
389}
390
391
392static int
393permsign(uint8_t *a, int n)
394{
395 int i, j;
396 uint8_t ret = 0;
397
398 for (i = 0; i < n; i++)
399 for (j = i+1; j < n; j++)
400 ret += (a[i] & _pbits) > (a[j] & _pbits) ? 1 : 0;
401
402 return ret % 2;
403}
404
405bool
406isconsistent(cube_t cube)
407{
408 int8_t p, psum, eosum, co, cosum;
409 bool found[12];
410 int i;
411
412 psum = 0;
413 for (i = 0; i < 12; i++)
414 found[i] = false;
415 for (i = 0; i < 12; i++) {
416 p = cube.e[i] & _pbits;
417 if (p >= 12)
418 goto inconsistent_ep;
419 found[p] = true;
420 }
421 for (i = 0; i < 12; i++)
422 if (!found[i])
423 goto inconsistent_ep;
424 psum = permsign(cube.e, 12);
425
426 for (i = 0; i < 8; i++)
427 found[i] = false;
428 for (i = 0; i < 8; i++) {
429 p = cube.c[i] & _pbits;
430 if (p >= 8)
431 goto inconsistent_cp;
432 found[p] = true;
433 }
434 for (i = 0; i < 8; i++)
435 if (!found[i])
436 goto inconsistent_cp;
437 psum += permsign(cube.c, 8);
438
439 if (psum % 2 != 0)
440 goto inconsistent_parity;
441
442 eosum = 0;
443 for (i = 0; i < 12; i++)
444 eosum += (cube.e[i] & _eobit) >> _eoshift;
445 if (eosum % 2 != 0)
446 goto inconsistent_eo;
447
448 cosum = 0;
449 for (i = 0; i < 8; i++) {
450 co = (cube.c[i] & _cobits) >> _coshift;
451 if (co > 2)
452 goto inconsistent_co;
453 cosum += co;
454 }
455 if (cosum % 3 != 0)
456 goto inconsistent_co;
457
458 return true;
459
460inconsistent_ep:
461#ifdef DEBUG
462 fprintf(stderr, "Inconsistent EP\n");
463#endif
464 goto inconsistent_return;
465inconsistent_cp:
466#ifdef DEBUG
467 fprintf(stderr, "Inconsistent CP\n");
468#endif
469 goto inconsistent_return;
470inconsistent_parity:
471#ifdef DEBUG
472 fprintf(stderr, "Inconsistent parity\n");
473#endif
474 goto inconsistent_return;
475inconsistent_eo:
476#ifdef DEBUG
477 fprintf(stderr, "Inconsistent EO\n");
478#endif
479 goto inconsistent_return;
480inconsistent_co:
481#ifdef DEBUG
482 fprintf(stderr, "Inconsistent CO\n");
483#endif
484 goto inconsistent_return;
485inconsistent_return:
486 return false;
487}
488
489bool
490equal(cube_t cube1, cube_t cube2)
491{
492 uint8_t i;
493
494 for (i = 0; i < 12; i++)
495 if (cube1.e[i] != cube2.e[i])
496 return false;
497
498 for (i = 0; i < 8; i++)
499 if (cube1.c[i] != cube2.c[i])
500 return false;
501
502 return true;
503}
504
505bool
506issolved(cube_t cube)
507{
508 return equal(cube, solvedcube);
509}
510
511bool
512iserror(cube_t cube)
513{
514 return equal(cube, errorcube);
515}
516
517cube_t
518move(cube_t c, move_t m)
519{
520 cube_t ret;
521 uint8_t aux, auy, auz;
522
523#ifdef DEBUG
524 if (!isconsistent(c))
525 goto move_inconsistent;
526#endif
527
528#define PERM4(r, i, j, k, l) \
529 aux = r[i]; \
530 r[i] = r[l]; \
531 r[l] = r[k]; \
532 r[k] = r[j]; \
533 r[j] = aux;
534#define PERM22(r, i, j, k, l) \
535 aux = r[i]; \
536 r[i] = r[j]; \
537 r[j] = aux; \
538 aux = r[k]; \
539 r[k] = r[l]; \
540 r[l] = aux;
541#define CO(a, b) \
542 aux = (a & _cobits) + (b & _cobits); \
543 auy = (aux + _ctwist_cw) >> 2U; \
544 auz = (aux + auy) & _cobits2; \
545 a = (a & _pbits) | auz;
546#define CO4(r, i, j, k, l) \
547 CO(r[i], _ctwist_cw) \
548 CO(r[j], _ctwist_cw) \
549 CO(r[k], _ctwist_ccw) \
550 CO(r[l], _ctwist_ccw)
551#define EO4(r, i, j, k, l) \
552 r[i] ^= _eobit; \
553 r[j] ^= _eobit; \
554 r[k] ^= _eobit; \
555 r[l] ^= _eobit;
556
557 ret = c;
558
559 switch (m) {
560 case U:
561 PERM4(ret.e, _e_uf, _e_ul, _e_ub, _e_ur)
562 PERM4(ret.c, _c_ufr, _c_ufl, _c_ubl, _c_ubr)
563
564 return ret;
565 case U2:
566 PERM22(ret.e, _e_uf, _e_ub, _e_ul, _e_ur)
567 PERM22(ret.c, _c_ufr, _c_ubl, _c_ufl, _c_ubr)
568
569 return ret;
570 case U3:
571 PERM4(ret.e, _e_uf, _e_ur, _e_ub, _e_ul)
572 PERM4(ret.c, _c_ufr, _c_ubr, _c_ubl, _c_ufl)
573
574 return ret;
575 case D:
576 PERM4(ret.e, _e_df, _e_dr, _e_db, _e_dl)
577 PERM4(ret.c, _c_dfr, _c_dbr, _c_dbl, _c_dfl)
578
579 return ret;
580 case D2:
581 PERM22(ret.e, _e_df, _e_db, _e_dr, _e_dl)
582 PERM22(ret.c, _c_dfr, _c_dbl, _c_dbr, _c_dfl)
583
584 return ret;
585 case D3:
586 PERM4(ret.e, _e_df, _e_dl, _e_db, _e_dr)
587 PERM4(ret.c, _c_dfr, _c_dfl, _c_dbl, _c_dbr)
588
589 return ret;
590 case R:
591 PERM4(ret.e, _e_ur, _e_br, _e_dr, _e_fr)
592 PERM4(ret.c, _c_ufr, _c_ubr, _c_dbr, _c_dfr)
593
594 CO4(ret.c, _c_ubr, _c_dfr, _c_ufr, _c_dbr)
595
596 return ret;
597 case R2:
598 PERM22(ret.e, _e_ur, _e_dr, _e_fr, _e_br)
599 PERM22(ret.c, _c_ufr, _c_dbr, _c_ubr, _c_dfr)
600
601 return ret;
602 case R3:
603 PERM4(ret.e, _e_ur, _e_fr, _e_dr, _e_br)
604 PERM4(ret.c, _c_ufr, _c_dfr, _c_dbr, _c_ubr)
605
606 CO4(ret.c, _c_ubr, _c_dfr, _c_ufr, _c_dbr)
607
608 return ret;
609 case L:
610 PERM4(ret.e, _e_ul, _e_fl, _e_dl, _e_bl)
611 PERM4(ret.c, _c_ufl, _c_dfl, _c_dbl, _c_ubl)
612
613 CO4(ret.c, _c_ufl, _c_dbl, _c_dfl, _c_ubl)
614
615 return ret;
616 case L2:
617 PERM22(ret.e, _e_ul, _e_dl, _e_fl, _e_bl)
618 PERM22(ret.c, _c_ufl, _c_dbl, _c_ubl, _c_dfl)
619
620 return ret;
621 case L3:
622 PERM4(ret.e, _e_ul, _e_bl, _e_dl, _e_fl)
623 PERM4(ret.c, _c_ufl, _c_ubl, _c_dbl, _c_dfl)
624
625 CO4(ret.c, _c_ufl, _c_dbl, _c_dfl, _c_ubl)
626
627 return ret;
628 case F:
629 PERM4(ret.e, _e_uf, _e_fr, _e_df, _e_fl)
630 PERM4(ret.c, _c_ufr, _c_dfr, _c_dfl, _c_ufl)
631
632 EO4(ret.e, _e_uf, _e_fr, _e_df, _e_fl)
633 CO4(ret.c, _c_ufr, _c_dfl, _c_dfr, _c_ufl)
634
635 return ret;
636 case F2:
637 PERM22(ret.e, _e_uf, _e_df, _e_fr, _e_fl)
638 PERM22(ret.c, _c_ufr, _c_dfl, _c_ufl, _c_dfr)
639
640 return ret;
641 case F3:
642 PERM4(ret.e, _e_uf, _e_fl, _e_df, _e_fr)
643 PERM4(ret.c, _c_ufr, _c_ufl, _c_dfl, _c_dfr)
644
645 EO4(ret.e, _e_uf, _e_fr, _e_df, _e_fl)
646 CO4(ret.c, _c_ufr, _c_dfl, _c_dfr, _c_ufl)
647
648 return ret;
649 case B:
650 PERM4(ret.e, _e_ub, _e_bl, _e_db, _e_br)
651 PERM4(ret.c, _c_ubr, _c_ubl, _c_dbl, _c_dbr)
652
653 EO4(ret.e, _e_ub, _e_br, _e_db, _e_bl)
654 CO4(ret.c, _c_ubl, _c_dbr, _c_dbl, _c_ubr)
655
656 return ret;
657 case B2:
658 PERM22(ret.e, _e_ub, _e_db, _e_br, _e_bl)
659 PERM22(ret.c, _c_ubr, _c_dbl, _c_ubl, _c_dbr)
660
661 return ret;
662 case B3:
663 PERM4(ret.e, _e_ub, _e_br, _e_db, _e_bl)
664 PERM4(ret.c, _c_ubr, _c_dbr, _c_dbl, _c_ubl)
665
666 EO4(ret.e, _e_ub, _e_br, _e_db, _e_bl)
667 CO4(ret.c, _c_ubl, _c_dbr, _c_dbl, _c_ubr)
668
669 return ret;
670 default:
671 goto move_unknown;
672 }
673
674move_inconsistent:
675 fprintf(stderr, "move error, inconsistent cube\n");
676 goto move_error;
677move_unknown:
678 fprintf(stderr, "mover error, unknown move\n");
679 goto move_error;
680move_error:
681 return errorcube;
682}
683
684cube_t
685inverse(cube_t c)
686{
687 uint8_t i, piece, orien;
688 cube_t ret = {0};
689
690#ifdef DEBUG
691 if (!isconsistent(c))
692 goto inverse_inconsistent;
693#endif
694
695 for (i = 0; i < 12; i++) {
696 piece = c.e[i & _pbits];
697 orien = piece & _eobit;
698 ret.e[piece & _pbits] = i | orien;
699 }
700
701 for (i = 0; i < 8; i++) {
702 piece = c.c[i & _pbits];
703 orien = ((piece << 1) | (piece >> 1)) & _cobits2;
704 ret.c[piece & _pbits] = i | orien;
705 }
706
707 return ret;
708
709inverse_inconsistent:
710 fprintf(stderr, "inverse error, inconsistent cube\n");
711 return errorcube;
712}
diff --git a/src/cube.h b/src/cube.h
index b916f96..836bb5d 100644
--- a/src/cube.h
+++ b/src/cube.h
@@ -3,25 +3,51 @@ typedef enum {
3 R, R2, R3, L, L2, L3, 3 R, R2, R3, L, L2, L3,
4 F, F2, F3, B, B2, B3 4 F, F2, F3, B, B2, B3
5} move_t; 5} move_t;
6
6typedef struct { 7typedef struct {
7 uint64_t e; 8 uint8_t c[8];
8 uint64_t c; 9 uint8_t e[12];
9} cube_t; 10} cube_t;
10 11
11extern cube_t solvedcube; 12extern cube_t solvedcube;
12extern cube_t errorcube;
13 13
14bool isconsistent(cube_t); 14/*
15bool issolved(cube_t); 15The functions readcube() and writecube() use the following format.
16
17Each edge is represented by two letters denoting the sides it belongs to
18and one number denoting its orientation (0 oriented, 1 mis-oriented).
19Similarly, each corner is represented by three letters and a number
20(0 oriented, 1 twisted clockwise, 2 twisted counter-clockwise).
21Edge orientation is relative to the F / B axis, corner orientation is
22relative to the U / D axis.
23
24The pieces are ordered such that the solved cube looks like this:
25
26UF0 UB0 DB0 DF0 UR0 UL0 DL0 DR0 FR0 FL0 BL0 BR0
27UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0
28
29Whitespace (including newlines) between pieces is ignored when reading
30the cube, and a single whitespace character is added between pieces
31when writing.
32
33The cube after the moves R'U'F looks like this:
34
35FL1 BR0 DB0 UR1 UF0 UB0 DL0 FR0 UL1 DF1 BL0 DR0
36UBL1 DBR1 UFR2 DFR2 DFL2 UBL2 UFL2 DBL0
37
38More formats might be supported in the future.
39*/
16 40
17cube_t readcube(char *); 41cube_t readcube(char *);
18void writecube(cube_t, char *); 42void writecube(cube_t, char *);
19 43
44bool isconsistent(cube_t);
45bool equal(cube_t, cube_t);
46bool issolved(cube_t);
47bool iserror(cube_t);
48
20int readmoves(char *, move_t *); 49int readmoves(char *, move_t *);
21void writemoves(move_t *, int, char *); 50void writemoves(move_t *, int, char *);
22 51
23cube_t move(cube_t, move_t); 52cube_t move(cube_t, move_t);
24
25/*
26cube_t inverse(cube_t); 53cube_t inverse(cube_t);
27*/
diff --git a/test/00_basic/all.out b/test/00_basic/all.out
index d77f7f4..aad167e 100644
--- a/test/00_basic/all.out
+++ b/test/00_basic/all.out
@@ -2,3 +2,6 @@ Solved is consistent
2Solved is solved 2Solved is solved
3Zero is NOT consistent 3Zero is NOT consistent
4Zero is NOT solved 4Zero is NOT solved
5Solved and Solved are equal
6Solved and Zero are NOT equal
7Zero and Solved are NOT equal
diff --git a/test/00_basic/basic_tests.c b/test/00_basic/basic_tests.c
index cc2a55c..8c52941 100644
--- a/test/00_basic/basic_tests.c
+++ b/test/00_basic/basic_tests.c
@@ -4,16 +4,29 @@
4 4
5#include "../../src/cube.h" 5#include "../../src/cube.h"
6 6
7void
8check(cube_t cube, char *name)
9{
10 printf("%s is%s consistent\n", name, isconsistent(cube) ? "" : " NOT");
11 printf("%s is%s solved\n", name, issolved(cube) ? "" : " NOT");
12}
13
14void
15check2(cube_t cube1, char *name1, cube_t cube2, char *name2)
16{
17 printf("%s and %s are%s equal\n", name1, name2,
18 equal(cube1, cube2) ? "" : " NOT");
19}
20
7int main() { 21int main() {
8 cube_t z, s; 22 cube_t zero = (cube_t){0};
9 23
10 s = solvedcube; 24 check(solvedcube, "Solved");
11 printf("Solved %s consistent\n", isconsistent(s) ? "is" : "is NOT"); 25 check(zero, "Zero");
12 printf("Solved %s solved\n", issolved(s) ? "is" : "is NOT");
13 26
14 z = (cube_t){0}; 27 check2(solvedcube, "Solved", solvedcube, "Solved");
15 printf("Zero %s consistent\n", isconsistent(z) ? "is" : "is NOT"); 28 check2(solvedcube, "Solved", zero, "Zero");
16 printf("Zero %s solved\n", issolved(z) ? "is" : "is NOT"); 29 check2(zero, "Zero", solvedcube, "Solved");
17 30
18 return 0; 31 return 0;
19} 32}
diff --git a/test/01_io/io_tests.c b/test/01_io/io_tests.c
index 1ef99d0..42ef9b8 100644
--- a/test/01_io/io_tests.c
+++ b/test/01_io/io_tests.c
@@ -15,7 +15,7 @@ int main() {
15 15
16 cube = readcube(str); 16 cube = readcube(str);
17 17
18 if (cube.e == errorcube.e && cube.c == errorcube.c) { 18 if (iserror(cube)) {
19 printf("Error reading cube\n"); 19 printf("Error reading cube\n");
20 } else if (!isconsistent(cube)) { 20 } else if (!isconsistent(cube)) {
21 printf("Cube is inconsistent\n"); 21 printf("Cube is inconsistent\n");
diff --git a/test/02_move/move_tests.c b/test/02_move/move_tests.c
index 23fc45e..ac25de3 100644
--- a/test/02_move/move_tests.c
+++ b/test/02_move/move_tests.c
@@ -27,7 +27,7 @@ int main() {
27 for (i = 0; i < n; i++) 27 for (i = 0; i < n; i++)
28 cube = move(cube, moves[i]); 28 cube = move(cube, moves[i]);
29 29
30 if (cube.e == errorcube.e && cube.c == errorcube.c) { 30 if (iserror(cube)) {
31 printf("Error moving cube\n"); 31 printf("Error moving cube\n");
32 } else if (!isconsistent(cube)) { 32 } else if (!isconsistent(cube)) {
33 printf("Moved cube is inconsistent\n"); 33 printf("Moved cube is inconsistent\n");
diff --git a/test/03_inverse/00_solved.in b/test/03_inverse/00_solved.in
new file mode 100644
index 0000000..dff224d
--- /dev/null
+++ b/test/03_inverse/00_solved.in
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 UL0 DL0 DR0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0
diff --git a/test/03_inverse/00_solved.out b/test/03_inverse/00_solved.out
new file mode 100644
index 0000000..dff224d
--- /dev/null
+++ b/test/03_inverse/00_solved.out
@@ -0,0 +1 @@
UF0 UB0 DB0 DF0 UR0 UL0 DL0 DR0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0
diff --git a/test/03_inverse/01_scrambled.in b/test/03_inverse/01_scrambled.in
new file mode 100644
index 0000000..263213b
--- /dev/null
+++ b/test/03_inverse/01_scrambled.in
@@ -0,0 +1 @@
DR0 DB0 BL0 DF1 UB0 UR1 FR1 UF0 FL1 DL0 BR1 UL1 DBL2 DFL0 UBR1 DFR2 UFR0 DBR1 UBL0 UFL0
diff --git a/test/03_inverse/01_scrambled.out b/test/03_inverse/01_scrambled.out
new file mode 100644
index 0000000..25089c6
--- /dev/null
+++ b/test/03_inverse/01_scrambled.out
@@ -0,0 +1 @@
DR0 UR0 UB0 DF1 UL1 BR1 FL0 UF0 DL1 FR1 DB0 BL1 UFL0 DFR0 UBL0 UBR2 DBL0 DFL2 DBR1 UFR1
diff --git a/test/03_inverse/inverse_tests.c b/test/03_inverse/inverse_tests.c
new file mode 100644
index 0000000..5fab71a
--- /dev/null
+++ b/test/03_inverse/inverse_tests.c
@@ -0,0 +1,27 @@
1#include <stdbool.h>
2#include <stdint.h>
3#include <stdio.h>
4
5#include "../../src/cube.h"
6
7#define STRLENMAX 10000
8
9int main() {
10 char str[STRLENMAX];
11 cube_t cube, inv;
12
13 fgets(str, STRLENMAX, stdin);
14 cube = readcube(str);
15 inv = inverse(cube);
16
17 if (iserror(inv)) {
18 printf("Error inverting cube\n");
19 } else if (!isconsistent(inv)) {
20 printf("Inverted cube is inconsistent\n");
21 } else {
22 writecube(inv, str);
23 printf("%s\n", str);
24 }
25
26 return 0;
27}
diff --git a/test/test.sh b/test/test.sh
index d59270b..75be809 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -5,7 +5,7 @@ CC="cc -DDEBUG -std=c99 -pthread -pedantic -Wall -Wextra \
5if [ $(uname) != "OpenBSD" ]; then 5if [ $(uname) != "OpenBSD" ]; then
6 CC="$CC -fsanitize=address -fsanitize=undefined" 6 CC="$CC -fsanitize=address -fsanitize=undefined"
7fi 7fi
8SRC="src/cube.c" 8SRC="src/array_cube.c"
9TESTBIN="test/run" 9TESTBIN="test/run"
10TESTOUT="test/last.out" 10TESTOUT="test/last.out"
11TESTERR="test/last.err" 11TESTERR="test/last.err"

Generated with cgit - Back to sebastiano.tronto.net