nissy-core

The "engine" of nissy, including the H48 optimal solver.
git clone https://git.tronto.net/nissy-core
Download | Log | Files | Refs | README | LICENSE

commit 83f6533c384a617181e818d1941b08e40aa40b7d
parent 3aba28a34f5fb94e2aff9c437d6b164e3dcc790e
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Tue, 23 Dec 2025 11:53:57 +0100

Added cornersx solver

Diffstat:
Mdoc/solvers.md | 20+++++++++++++++++---
Msrc/core/constants.h | 2++
Msrc/solvers/coord/coord.h | 1+
Asrc/solvers/coord/cornersx.h | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solvers/coord/list.h | 1+
Msrc/solvers/coord/types_macros.h | 2+-
Msrc/solvers/dispatch.h | 1+
Atools/421_solvetest_cornersx/scrambles.h | 29+++++++++++++++++++++++++++++
Atools/421_solvetest_cornersx/solvetest.c | 9+++++++++
9 files changed, 137 insertions(+), 4 deletions(-)

diff --git a/doc/solvers.md b/doc/solvers.md @@ -129,17 +129,31 @@ NISS will not be used. * Moveset: {U, U', U2, D, D', D2, R2, L2, F2, B2}. * Data size: 54MB. -### Solve corners +### Solve corners (fixed centers) -Solve the corners of the cube. Note: centers are considered fixed, +Solve the corners of the cube. The centers are considered fixed, this is not the same as solving a 2x2x2 cube. -* Name: `coord_DRFIN_UF`. Other rotations in place of `UF` are allowed, +* Name: `coord_CORNERS_UF`. Other rotations in place of `UF` are allowed, but they are irrelevant to the solver. Provided alias: `corners`. * Requisites: none. * Moveset: HTM (all 18 basic moves). * Data size: 1.2MB. +### Solve corners (ignoring centers) + +Solve the corners of the cube relative to each other, ignoring centers. +This is the same as solving a 2x2x2 cube. + +* Name: `coord_CORNERSX_UF`. Other rotations in place of `UF` are allowed, + but they are irrelevant to the solver. Provided alias: `cornersx`. +* Requisites: none. +* Moveset: {U, U', U2, R, R', R2, F, F', F2}. Note: if the given cube + has an orientation different from the standard `UF` orientation, the + solution will use a different moves. The solution will always only use + at most 3 different types of moves (as in U, R, F). +* Data size: 1.2MB. + ### Undocumented coordinate solvers There are some coordinate solvers that have not been listed above. These diff --git a/src/core/constants.h b/src/core/constants.h @@ -366,6 +366,8 @@ MM_SINGLE(MOVE_F2) | MM_SINGLE(MOVE_B2)) #define MM18_DR_NOD (MM18_DR & ~MM18_FACE(MOVE_D)) #define MM18_HTR (MM18_ALLMOVES & ~MM18_NOHALFTURNS) +#define MM18_URF (\ + MM18_FACE(MOVE_U) | MM18_FACE(MOVE_R) | MM18_FACE(MOVE_F)) #define TM_SINGLE(t) (UINT64_C(1) << (uint64_t)(t)) #define TM_ALLTRANS UINT64_C(0xFFFFFFFFFFFF) diff --git a/src/solvers/coord/coord.h b/src/solvers/coord/coord.h @@ -9,6 +9,7 @@ #include "drfin.h" #include "htr.h" #include "corners.h" +#include "cornersx.h" #include "list.h" #include "utils.h" #include "gendata.h" diff --git a/src/solvers/coord/cornersx.h b/src/solvers/coord/cornersx.h @@ -0,0 +1,76 @@ +STATIC bool is_cornersx_solved(uint64_t, const unsigned char *); + +STATIC coord_t coordinate_cornersx = { + .name = "CORNERSX", + .coord = &coordinate_corners_coord, + .cube = &coordinate_corners_cube, + .isnasty = &coordinate_corners_isnasty, + .gendata = coordinate_corners_gendata, + .max = CLASSES_CP_48 * POW_3_7, + .trans_mask = TM_ALLTRANS, + .moves_mask_gendata = MM18_ALLMOVES, + .moves_mask_solve = MM18_URF, + .is_admissible = &solution_always_valid, + .solution_prune = NULL, + .is_solvable = &cube_true, + .is_solved = &is_cornersx_solved, + .allow_niss = false, + .pruning_distribution = { + [0] = 5, + [1] = 11, + [2] = 42, + [3] = 240, + [4] = 1115, + [5] = 5848, + [6] = 29088, + [7] = 133410, + [8] = 508020, + [9] = 1100543, + [10] = 371364, + [11] = 2322, + }, + .pruning_max = 11, + .sym = { + .classes = CLASSES_CP_48, + .max = FACT_8, + .coord = &coord_cp, + .cube = &invcoord_cp, + .max2 = POW_3_7, + .coord2 = &coord_co, + .cube2 = &invcoord_co, + .merge = &coordinate_merge_cpco, + }, +}; + +STATIC bool +is_cornersx_solved(uint64_t coord, const unsigned char *data) +{ + /* + TODO we use a bit of an ugly trick to check all rotated versions of + the cube. We would like to apply rotations, but our oriented_cube_t + type does not allow to do this directly (we would just be changing + the orientation field, not the cube itself). So we apply slice moves + instead. We should make this less ugly. + */ + static uint8_t mt[] = { + [MOVE_x] = MOVE_M, [MOVE_x2] = MOVE_M2, [MOVE_x3] = MOVE_M3, + [MOVE_y] = MOVE_E, [MOVE_y2] = MOVE_E2, [MOVE_y3] = MOVE_E3, + [MOVE_z] = MOVE_S3, [MOVE_z2] = MOVE_S2, [MOVE_z3] = MOVE_S + }; + + uint8_t i, j; + cube_t cube; + oriented_cube_t oc; + + cube = coordinate_corners_cube(coord, data); + oc.orientation = ORIENTATION_UF; + for (i = ORIENTATION_UF; i <= ORIENTATION_BL; i++) { + oc.cube = cube; + for (j = 0; orientation_moves[i][j] != UINT8_MAX; j++) + oc = move_extended(oc, mt[orientation_moves[i][j]]); + if (coordinate_corners_coord(oc.cube, data) == 0) + return true; + } + + return false; +} diff --git a/src/solvers/coord/list.h b/src/solvers/coord/list.h @@ -7,6 +7,7 @@ coord_t *all_coordinates[] = { &coordinate_cpepe, &coordinate_htr, &coordinate_corners, + &coordinate_cornersx, NULL }; diff --git a/src/solvers/coord/types_macros.h b/src/solvers/coord/types_macros.h @@ -30,7 +30,7 @@ typedef struct { bool (*is_admissible)(const solution_moves_t[static 1]); bool (*solution_prune)(const solution_moves_t[static 1]); bool (*is_solvable)(cube_t); - /* if is_solved is nulle, coord == 0 is used */ + /* if is_solved is null, coord == 0 is used */ bool (*is_solved)(uint64_t, const unsigned char *); uint64_t pruning_distribution[INFO_DISTRIBUTION_LEN]; uint8_t pruning_max; diff --git a/src/solvers/dispatch.h b/src/solvers/dispatch.h @@ -66,6 +66,7 @@ const char *solver_aliases[][2] = { { "htr-drrl", "coord_HTR_LF" }, { "htr-drfb", "coord_HTR_BU" }, { "corners", "coord_CORNERS_UF" }, + { "cornersx", "coord_CORNERSX_UF" }, { NULL, NULL } }; diff --git a/tools/421_solvetest_cornersx/scrambles.h b/tools/421_solvetest_cornersx/scrambles.h @@ -0,0 +1,29 @@ +struct { + char *scramble; + char *solutions; +} s[] = { +[0] = { + .scramble = "R2 D' F2 B D L2 U L U2 R' D' F2 B2 U F2 D F2 U' L2 D' F2", + .solutions = + "U R U2 F' U R2 U R F'\n" + "U R U' R F R2 F U' F2\n" + "U2 R' U F' U F' U R' U2\n" + "U R2 U2 F U R' U' F U' F2\n" + "U2 F R' F' R2 F' U' F2 U' R\n" + "U2 F2 R F' R' U' R U2 F R'\n" + "U2 F2 R' U R2 F R' F' U' R\n" + "U' F U2 R2 F2 U' F U F' R\n" + "U' F' U2 R2 U' R' U' F U' F2\n" + "U' F' U2 R2 F2 U F U F' R\n" + "R2 U F2 U' R U' F U' R' F2\n" + "F' U F2 U F U' F2 R F' U2\n" + "F' R' F R' F R' U' R' U' F2\n" +}, +/* +TODO: add more scrambles, use https://or18.github.io/RubiksSolverDemo/2x2x2 +to generate test cases. +*/ +{ + .scramble = "", /* End-of-list signal */ +} +}; diff --git a/tools/421_solvetest_cornersx/solvetest.c b/tools/421_solvetest_cornersx/solvetest.c @@ -0,0 +1,9 @@ +#define SOLVER "cornersx" +#define NISSFLAG NISSY_NISSFLAG_NORMAL +#define MINMOVES 0 +#define MAXMOVES 20 +#define MAXSOLUTIONS 500 +#define OPTIMAL 1 + +#include "scrambles.h" +#include "../solvetest.h"