nissy-fmc

A Rubik's cube FMC assistant
git clone https://git.tronto.net/nissy-fmc
Download | Log | Files | Refs | README | LICENSE

commit 06c3b9610b7694db34ee91312d8f3aa2196d7d62
parent 1485cc87c248e1f56367774ebd4819a97116abcc
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Fri, 25 Feb 2022 17:20:30 +0100

Added cleanup command

Diffstat:
MMakefile | 4++--
MTODO.md | 16+++++++++++-----
Anissy | 0
Msrc/commands.c | 24++++++++++++++++++++++++
Msrc/moves.c | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/moves.h | 1+
6 files changed, 158 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,6 +1,6 @@ # See LICENSE file for copyright and license details. -VERSION = 2.0.1 +VERSION = 2.1-current PREFIX = /usr/local MANPREFIX = ${PREFIX}/share/man @@ -16,7 +16,7 @@ CC = cc all: nissy -nissy: +nissy: clean ${CC} ${CFLAGS} -o nissy src/*.c nissy.exe: diff --git a/TODO.md b/TODO.md @@ -62,14 +62,18 @@ including e.g. solutions that were not shown because -c) ## Technical stuff ### Memory management -* free pruning table after solve is done? if so, I need to add another way - of doing batch solving (I don't want to re-load the tables every time); - for example I could add the possibility of reading scrambles from file, - and execute the same solve command to every line; also improve multi-threading: - I can just solve one scramble per thread, it's better because there is no lock. +* free pruning table after solve is done? if I do this I need to deafault to a + small table for < 8 moves solutions or smth +* improve multi-threading when solving multiple scrambles * alternative: just add a command "free" to free up memory; it is not user friendly (who wants to manage memory manually?) but on the other hand it will only be used by the few who have less than 4(?) Gb of ram. +* nissy -M maxmem option for running with at most maxmem memory; if exceeded + when loading a pruning table, return failure (or make every solve command + use tiny tables instead?); if maxmem is very 600Mb or + less do not use invtables (the performance loss is minimal anyway). If the + limit is really tiny, do not use mtables or ttables (but this would be + very slow and probably nobody will ever use it) * Check if memory is enough for loading pruning tables; if not, abort * For optimal solver: choose largest that fits in memory between nxopt and light @@ -93,3 +97,5 @@ including e.g. solutions that were not shown because -c) than when called directly, to avoid nasty problems with threading * unniss and inverse_alg work differently (one in place, the other makes a copy and returns) changing inverse_alg seems the best option. +* parse command args: one function per arg type, then each command has + a list of options that it accepts (as a string) diff --git a/nissy b/nissy Binary files differ. diff --git a/src/commands.c b/src/commands.c @@ -12,6 +12,7 @@ CommandArgs * scramble_parse_args(int c, char **v); /* Exec functions ************************************************************/ static void gen_exec(CommandArgs *args); +static void cleanup_exec(CommandArgs *args); static void invert_exec(CommandArgs *args); static void solve_exec(CommandArgs *args); static void scramble_exec(CommandArgs *args); @@ -123,6 +124,15 @@ quit_cmd = { }; Command +cleanup_cmd = { + .name = "cleanup", + .usage = "cleanup SCRAMBLE", + .description = "Rewrite a scramble using only standard moves (HTM)", + .parse_args = parse_only_scramble, + .exec = cleanup_exec, +}; + +Command unniss_cmd = { .name = "unniss", .usage = "unniss SCRAMBLE", @@ -151,6 +161,7 @@ Command *commands[NCOMMANDS] = { &scramble_cmd, &steps_cmd, &twophase_cmd, + &cleanup_cmd, &unniss_cmd, &version_cmd, }; @@ -499,6 +510,19 @@ quit_exec(CommandArgs *args) } static void +cleanup_exec(CommandArgs *args) +{ + Alg *alg; + + init_moves(); + + alg = cleanup(args->scramble); + print_alg(alg, false); + + free_alg(alg); +} + +static void unniss_exec(CommandArgs *args) { unniss(args->scramble); diff --git a/src/moves.c b/src/moves.c @@ -3,6 +3,7 @@ /* Local functions ***********************************************************/ static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); +static void cleanup_aux(Alg *alg, Alg *ret, bool inv); static bool read_mtables_file(); static bool write_mtables_file(); @@ -221,6 +222,125 @@ apply_move(Move m, Cube cube) }; } +Alg * +cleanup(Alg *alg) +{ + int i, j, k, b[2], n, L; + Move bb, m; + Alg *ret; + + ret = new_alg(""); + cleanup_aux(alg, ret, false); + cleanup_aux(alg, ret, true); + + do { + for (i = 0, j = 0, n = 0; i < ret->len; i = j) { + if (ret->move[i] > B3) { + ret->move[n] = ret->move[i]; + ret->inv[n] = ret->inv[i]; + n++; + j++; + continue; + } + + bb = 1 + ((base_move(ret->move[i]) - 1)/6)*6; + while (j < ret->len && + ret->move[j] <= B3 && + ret->inv[j] == ret->inv[i] && + 1 + ((base_move(ret->move[j]) - 1)/6)*6 == bb) + j++; + + for (k = i, b[0] = 0, b[1] = 0; k < j; k++) { + m = ret->move[k]; + if (base_move(m) == bb) + b[0] = (b[0]+1+m-base_move(m)) % 4; + else + b[1] = (b[1]+1+m-base_move(m)) % 4; + } + + for (k = 0; k < 2; k++) { + if (b[k] != 0) { + ret->move[n] = bb + b[k] - 1 + 3*k; + ret->inv[n] = ret->inv[i]; + n++; + } + } + } + + L = ret->len; + ret->len = n; + } while (L != n); + + return ret; +} + +static void +cleanup_aux(Alg *alg, Alg *ret, bool inv) +{ + int i, j; + Cube c, d; + Move m, mm; + Alg *equiv_alg; + + c = (Cube){0}; + for (i = 0; i < alg->len; i++) { + if (alg->inv[i] != inv) + continue; + + equiv_alg = new_alg(equiv_alg_string[alg->move[i]]); + + for (j = 0; j < equiv_alg->len; j++) { + m = equiv_alg->move[j]; + if (m == U) { + mm = 3*what_center_at(c, U_center) + 1; + append_move(ret, mm, inv); + } else { + c = apply_move(m, c); + } + } + + free_alg(equiv_alg); + } + + m = NULLMOVE; + switch (what_center_at(c, F_center)) { + case U_center: + m = x3; + break; + case D_center: + m = x; + break; + case R_center: + m = y; + break; + case L_center: + m = y3; + break; + case B_center: + if (what_center_at(c, U_center) == U_center) + m = y2; + else + m = x2; + break; + default: + break; + } + d = apply_move(m, (Cube){0}); + if (m != NULLMOVE) + append_move(ret, m, inv); + + m = NULLMOVE; + if (what_center_at(c, U_center) == what_center_at(d, D_center)) { + m = z2; + } else if (what_center_at(c, U_center) == what_center_at(d, R_center)) { + m = z3; + } else if (what_center_at(c, U_center) == what_center_at(d, L_center)) { + m = z; + } + if (m != NULLMOVE) + append_move(ret, m, inv); +} + static bool read_mtables_file() { diff --git a/src/moves.h b/src/moves.h @@ -8,6 +8,7 @@ Cube apply_alg(Alg *alg, Cube cube); Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); Cube apply_move(Move m, Cube cube); +Alg * cleanup(Alg *alg); void init_moves();