commit 83f6533c384a617181e818d1941b08e40aa40b7d
parent 3aba28a34f5fb94e2aff9c437d6b164e3dcc790e
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date: Tue, 23 Dec 2025 11:53:57 +0100
Added cornersx solver
Diffstat:
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"