diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2023-11-12 14:42:20 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2023-11-12 14:42:20 +0100 |
| commit | d0c592bdc3beb12074f085ab085dd90de9b8e643 (patch) | |
| tree | a7b31fc66c83400c95288edd7550d6b27cccecaa | |
| parent | 91afd406dca8dee4dfdb84ad025dd390f4e5a70c (diff) | |
| download | nissy-core-d0c592bdc3beb12074f085ab085dd90de9b8e643.tar.gz nissy-core-d0c592bdc3beb12074f085ab085dd90de9b8e643.zip | |
Simple solver: added tests, fixed
| -rw-r--r-- | TODO.txt | 11 | ||||
| -rw-r--r-- | cube.c | 111 | ||||
| -rw-r--r-- | cube.h | 5 | ||||
| -rw-r--r-- | test/060_solve_simple/01_U_U3.in | 8 | ||||
| -rw-r--r-- | test/060_solve_simple/01_U_U3.out | 1 | ||||
| -rw-r--r-- | test/060_solve_simple/02_MUMU_alloptimal.in | 8 | ||||
| -rw-r--r-- | test/060_solve_simple/02_MUMU_alloptimal.out | 4 | ||||
| -rw-r--r-- | test/060_solve_simple/solve_simple_tests.c | 58 |
8 files changed, 171 insertions, 35 deletions
| @@ -2,12 +2,14 @@ | |||
| 2 | 2 | ||
| 3 | See the sections below for details | 3 | See the sections below for details |
| 4 | 4 | ||
| 5 | * Tests for simple solver | 5 | * Tests for multisolve |
| 6 | * Extend cube and moves to include centers | 6 | * More tests for simple solver? |
| 7 | * Benchmarks? | ||
| 7 | * More complex optimal solvers, pruning tables | 8 | * More complex optimal solvers, pruning tables |
| 8 | * Benchmarks | 9 | * (More) benchmarks |
| 9 | * Multithreading (build-time option number of threads) | 10 | * Multithreading (build-time option number of threads) |
| 10 | * Other optimizations | 11 | * Other optimizations |
| 12 | * Extend cube and moves to include centers | ||
| 11 | * NISS | 13 | * NISS |
| 12 | * Move manipulation utilities | 14 | * Move manipulation utilities |
| 13 | * Coordinate solvers and other steps | 15 | * Coordinate solvers and other steps |
| @@ -76,6 +78,8 @@ What about symcoord? | |||
| 76 | 78 | ||
| 77 | ### General things | 79 | ### General things |
| 78 | 80 | ||
| 81 | * Moves: don't do full compose for U*, D*, *2 (I removed this because I | ||
| 82 | was using shuffle intructions wrong, should re-do it) | ||
| 79 | * Trans: don't do full compose, for some trans composing perm is enough. | 83 | * Trans: don't do full compose, for some trans composing perm is enough. |
| 80 | Split out sumco() as a separate function and refactor, optimize. | 84 | Split out sumco() as a separate function and refactor, optimize. |
| 81 | * Use multi-move (up to 4/5 moves at once) | 85 | * Use multi-move (up to 4/5 moves at once) |
| @@ -113,6 +117,7 @@ What about symcoord? | |||
| 113 | * print ptables (or layout data in such a way that can be printed | 117 | * print ptables (or layout data in such a way that can be printed |
| 114 | easily, e.g. first bytes are null-terminated strig and can be | 118 | easily, e.g. first bytes are null-terminated strig and can be |
| 115 | printed by user) | 119 | printed by user) |
| 120 | * remove writetrans? | ||
| 116 | 121 | ||
| 117 | ## "Front-end" | 122 | ## "Front-end" |
| 118 | 123 | ||
| @@ -277,7 +277,7 @@ _move_U(cube_fast_t c) | |||
| 277 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 1, 0, 3, 2, 4, 5 | 277 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 1, 0, 3, 2, 4, 5 |
| 278 | ); | 278 | ); |
| 279 | 279 | ||
| 280 | return _mm256_shuffle_epi8(c, m); | 280 | return compose_fast(c, m); |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static inline cube_fast_t | 283 | static inline cube_fast_t |
| @@ -288,7 +288,7 @@ _move_U2(cube_fast_t c) | |||
| 288 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 4, 5, 3, 2, 0, 1 | 288 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 4, 5, 3, 2, 0, 1 |
| 289 | ); | 289 | ); |
| 290 | 290 | ||
| 291 | return _mm256_shuffle_epi8(c, m); | 291 | return compose_fast(c, m); |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | static inline cube_fast_t | 294 | static inline cube_fast_t |
| @@ -299,7 +299,7 @@ _move_U3(cube_fast_t c) | |||
| 299 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 0, 1, 3, 2, 5, 4 | 299 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 0, 1, 3, 2, 5, 4 |
| 300 | ); | 300 | ); |
| 301 | 301 | ||
| 302 | return _mm256_shuffle_epi8(c, m); | 302 | return compose_fast(c, m); |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | static inline cube_fast_t | 305 | static inline cube_fast_t |
| @@ -310,7 +310,7 @@ _move_D(cube_fast_t c) | |||
| 310 | 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 5, 4, 6, 7, 1, 0 | 310 | 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 5, 4, 6, 7, 1, 0 |
| 311 | ); | 311 | ); |
| 312 | 312 | ||
| 313 | return _mm256_shuffle_epi8(c, m); | 313 | return compose_fast(c, m); |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | static inline cube_fast_t | 316 | static inline cube_fast_t |
| @@ -321,7 +321,7 @@ _move_D2(cube_fast_t c) | |||
| 321 | 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 5, 4, 2, 3, 1, 0 | 321 | 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 5, 4, 2, 3, 1, 0 |
| 322 | ); | 322 | ); |
| 323 | 323 | ||
| 324 | return _mm256_shuffle_epi8(c, m); | 324 | return compose_fast(c, m); |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | static inline cube_fast_t | 327 | static inline cube_fast_t |
| @@ -332,7 +332,7 @@ _move_D3(cube_fast_t c) | |||
| 332 | 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 4, 7, 6, 1, 0 | 332 | 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 4, 7, 6, 1, 0 |
| 333 | ); | 333 | ); |
| 334 | 334 | ||
| 335 | return _mm256_shuffle_epi8(c, m); | 335 | return compose_fast(c, m); |
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | static inline cube_fast_t | 338 | static inline cube_fast_t |
| @@ -354,7 +354,7 @@ _move_R2(cube_fast_t c) | |||
| 354 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 6, 4, 0, 2, 1, 3 | 354 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 6, 4, 0, 2, 1, 3 |
| 355 | ); | 355 | ); |
| 356 | 356 | ||
| 357 | return _mm256_shuffle_epi8(c, m); | 357 | return compose_fast(c, m); |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | static inline cube_fast_t | 360 | static inline cube_fast_t |
| @@ -387,7 +387,7 @@ _move_L2(cube_fast_t c) | |||
| 387 | 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 5, 7, 3, 1, 2, 0 | 387 | 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 5, 7, 3, 1, 2, 0 |
| 388 | ); | 388 | ); |
| 389 | 389 | ||
| 390 | return _mm256_shuffle_epi8(c, m); | 390 | return compose_fast(c, m); |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | static inline cube_fast_t | 393 | static inline cube_fast_t |
| @@ -420,7 +420,7 @@ _move_F2(cube_fast_t c) | |||
| 420 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, 5, 6, 3, 0, 1, 2 | 420 | 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, 5, 6, 3, 0, 1, 2 |
| 421 | ); | 421 | ); |
| 422 | 422 | ||
| 423 | return _mm256_shuffle_epi8(c, m); | 423 | return compose_fast(c, m); |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | static inline cube_fast_t | 426 | static inline cube_fast_t |
| @@ -453,7 +453,7 @@ _move_B2(cube_fast_t c) | |||
| 453 | 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 4, 1, 2, 3, 0 | 453 | 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 4, 1, 2, 3, 0 |
| 454 | ); | 454 | ); |
| 455 | 455 | ||
| 456 | return _mm256_shuffle_epi8(c, m); | 456 | return compose_fast(c, m); |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | static inline cube_fast_t | 459 | static inline cube_fast_t |
| @@ -1479,13 +1479,13 @@ fasttocube(cube_fast_t c) | |||
| 1479 | static inline bool | 1479 | static inline bool |
| 1480 | equal_fast(cube_fast_t c1, cube_fast_t c2) | 1480 | equal_fast(cube_fast_t c1, cube_fast_t c2) |
| 1481 | { | 1481 | { |
| 1482 | uint32_t mask; | 1482 | int32_t mask; |
| 1483 | __m256i cmp; | 1483 | __m256i cmp; |
| 1484 | 1484 | ||
| 1485 | cmp = _mm256_cmpeq_epi8(c1, c2); | 1485 | cmp = _mm256_cmpeq_epi8(c1, c2); |
| 1486 | mask = _mm256_movemask_epi8(cmp); | 1486 | mask = _mm256_movemask_epi8(cmp); |
| 1487 | 1487 | ||
| 1488 | return mask == 0xffffffffU; | 1488 | return mask == ~0; |
| 1489 | } | 1489 | } |
| 1490 | 1490 | ||
| 1491 | static inline bool | 1491 | static inline bool |
| @@ -1511,6 +1511,19 @@ invertco_fast(cube_fast_t c) | |||
| 1511 | } | 1511 | } |
| 1512 | 1512 | ||
| 1513 | static inline cube_fast_t | 1513 | static inline cube_fast_t |
| 1514 | cleanaftershuffle(cube_fast_t c) | ||
| 1515 | { | ||
| 1516 | __m256i b; | ||
| 1517 | |||
| 1518 | b = _mm256_set_epi8( | ||
| 1519 | ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 1520 | ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
| 1521 | ); | ||
| 1522 | |||
| 1523 | return _mm256_andnot_si256(b, c); | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | static inline cube_fast_t | ||
| 1514 | inverse_fast(cube_fast_t c) | 1527 | inverse_fast(cube_fast_t c) |
| 1515 | { | 1528 | { |
| 1516 | /* Method taken from Andrew Skalski's vcube[1]. The addition sequence | 1529 | /* Method taken from Andrew Skalski's vcube[1]. The addition sequence |
| @@ -1544,6 +1557,7 @@ inverse_fast(cube_fast_t c) | |||
| 1544 | vo = _mm256_shuffle_epi8(vo, vi); | 1557 | vo = _mm256_shuffle_epi8(vo, vi); |
| 1545 | vp = _mm256_andnot_si256(_mm256_or_si256(_eo_avx2, _co2_avx2), vi); | 1558 | vp = _mm256_andnot_si256(_mm256_or_si256(_eo_avx2, _co2_avx2), vi); |
| 1546 | ret = _mm256_or_si256(vp, vo); | 1559 | ret = _mm256_or_si256(vp, vo); |
| 1560 | ret = cleanaftershuffle(ret); | ||
| 1547 | 1561 | ||
| 1548 | return invertco_fast(ret); | 1562 | return invertco_fast(ret); |
| 1549 | } | 1563 | } |
| @@ -1557,6 +1571,7 @@ compose_fast(cube_fast_t c1, cube_fast_t c2) | |||
| 1557 | 1571 | ||
| 1558 | eo2 = _mm256_and_si256(c2, _eo_avx2); | 1572 | eo2 = _mm256_and_si256(c2, _eo_avx2); |
| 1559 | s = _mm256_shuffle_epi8(c1, c2); | 1573 | s = _mm256_shuffle_epi8(c1, c2); |
| 1574 | s = cleanaftershuffle(s); | ||
| 1560 | ed = _mm256_xor_si256(s, eo2); | 1575 | ed = _mm256_xor_si256(s, eo2); |
| 1561 | co1 = _mm256_and_si256(s, _co2_avx2); | 1576 | co1 = _mm256_and_si256(s, _co2_avx2); |
| 1562 | co2 = _mm256_and_si256(c2, _co2_avx2); | 1577 | co2 = _mm256_and_si256(c2, _co2_avx2); |
| @@ -2939,6 +2954,8 @@ Some of these routines depend on the efficient functions implemented in the | |||
| 2939 | previous sections, while some other operate directly on the cube. | 2954 | previous sections, while some other operate directly on the cube. |
| 2940 | ******************************************************************************/ | 2955 | ******************************************************************************/ |
| 2941 | 2956 | ||
| 2957 | static inline uint8_t movebase(uint8_t); | ||
| 2958 | static inline uint8_t moveaxis(uint8_t); | ||
| 2942 | static uint8_t readco(char *); | 2959 | static uint8_t readco(char *); |
| 2943 | static uint8_t readcp(char *); | 2960 | static uint8_t readcp(char *); |
| 2944 | static uint8_t readeo(char *); | 2961 | static uint8_t readeo(char *); |
| @@ -2990,6 +3007,18 @@ iserror(cube_t cube) | |||
| 2990 | return equal(cube, zero); | 3007 | return equal(cube, zero); |
| 2991 | } | 3008 | } |
| 2992 | 3009 | ||
| 3010 | static inline uint8_t | ||
| 3011 | movebase(uint8_t move) | ||
| 3012 | { | ||
| 3013 | return move / 3; | ||
| 3014 | } | ||
| 3015 | |||
| 3016 | static inline uint8_t | ||
| 3017 | moveaxis(uint8_t move) | ||
| 3018 | { | ||
| 3019 | return move / 6; | ||
| 3020 | } | ||
| 3021 | |||
| 2993 | static uint8_t | 3022 | static uint8_t |
| 2994 | readco(char *str) | 3023 | readco(char *str) |
| 2995 | { | 3024 | { |
| @@ -3292,6 +3321,9 @@ writemoves(uint8_t *m, int n, char *buf) | |||
| 3292 | b += len; | 3321 | b += len; |
| 3293 | *b = ' '; | 3322 | *b = ' '; |
| 3294 | } | 3323 | } |
| 3324 | |||
| 3325 | if (b != buf) | ||
| 3326 | b--; /* Remove last space */ | ||
| 3295 | *b = '\0'; | 3327 | *b = '\0'; |
| 3296 | 3328 | ||
| 3297 | return b - buf; | 3329 | return b - buf; |
| @@ -3653,8 +3685,8 @@ typedef struct { | |||
| 3653 | cube_fast_t cube; | 3685 | cube_fast_t cube; |
| 3654 | uint8_t depth; | 3686 | uint8_t depth; |
| 3655 | int64_t maxsols; | 3687 | int64_t maxsols; |
| 3656 | char *sols; | 3688 | char **nextsol; |
| 3657 | int64_t nsols; | 3689 | int64_t *nsols; |
| 3658 | uint8_t nmoves; | 3690 | uint8_t nmoves; |
| 3659 | uint8_t moves[20]; | 3691 | uint8_t moves[20]; |
| 3660 | uint8_t (*estimate)(cube_fast_t); | 3692 | uint8_t (*estimate)(cube_fast_t); |
| @@ -3671,10 +3703,10 @@ allowednextmove(dfsarg_generic_t arg, uint8_t m) | |||
| 3671 | if (n == 0) | 3703 | if (n == 0) |
| 3672 | return true; | 3704 | return true; |
| 3673 | 3705 | ||
| 3674 | mbase = m / 3; | 3706 | mbase = movebase(m); |
| 3675 | maxis = mbase / 2; | 3707 | maxis = moveaxis(m); |
| 3676 | l1base = arg.moves[n-1] / 3; | 3708 | l1base = movebase(arg.moves[n-1]); |
| 3677 | l1axis = l1base / 2; | 3709 | l1axis = moveaxis(arg.moves[n-1]); |
| 3678 | 3710 | ||
| 3679 | if (mbase == l1base || (maxis == l1axis && mbase < l1base)) | 3711 | if (mbase == l1base || (maxis == l1axis && mbase < l1base)) |
| 3680 | return false; | 3712 | return false; |
| @@ -3682,12 +3714,25 @@ allowednextmove(dfsarg_generic_t arg, uint8_t m) | |||
| 3682 | if (n == 1) | 3714 | if (n == 1) |
| 3683 | return true; | 3715 | return true; |
| 3684 | 3716 | ||
| 3685 | l2base = arg.moves[n-2] / 3; | 3717 | l2base = movebase(arg.moves[n-2]); |
| 3686 | l2axis = l1base / 2; | 3718 | l2axis = moveaxis(arg.moves[n-2]); |
| 3687 | 3719 | ||
| 3688 | return l1axis != l2axis || mbase != l2base; | 3720 | return l1axis != l2axis || mbase != l2base; |
| 3689 | } | 3721 | } |
| 3690 | 3722 | ||
| 3723 | static void | ||
| 3724 | solve_generic_appendsolution(dfsarg_generic_t arg) | ||
| 3725 | { | ||
| 3726 | int strl; | ||
| 3727 | |||
| 3728 | strl = writemoves(arg.moves, arg.depth, *arg.nextsol); | ||
| 3729 | DBG_LOG("Solution found: %s\n", *arg.nextsol); | ||
| 3730 | *arg.nextsol += strl; | ||
| 3731 | **arg.nextsol = '\n'; | ||
| 3732 | (*arg.nextsol)++; | ||
| 3733 | (*arg.nsols)++; | ||
| 3734 | } | ||
| 3735 | |||
| 3691 | static int | 3736 | static int |
| 3692 | solve_generic_dfs(dfsarg_generic_t arg) | 3737 | solve_generic_dfs(dfsarg_generic_t arg) |
| 3693 | { | 3738 | { |
| @@ -3697,15 +3742,13 @@ solve_generic_dfs(dfsarg_generic_t arg) | |||
| 3697 | 3742 | ||
| 3698 | bound = arg.estimate(arg.cube); | 3743 | bound = arg.estimate(arg.cube); |
| 3699 | 3744 | ||
| 3700 | if (arg.nsols == arg.maxsols || bound + arg.nmoves > arg.depth) | 3745 | if (*arg.nsols == arg.maxsols || bound + arg.nmoves > arg.depth) |
| 3701 | return 0; | 3746 | return 0; |
| 3702 | 3747 | ||
| 3703 | if (bound == 0) { | 3748 | if (bound == 0) { |
| 3704 | if (arg.nmoves != arg.depth) | 3749 | if (arg.nmoves != arg.depth) |
| 3705 | return 0; | 3750 | return 0; |
| 3706 | arg.sols += writemoves(arg.moves, arg.depth, arg.sols); | 3751 | solve_generic_appendsolution(arg); |
| 3707 | *arg.sols = '\n'; | ||
| 3708 | arg.sols++; | ||
| 3709 | return 1; | 3752 | return 1; |
| 3710 | } | 3753 | } |
| 3711 | 3754 | ||
| @@ -3746,6 +3789,13 @@ solve_generic( | |||
| 3746 | return -1; | 3789 | return -1; |
| 3747 | } | 3790 | } |
| 3748 | 3791 | ||
| 3792 | if (issolved(cube)) { | ||
| 3793 | DBG_LOG("solve: cube is already solved\n"); | ||
| 3794 | sols[0] = '\n'; | ||
| 3795 | sols[1] = 0; | ||
| 3796 | return 1; | ||
| 3797 | } | ||
| 3798 | |||
| 3749 | DBG_WARN(!strcmp(nisstype, ""), | 3799 | DBG_WARN(!strcmp(nisstype, ""), |
| 3750 | "solve: NISS not implemented yet, 'nisstype' ignored\n"); | 3800 | "solve: NISS not implemented yet, 'nisstype' ignored\n"); |
| 3751 | 3801 | ||
| @@ -3782,8 +3832,8 @@ solve_generic( | |||
| 3782 | arg = (dfsarg_generic_t) { | 3832 | arg = (dfsarg_generic_t) { |
| 3783 | .cube = cubetofast(cube), | 3833 | .cube = cubetofast(cube), |
| 3784 | .maxsols = maxsols, | 3834 | .maxsols = maxsols, |
| 3785 | .sols = sols, | 3835 | .nextsol = &sols, |
| 3786 | .nsols = 0, | 3836 | .nsols = &ret, |
| 3787 | .nmoves = 0, | 3837 | .nmoves = 0, |
| 3788 | .moves = {0}, | 3838 | .moves = {0}, |
| 3789 | .estimate = estimate, | 3839 | .estimate = estimate, |
| @@ -3793,12 +3843,11 @@ solve_generic( | |||
| 3793 | first = -1; | 3843 | first = -1; |
| 3794 | for (arg.depth = minmoves; arg.depth <= maxmoves; arg.depth++) { | 3844 | for (arg.depth = minmoves; arg.depth <= maxmoves; arg.depth++) { |
| 3795 | tmp = solve_generic_dfs(arg); | 3845 | tmp = solve_generic_dfs(arg); |
| 3796 | ret += tmp; | ||
| 3797 | if (tmp != 0) | 3846 | if (tmp != 0) |
| 3798 | first = arg.depth; | 3847 | first = arg.depth; |
| 3799 | 3848 | ||
| 3800 | DBG_LOG("Found %" PRId64 " solutions at depth %" PRIu8 "\n", | 3849 | DBG_LOG("Found %" PRId64 " solution%s at depth %" PRIu8 "\n", |
| 3801 | tmp, arg.depth); | 3850 | tmp, tmp == 1 ? "" : "s", arg.depth); |
| 3802 | 3851 | ||
| 3803 | if (ret >= maxsols) | 3852 | if (ret >= maxsols) |
| 3804 | break; | 3853 | break; |
| @@ -3864,7 +3913,7 @@ solve( | |||
| 3864 | DBG_WARN(data == NULL, | 3913 | DBG_WARN(data == NULL, |
| 3865 | "solve: 'data' not implemented yet, ignoring\n"); | 3914 | "solve: 'data' not implemented yet, ignoring\n"); |
| 3866 | 3915 | ||
| 3867 | if (!strcmp(solver, "simple")) { | 3916 | if (!strcmp(solver, "optimal") || !strcmp(solver, "simple")) { |
| 3868 | return solve_simple( | 3917 | return solve_simple( |
| 3869 | cube, | 3918 | cube, |
| 3870 | minmoves, | 3919 | minmoves, |
| @@ -3874,7 +3923,7 @@ solve( | |||
| 3874 | solutions | 3923 | solutions |
| 3875 | ); | 3924 | ); |
| 3876 | } else { | 3925 | } else { |
| 3877 | DBG_LOG("solve: unknown solver\n"); | 3926 | DBG_LOG("solve: unknown solver '%s'\n", solver); |
| 3878 | return -1; | 3927 | return -1; |
| 3879 | } | 3928 | } |
| 3880 | 3929 | ||
| @@ -120,7 +120,10 @@ could. | |||
| 120 | 120 | ||
| 121 | int64_t solve( | 121 | int64_t solve( |
| 122 | cube_t cube, /* The cube to solve. Must be solvable. */ | 122 | cube_t cube, /* The cube to solve. Must be solvable. */ |
| 123 | char *solver, /* The solver. Supported solvers: TODO. */ | 123 | char *solver, /* Supported solvers: |
| 124 | * "optimal" - currently the same as "simple" | ||
| 125 | * "simple" - a simple, slow solver using no tables | ||
| 126 | */ | ||
| 124 | char *options, /* Some solvers accept extra options, | 127 | char *options, /* Some solvers accept extra options, |
| 125 | * like "!filter". | 128 | * like "!filter". |
| 126 | */ | 129 | */ |
diff --git a/test/060_solve_simple/01_U_U3.in b/test/060_solve_simple/01_U_U3.in new file mode 100644 index 0000000..c0f7930 --- /dev/null +++ b/test/060_solve_simple/01_U_U3.in | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | UR0 UL0 DB0 DF0 UB0 UF0 DL0 DR0 FR0 FL0 BL0 BR0 UBR0 UFL0 DFL0 DBR0 UFR0 UBL0 DFR0 DBL0 | ||
| 2 | simple | ||
| 3 | |||
| 4 | normal | ||
| 5 | 0 | ||
| 6 | 3 | ||
| 7 | 3 | ||
| 8 | -1 | ||
diff --git a/test/060_solve_simple/01_U_U3.out b/test/060_solve_simple/01_U_U3.out new file mode 100644 index 0000000..ca934b4 --- /dev/null +++ b/test/060_solve_simple/01_U_U3.out | |||
| @@ -0,0 +1 @@ | |||
| U' | |||
diff --git a/test/060_solve_simple/02_MUMU_alloptimal.in b/test/060_solve_simple/02_MUMU_alloptimal.in new file mode 100644 index 0000000..f97c95f --- /dev/null +++ b/test/060_solve_simple/02_MUMU_alloptimal.in | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | UB0 DF0 DB0 UF0 UR0 UL0 DL0 DR0 FR0 FL0 BL0 BR0 UFR0 UBL0 DFL0 DBR0 UFL0 UBR0 DFR0 DBL0 | ||
| 2 | simple | ||
| 3 | |||
| 4 | normal | ||
| 5 | 0 | ||
| 6 | -1 | ||
| 7 | 10 | ||
| 8 | 0 | ||
diff --git a/test/060_solve_simple/02_MUMU_alloptimal.out b/test/060_solve_simple/02_MUMU_alloptimal.out new file mode 100644 index 0000000..06cd521 --- /dev/null +++ b/test/060_solve_simple/02_MUMU_alloptimal.out | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | U2 R' L F2 R L' | ||
| 2 | R U2 R' L F2 L' | ||
| 3 | R L' U2 R' L F2 | ||
| 4 | L' U2 R' L F2 R | ||
diff --git a/test/060_solve_simple/solve_simple_tests.c b/test/060_solve_simple/solve_simple_tests.c new file mode 100644 index 0000000..14a1674 --- /dev/null +++ b/test/060_solve_simple/solve_simple_tests.c | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | #include <stdbool.h> | ||
| 2 | #include <stdint.h> | ||
| 3 | #include <stdio.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | #include <string.h> | ||
| 6 | |||
| 7 | #ifdef CUBE_AVX2 | ||
| 8 | #include <immintrin.h> | ||
| 9 | #endif | ||
| 10 | |||
| 11 | #include "../../cube.h" | ||
| 12 | |||
| 13 | #define S 10000 | ||
| 14 | |||
| 15 | int main() { | ||
| 16 | char cubestr[S], solverstr[S], optionsstr[S], nisstypestr[S]; | ||
| 17 | char minmovesstr[S], maxmovesstr[S], maxsolsstr[S], optimalstr[S]; | ||
| 18 | char solutionsstr[S]; | ||
| 19 | cube_t cube; | ||
| 20 | int64_t maxsols; | ||
| 21 | int8_t minmoves, maxmoves, optimal; | ||
| 22 | |||
| 23 | fgets(cubestr, S, stdin); | ||
| 24 | fgets(solverstr, S, stdin); | ||
| 25 | fgets(optionsstr, S, stdin); | ||
| 26 | fgets(nisstypestr, S, stdin); | ||
| 27 | fgets(minmovesstr, S, stdin); | ||
| 28 | fgets(maxmovesstr, S, stdin); | ||
| 29 | fgets(maxsolsstr, S, stdin); | ||
| 30 | fgets(optimalstr, S, stdin); | ||
| 31 | |||
| 32 | solverstr[strcspn(solverstr, "\n")] = 0; | ||
| 33 | optionsstr[strcspn(optionsstr, "\n")] = 0; | ||
| 34 | nisstypestr[strcspn(nisstypestr, "\n")] = 0; | ||
| 35 | |||
| 36 | cube = readcube("H48", cubestr); | ||
| 37 | minmoves = atoi(minmovesstr); | ||
| 38 | maxmoves = atoi(maxmovesstr); | ||
| 39 | maxsols = atoi(maxsolsstr); | ||
| 40 | optimal = atoi(optimalstr); | ||
| 41 | |||
| 42 | solve( | ||
| 43 | cube, | ||
| 44 | solverstr, | ||
| 45 | optionsstr, | ||
| 46 | nisstypestr, | ||
| 47 | minmoves, | ||
| 48 | maxmoves, | ||
| 49 | maxsols, | ||
| 50 | optimal, | ||
| 51 | NULL, | ||
| 52 | solutionsstr | ||
| 53 | ); | ||
| 54 | |||
| 55 | printf("%s", solutionsstr); | ||
| 56 | |||
| 57 | return 0; | ||
| 58 | } | ||
