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

commit 0550a16c1cce868bbc3f3b5ad59f80e35cf2a6cd
parent ab95e3801f6659aa6b25ebd9a69b2e23dded130e
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Wed, 19 Mar 2025 17:16:41 +0100

Filter solutions for coordinate solver and fix ordering

Diffstat:
DTODO_COORDINATES | 15---------------
Msrc/core/moves.h | 28++++++++++++++++++++++++++++
Msrc/solvers/coord/eo.h | 1+
Msrc/solvers/coord/solve.h | 8+++++---
Msrc/solvers/coord/types_macros.h | 1+
5 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/TODO_COORDINATES b/TODO_COORDINATES @@ -1,15 +0,0 @@ -- filter solutions - - allow not showing repeated solutions like R2 F and R2 F' for EO - - avoid B2 F as an EO -- in nissy.c, check for minmoves, maxmoves and nissflag (must be in range) -- add a dispatcher in solvers.h? -- test solver for EO (with unit test or tool) -- add NISS (and add tests for NISS EO) -- make solve parallelized -- other coordinates - - gendata must handle symmetry -- make gendata parallelized - -- refactor common parts of coord and h48 solvers -- move parse_h48 to h48 module? - then maybe do like for coordinate and exclude the "h48" part diff --git a/src/core/moves.h b/src/core/moves.h @@ -6,6 +6,8 @@ STATIC_INLINE uint32_t allowednextmove_mask(uint8_t *, uint8_t); STATIC_INLINE uint8_t movebase(uint8_t); STATIC_INLINE uint8_t moveaxis(uint8_t); +STATIC_INLINE bool isbase(uint8_t); +STATIC_INLINE bool parallel(uint8_t, uint8_t); STATIC_INLINE uint32_t disable_moves(uint32_t, uint8_t); STATIC cube_t move(cube_t, uint8_t); @@ -13,6 +15,7 @@ STATIC cube_t premove(cube_t, uint8_t); STATIC uint8_t inverse_move(uint8_t); STATIC void invertmoves(uint8_t *, uint8_t, uint8_t *); STATIC void sortparallel(uint8_t *, uint8_t); +STATIC bool are_lastmoves_singlecw(int n, uint8_t [n]); STATIC int readmoves(const char *, int, uint8_t *); STATIC cube_t applymoves(cube_t, const char *); @@ -91,6 +94,18 @@ moveaxis(uint8_t move) return move / 6; } +STATIC_INLINE bool +isbase(uint8_t move) +{ + return move == 3 * movebase(move); +} + +STATIC_INLINE bool +parallel(uint8_t m1, uint8_t m2) +{ + return moveaxis(m1) == moveaxis(m2); +} + STATIC_INLINE uint8_t moveopposite(uint8_t move) { @@ -241,6 +256,19 @@ sortparallel(uint8_t *moves, uint8_t n) SWAP(moves[i], moves[i+1]); } +STATIC bool +are_lastmoves_singlecw(int n, uint8_t moves[n]) +{ + bool two; + + if (n == 0) + return true; + + two = n > 1 && parallel(moves[n-1], moves[n-2]); + + return isbase(moves[n-1]) && (!two || isbase(moves[n-2])); +} + STATIC int readmoves(const char *buf, int max, uint8_t *ret) { diff --git a/src/solvers/coord/eo.h b/src/solvers/coord/eo.h @@ -15,6 +15,7 @@ STATIC coord_t coordinate_eo = { [AXIS_RL] = TRANS_URr, [AXIS_FB] = TRANS_UFr, }, + .is_admissible = &are_lastmoves_singlecw, }; STATIC uint64_t diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h @@ -35,15 +35,17 @@ solve_coord_appendsolution(dfsarg_solve_coord_t *arg) char *m; if (*arg->nsols >= arg->maxsolutions || - arg->nmoves > *arg->shortest_sol + arg->optimal) + arg->nmoves > *arg->shortest_sol + arg->optimal || + (arg->coord->is_admissible != NULL && + !arg->coord->is_admissible(arg->nmoves, arg->moves))) return 0; - sortparallel(arg->moves, arg->nmoves); - t = inverse_trans(arg->trans); for (i = 0; i < arg->nmoves; i++) tmoves[i] = transform_move(arg->moves[i], t); + sortparallel(tmoves, arg->nmoves); + l = arg->solutions_size - *arg->solutions_used; m = *arg->solutions + *arg->solutions_used; strl = writemoves(tmoves, arg->nmoves, l, m); diff --git a/src/solvers/coord/types_macros.h b/src/solvers/coord/types_macros.h @@ -11,4 +11,5 @@ typedef struct { uint32_t moves_mask; uint64_t trans_mask; uint8_t axistrans[3]; + bool (*is_admissible)(int n, uint8_t [n]); } coord_t;