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 e2b154c40acaac4e7a7b3e379ada0404519c3750
parent 36c317ebd1cf1dba8a8cbec494f4d3971e6cefd3
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Thu, 31 Jul 2025 08:38:37 +0200

Added solvetest for EO (broken for now)

Diffstat:
Dtools/400_solvetest/solve_test.c | 120-------------------------------------------------------------------------------
Rtools/400_solvetest/scrambles.h -> tools/400_solvetest_optimal/scrambles.h | 0
Atools/400_solvetest_optimal/solvetest.c | 8++++++++
Atools/401_solvetest_opt0_EO_FB/scrambles.h | 300+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atools/401_solvetest_opt0_EO_FB/solvetest.c | 8++++++++
Atools/solvetest.h | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autils/solvetest_gen.sh | 23+++++++++++++++++++++++
7 files changed, 437 insertions(+), 120 deletions(-)

diff --git a/tools/400_solvetest/solve_test.c b/tools/400_solvetest/solve_test.c @@ -1,120 +0,0 @@ -#include "../tool.h" -#include "scrambles.h" - -#define SOL_BUFFER_LEN 100000 - -char *solver; -int64_t size = 0; -unsigned char *buf; - -bool check_one(char *actual, char *expected) { - unsigned i; - size_t l_actual, l_expected; - - for (l_actual = 0; actual[l_actual] != '\n'; l_actual++) ; - l_expected = strlen(expected); - if (l_actual > l_expected) - return false; - for (i = 0; i < l_expected; i++) { - if (!strncmp(actual, &expected[i], l_actual)) - return true; - while(expected[i] != '\n') i++; - } - return false; -} - -bool check_all(char *actual, char *expected) { - unsigned i, found, n_expected; - size_t l_actual; - - l_actual = strlen(actual); - if (l_actual != strlen(expected)) - return false; - - for (i = 0, n_expected = 0; expected[i]; i++) - n_expected += expected[i] == '\n'; - - for (i = 0, found = 0; i < l_actual; i++) - if (i == 0 || actual[i-1] == '\n') - found += check_one(&actual[i], expected); - - return found == n_expected; -} - -void run(void) { - int i; - int64_t n; - long long stats[NISSY_SIZE_SOLVE_STATS]; - char sol[SOL_BUFFER_LEN], cube[NISSY_SIZE_CUBE]; - - for (i = 0; s[i].scramble[0]; i++) { - printf("\n%d. %s\n", i, s[i].scramble); - - /* Single solution */ - if (nissy_applymoves(NISSY_SOLVED_CUBE, s[i].scramble, cube) - == -1) { - printf("Invalid scramble\n"); - continue; - } - n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, - 0, 20, 1, -1, 0, size, buf, SOL_BUFFER_LEN, sol, stats, - NULL, NULL); - if (n == 0) { - printf("Error: no solution\n"); - return; - } - if (check_one(sol, s[i].solutions)) { - printf("Single solution is correct\n"); - } else { - printf("Error!\n"); - printf("Found solution(s):\n%s", sol); - printf("Valid solution(s):\n%s", s[i].solutions); - return; - } - - /* Multiple solutions */ - if (nissy_applymoves(NISSY_SOLVED_CUBE, s[i].scramble, cube) - == -1) { - printf("Invalid scramble\n"); - continue; - } - n = nissy_solve(cube, solver, NISSY_NISSFLAG_NORMAL, - 0, 20, 100, 0, 0, size, buf, SOL_BUFFER_LEN, sol, stats, - NULL, NULL); - if (check_all(sol, s[i].solutions)) { - printf("All solutions are correct\n"); - } else { - printf("Error!\n"); - printf("Found solution(s):\n%s", sol); - printf("Valid solution(s):\n%s", s[i].solutions); - return; - } - } - - printf("\nAll scrambles solved correctly\n"); -} - -int main(int argc, char **argv) { - char filename[255], dataid[NISSY_SIZE_DATAID]; - - if (argc < 2) { - printf("Error: not enough arguments. " - "A solver must be given.\n"); - return 1; - } - - solver = argv[1]; - srand(time(NULL)); - nissy_setlogger(log_stderr, NULL); - - sprintf(filename, "tables/%s", solver); - if (getdata(solver, &buf, filename) != 0) - return 1; - - size = nissy_solverinfo(solver, dataid); - - timerun(run); - - free(buf); - return 0; -} diff --git a/tools/400_solvetest/scrambles.h b/tools/400_solvetest_optimal/scrambles.h diff --git a/tools/400_solvetest_optimal/solvetest.c b/tools/400_solvetest_optimal/solvetest.c @@ -0,0 +1,8 @@ +#define NISSFLAG NISSY_NISSFLAG_NORMAL +#define MINMOVES 0 +#define MAXMOVES 20 +#define MAXSOLUTIONS 100 +#define OPTIMAL 0 + +#include "scrambles.h" +#include "../solvetest.h" diff --git a/tools/401_solvetest_opt0_EO_FB/scrambles.h b/tools/401_solvetest_opt0_EO_FB/scrambles.h @@ -0,0 +1,300 @@ +struct { + char *scramble; + char *solutions; +} s[] = { +[0] = { + .scramble = "B R' F2 D' B' R B' L U R2 U' B2 U L2 B2 L2 U' D R2 U B2 R2", + .solutions = + "L F' U' F\n" + "L' F D F\n" + "R B' U' B\n" + "R' B D B\n" + "(U2 F' L2 F)\n" + "(L2 F U2 F)\n" + "(U B' U' B)\n" + "(U2 B' U2 B)\n" + "(U' B' U B)\n" + "(L B L' B)\n" + "(L2 B L2 B)\n" + "(L' B L B)\n" + "B (U D' B)\n" + "B R' B (B)\n" +}, +[1] = { + .scramble = "U2 L F' B R2 B2 D' B R L2 D' L2 B2 L2 U' F2 U' L2 D2 B2 U' L2", + .solutions = + "(B U D2 F)\n" + "R B (U' B)\n" + "R L B (B)\n" + "B (B R B)\n" +}, +[2] = { + .scramble = "U2 F U D' L2 U' B U L U R2 D2 B2 D' F2 U' L2 U2 F2 R2 F2", + .solutions = + "(D' B D2 F)\n" + "(D' F L2 B)\n" + "(F D' L2 B)\n" + "(F L D' B)\n" +}, +[3] = { + .scramble = "F2 R B' U D' F U L2 D2 R F L2 U2 B' R2 D2 F2 B' D2 L2 F2", + .solutions = + "B R F (U2 F)\n" + "B R' F (U F)\n" + "B' R F (U2 F)\n" + "B' R' F (U F)\n" + "B (B2 U F B)\n" + "B (B2 U' F B)\n" + "F B (U R' F)\n" + "F B (R' U2 F)\n" +}, +[4] = { + .scramble = "R' U' D' B D2 R' U L' D' F U L2 B2 U F2 U D L2 F2 L2 F2", + .solutions = + "D L' B (B)\n" + "L' D B (B)\n" +}, +[5] = { + .scramble = "D' B R B2 L' F R U' R2 B' R2 F2 D' L2 U' L2 U B2 D F2 D' F2 L2", + .solutions = + "U F (R2 B)\n" +}, +[6] = { + .scramble = "L2 B' U D2 R2 D' B' L' U L2 U' F2 R2 D B2 L2 U2 D B2", + .solutions = + "F' B U F\n" + "F' B' U F\n" + "(D B' U2 F)\n" + "(D' B' U2 F)\n" + "(D F' L2 B)\n" + "(D' F' L2 B)\n" + "B (F D F)\n" +}, +[7] = { + .scramble = "F2 D' L2 B L F L B2 U' F2 R2 L2 U2 L2 F L2 B2 R2 B U2", + .solutions = + "F U' L' D' F\n" + "F' U' R D F\n" + "F' R U' D F\n" + "(B D B L F)\n" + "(B D B' L F)\n" + "(B D' B L F)\n" + "(B D' B' L F)\n" + "(D F U2 R B)\n" + "(D' F U2 R B)\n" + "(L' B D F B)\n" + "(L' B D' F B)\n" + "(B L' D F B)\n" + "(B L' D' F B)\n" + "U F (D2 L' F)\n" + "U2 F (D' L' F)\n" + "U2 F (F2 R F)\n" + "U2 D' F (L2 F)\n" + "U2 R F (L F)\n" + "U' F (F D' F)\n" + "R U2 F (L F)\n" + "F (U D' L F)\n" + "F (U L D' F)\n" + "F (D' F2 R' F)\n" + "F (F D' R' F)\n" + "F (F2 U R F)\n" + "F' D L2 B (F)\n" + "F' L2 D B (F)\n" +}, +[8] = { + .scramble = "D L2 F2 L U B R2 L' F U R2 U F2 D2 B2 R2 D' R2 U' F2 L2 D'", + .solutions = + "R' B U' R2 F\n" + "R' B R2 U' F\n" + "(F R2 U' D' F)\n" + "(U F L2 D' B)\n" + "(F L2 U' D' B)\n" + "(F2 B U F B)\n" + "(F2 B U' F B)\n" + "U' R D F (F)\n" + "D F (F U B)\n" + "D F (F' U B)\n" + "R F (D2 L F)\n" + "R F (L D2 F)\n" + "R U' D F (F)\n" + "F (B L2 D F)\n" + "B U' F (D' B)\n" + "B' U' F (D' B)\n" + "U2 F R B (B)\n" + "U2 F' R B (B)\n" + "F U R B (B)\n" + "F B2 L' B (B)\n" + "F' U R B (B)\n" + "F' B2 L' B (B)\n" +}, +[9] = { + .scramble = "F R L2 U2 L' U2 R D' L F D2 L2 F R2 D2 B R2 U2 F2 R2 F", + .solutions = + "D2 B (F)\n" +}, +[10] = { + .scramble = "R' U' R2 L2 D' L' F' B R2 D' F' U2 D2 L2 U2 F' U2 B2 R2 B D2", + .solutions = + "U' B R2 D' F\n" + "F U B R2 F\n" + "F U' B R2 F\n" + "F2 U B' L2 F\n" + "F2 U' B' L2 F\n" + "F U F D2 B\n" + "F U' F D2 B\n" + "F2 U F' D2 B\n" + "F2 U' F' D2 B\n" + "(B L B U F)\n" + "(B L B' U F)\n" + "(B L' B U F)\n" + "(B L' B' U F)\n" + "(L F R2 D B)\n" + "(L' F R2 D B)\n" + "(U' B L F B)\n" + "(U' B L' F B)\n" + "(B U' L F B)\n" + "(B U' L' F B)\n" + "U' R' F (L F)\n" + "R' F (D L F)\n" + "F2 L F (L F)\n" + "F2 L2 F (L' F)\n" + "B2 R2 F (L' F)\n" + "U2 B (D' L B)\n" + "U2 B (L D2 B)\n" +}, +[11] = { + .scramble = "U B D R' L2 U' L' F2 L' B' R2 B2 L2 B2 D R2 F2 D R2 F2 D' L2", + .solutions = + "D R F\n" + "F2 L' F\n" +}, +[12] = { + .scramble = "U2 L' U L U' L2 U F' R F U2 F2 D' B2 D' F2 R2 U' F2 R2 U", + .solutions = + "F L F\n" + "(F' R F)\n" +}, +[13] = { + .scramble = "U2 D R L U' R L F' R F D2 B L2 F' L2 D2 F U2 D2 F D2", + .solutions = + "U R2 B (F)\n" + "R2 U B (F)\n" + "B (U' D F)\n" +}, +[14] = { + .scramble = "L' B L F D' L U R' F2 B' R2 U2 B R2 U2 B U2 B' L2 U2 B2", + .solutions = + "U D F B\n" + "U D' F B\n" + "U' D F B\n" + "U' D' F B\n" + "D2 F (F B)\n" +}, +[15] = { + .scramble = "B D F L2 D2 L' B' R B' R2 L2 U' B2 U F2 U' D' B2 U' F2", + .solutions = + "U' F R L B\n" + "U' F' R L B\n" + "L' U' F R B\n" + "L' U' F' R B\n" + "L' F R U B\n" + "L' F' R U B\n" + "F R U L B\n" + "F' R U L B\n" + "(D' R' B D' F)\n" + "(D' R' B' D' F)\n" + "(R B D R' F)\n" + "(R B R' D F)\n" + "(R B' D R' F)\n" + "(R B' R' D F)\n" + "(R2 D' B R F)\n" + "(R2 D' B' R F)\n" + "(R2 B R D F)\n" + "(R2 B' R D F)\n" + "(D F D' R B)\n" + "(D F R D' B)\n" + "(D F' D' R B)\n" + "(D F' R D' B)\n" + "(D2 R' F D B)\n" + "(D2 R' F' D B)\n" + "(D2 F D R B)\n" + "(D2 F' D R B)\n" + "(R' D' F R' B)\n" + "(R' D' F' R' B)\n" + "U B' D2 F (F)\n" + "U' F (D R' F)\n" + "U' F (R' D F)\n" + "U' D2 F (D F)\n" + "U' B' D2 F (F)\n" + "D2 F (U2 D F)\n" + "R' L' F (R B)\n" + "L' F (R L B)\n" + "F (U D R' F)\n" + "F (U R' D F)\n" + "F (D R' U2 F)\n" + "F (R' U2 D F)\n" + "F (D' R L2 B)\n" + "F (R D' L2 B)\n" + "F (R L D' B)\n" + "F (L D' R B)\n" + "U F' R2 B (F)\n" + "U' R' B (F B)\n" + "U' F' R2 B (F)\n" + "R B (F R' B)\n" + "R B (F' R' B)\n" +}, +[16] = { + .scramble = "D F2 R L B D' F' R' B L' D2 L' U2 R U2 B2 L F2 L2 B2", + .solutions = + "R F B (B)\n" + "R' F B (B)\n" +}, +[17] = { + .scramble = "R U2 F' L B' R' D2 L' F' D' R2 D' R2 D' F2 R2 F2 D R2", + .solutions = + "R' F (L B)\n" +}, +[18] = { + .scramble = "B' R2 B2 R D' R U' F2 U2 D L2 F' D2 R2 F2 D2 R2 L2 B' D2 B", + .solutions = + "B' U' D2 F\n" + "(U2 B' R2 F)\n" + "(R2 B U2 F)\n" + "(U2 F' U2 B)\n" + "(R2 F R2 B)\n" + "F D2 F (B)\n" + "B R2 B (B)\n" +}, +[19] = { + .scramble = "B L U' R2 D2 F B L U2 F' R2 F2 R2 L2 D' B2 L2 D2 L2 D' L2", + .solutions = + "U L' B D2 F\n" + "U B D L' F\n" + "U B L' D2 F\n" + "U' L' B D2 F\n" + "U' B D L' F\n" + "U' B L' D2 F\n" + "U L' F L2 B\n" + "U' L' F L2 B\n" + "F' U F L B\n" + "F' U F' L B\n" + "F' U' F L B\n" + "F' U' F' L B\n" + "F' L' U F B\n" + "F' L' U' F B\n" + "(R' L B U2 F)\n" + "(R' L' B U2 F)\n" + "(L B U R' F)\n" + "(L B R' U2 F)\n" + "(L' B U R' F)\n" + "(L' B R' U2 F)\n" + "(R' L F R2 B)\n" + "(R' L' F R2 B)\n" + "(F L F R B)\n" + "(F L F' R B)\n" + "(F L' F R B)\n" + "(F L' F' R B)\n" + "(R F L F B)\n" + "(R F L' F B)\n" +}, +}; diff --git a/tools/401_solvetest_opt0_EO_FB/solvetest.c b/tools/401_solvetest_opt0_EO_FB/solvetest.c @@ -0,0 +1,8 @@ +#define NISSFLAG NISSY_NISSFLAG_ALL +#define MINMOVES 0 +#define MAXMOVES 20 +#define MAXSOLUTIONS 500 +#define OPTIMAL 0 + +#include "scrambles.h" +#include "../solvetest.h" diff --git a/tools/solvetest.h b/tools/solvetest.h @@ -0,0 +1,98 @@ +#include "tool.h" + +#define SOL_BUFFER_LEN 100000 + +char *solver; +int64_t size = 0; +unsigned char *buf; + +bool check_one(char *actual, char *expected) { + unsigned i; + size_t l_actual, l_expected; + + for (l_actual = 0; actual[l_actual] != '\n'; l_actual++) ; + l_expected = strlen(expected); + if (l_actual > l_expected) + return false; + for (i = 0; i < l_expected; i++) { + if (!strncmp(actual, &expected[i], l_actual)) + return true; + while(expected[i] != '\n') i++; + } + return false; +} + +bool check_all(char *actual, char *expected) { + unsigned i, found, n_expected; + size_t l_actual; + + l_actual = strlen(actual); + if (l_actual != strlen(expected)) + return false; + + for (i = 0, n_expected = 0; expected[i]; i++) + n_expected += expected[i] == '\n'; + + for (i = 0, found = 0; i < l_actual; i++) + if (i == 0 || actual[i-1] == '\n') + found += check_one(&actual[i], expected); + + return found == n_expected; +} + +void run(void) { + int i; + int64_t n; + long long stats[NISSY_SIZE_SOLVE_STATS]; + char sol[SOL_BUFFER_LEN], cube[NISSY_SIZE_CUBE]; + + for (i = 0; s[i].scramble[0]; i++) { + printf("\n%d. %s\n", i, s[i].scramble); + + /* Multiple solutions */ + if (nissy_applymoves(NISSY_SOLVED_CUBE, s[i].scramble, cube) + == -1) { + printf("Invalid scramble\n"); + continue; + } + n = nissy_solve(cube, solver, + NISSFLAG, MINMOVES, MAXMOVES, MAXSOLUTIONS, OPTIMAL, + 0, size, buf, SOL_BUFFER_LEN, sol, stats, + NULL, NULL); + if (check_all(sol, s[i].solutions)) { + printf("All solutions are correct\n"); + } else { + printf("Error!\n"); + printf("Found solution(s):\n%s", sol); + printf("Valid solution(s):\n%s", s[i].solutions); + return; + } + } + + printf("\nAll scrambles solved correctly\n"); +} + +int main(int argc, char **argv) { + char filename[255], dataid[NISSY_SIZE_DATAID]; + + if (argc < 2) { + printf("Error: not enough arguments. " + "A solver must be given.\n"); + return 1; + } + + solver = argv[1]; + srand(time(NULL)); + nissy_setlogger(log_stderr, NULL); + + sprintf(filename, "tables/%s", solver); + if (getdata(solver, &buf, filename) != 0) + return 1; + + size = nissy_solverinfo(solver, dataid); + + timerun(run); + + free(buf); + return 0; +} diff --git a/utils/solvetest_gen.sh b/utils/solvetest_gen.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +args="$@" + +getsolutions() { + nissy solve -p $args "$1" | + while read -r solution; do + printf '\t\t"%s\\n"\n' "$solution" + done +} + +printf "struct {\n\tchar *scramble;\n\tchar *solutions;\n} s[] = {\n" + +i=0 +while read -r scramble; do + solutions="$(getsolutions "$scramble")" + printf '[%s] = {\n\t.scramble = "%s",\n' "$i" "$scramble" + printf '\t.solutions =\n%s\n' "$solutions" + printf '},\n' + i=$((i+1)) +done + +printf "};\n"