nissy-fmc

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

commit 7c7cf8a8689dcbbbca5e3604a464d2526db31a2b
parent b657d9d900bf8d9d00c1dd7ddf6b1b27990e91c1
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Fri, 14 Apr 2023 18:44:15 +0200

seems to work

Diffstat:
Dsrc/alg.c | 393-------------------------------------------------------------------------------
Dsrc/alg.h | 49-------------------------------------------------
Msrc/cube.c | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/cube.h | 36++++++++++++++++++++++--------------
Msrc/main.c | 56++++++++++++++++----------------------------------------
Msrc/pruning.c | 38++++++++++++++++++++++++++++++++++++++
Msrc/pruning.h | 7+++++++
Msrc/solve.c | 134++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/solve.h | 3+--
9 files changed, 386 insertions(+), 583 deletions(-)

diff --git a/src/alg.c b/src/alg.c @@ -1,393 +0,0 @@ -#define ALG_C - -#include "alg.h" - -static int axis(Move m); -static void free_alglistnode(AlgListNode *aln); -static void realloc_alg(Alg *alg, int n); - -static char move_string[NMOVES][7] = { - [NULLMOVE] = "-", - [U] = "U", [U2] = "U2", [U3] = "U\'", - [D] = "D", [D2] = "D2", [D3] = "D\'", - [R] = "R", [R2] = "R2", [R3] = "R\'", - [L] = "L", [L2] = "L2", [L3] = "L\'", - [F] = "F", [F2] = "F2", [F3] = "F\'", - [B] = "B", [B2] = "B2", [B3] = "B\'", - [Uw] = "Uw", [Uw2] = "Uw2", [Uw3] = "Uw\'", - [Dw] = "Dw", [Dw2] = "Dw2", [Dw3] = "Dw\'", - [Rw] = "Rw", [Rw2] = "Rw2", [Rw3] = "Rw\'", - [Lw] = "Lw", [Lw2] = "Lw2", [Lw3] = "Lw\'", - [Fw] = "Fw", [Fw2] = "Fw2", [Fw3] = "Fw\'", - [Bw] = "Bw", [Bw2] = "Bw2", [Bw3] = "Bw\'", - [M] = "M", [M2] = "M2", [M3] = "M\'", - [E] = "E", [E2] = "E2", [E3] = "E\'", - [S] = "S", [S2] = "S2", [S3] = "S\'", - [x] = "x", [x2] = "x2", [x3] = "x\'", - [y] = "y", [y2] = "y2", [y3] = "y\'", - [z] = "z", [z2] = "z2", [z3] = "z\'", -}; - -bool -allowed_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -allowed_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - -bool -allowed_eofb(Move m) -{ - Move b = base_move(m); - - return b == U || b == D || b == R || b == L || - ((b == F || b == B) && m == b+1); -} - -bool -allowed_drud(Move m) -{ - Move b = base_move(m); - - return b == U || b == D || - ((b == R || b == L || b == F || b == B) && m == b + 1); -} - -bool -allowed_htr(Move m) -{ - Move b = base_move(m); - - return allowed_HTM(m) && m == b + 1; -} - -void -append_alg(AlgList *l, Alg *alg) -{ - AlgListNode *node = malloc(sizeof(AlgListNode)); - int i; - - node->alg = new_alg(""); - for (i = 0; i < alg->len; i++) - append_move(node->alg, alg->move[i], alg->inv[i]); - node->next = NULL; - - if (++l->len == 1) - l->first = node; - else - l->last->next = node; - l->last = node; -} - -void -append_move(Alg *alg, Move m, bool inverse) -{ - if (alg->len == alg->allocated) - realloc_alg(alg, 2*alg->len); - - alg->move[alg->len] = m; - alg->inv [alg->len] = inverse; - alg->len++; -} - -static int -axis(Move m) -{ - if (m == NULLMOVE) - return 0; - - if (m >= U && m <= B3) - return (m-1)/6 + 1; - - if (m >= Uw && m <= Bw3) - return (m-1)/6 - 2; - - if (base_move(m) == E || base_move(m) == y) - return 1; - - if (base_move(m) == M || base_move(m) == x) - return 2; - - if (base_move(m) == S || base_move(m) == z) - return 3; - - return -1; -} - -Move -base_move(Move m) -{ - return m == NULLMOVE ? NULLMOVE : m - (m-1)%3; -} - -bool -commute(Move m1, Move m2) -{ - return axis(m1) == axis(m2); -} - -void -copy_alg(Alg *src, Alg *dst) -{ - int i; - - dst->len = 0; /* Overwrites */ - for (i = 0; i < src->len; i++) - append_move(dst, src->move[i], src->inv[i]); -} - -void -free_alg(Alg *alg) -{ - free(alg->move); - free(alg->inv); - free(alg); -} - -void -free_alglist(AlgList *l) -{ - AlgListNode *aux, *i = l->first; - - while (i != NULL) { - aux = i->next; - free_alglistnode(i); - i = aux; - } - free(l); -} - -static void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -Alg * -inverse_alg(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = alg->len-1; i >= 0; i--) - append_move(ret, inverse_move(alg->move[i]), alg->inv[i]); - - return ret; -} - -Move -inverse_move(Move m) -{ - return m == NULLMOVE ? NULLMOVE : m + 2 - 2*((m-1) % 3); -} - -Alg * -new_alg(char *str) -{ - Alg *alg; - int i; - bool niss, move_read; - Move j, m; - - alg = malloc(sizeof(Alg)); - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - niss = false; - for (i = 0; str[i]; i++) { - if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') - continue; - - if (str[i] == '(' && niss) { - fprintf(stderr, "Error reading moves: nested ( )\n"); - alg->len = 0; - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - alg->len = 0; - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - /* Single slash for comments */ - if (str[i] == '/') { - while (str[i] && str[i] != '\n') - i++; - - if (!str[i]) - i--; - - continue; - } - - move_read = false; - for (j = U; j < NMOVES; j++) { - if (str[i] == move_string[j][0] || - (str[i] >= 'a' && str[i] <= 'z' && - str[i] == move_string[j][0]-('A'-'a') && j<=B)) { - m = j; - if (str[i] >= 'a' && str[i] <= 'z' && j<=B) { - m += Uw - U; - } - if (m <= B && str[i+1]=='w') { - m += Uw - U; - i++; - } - if (str[i+1]=='2') { - m += 1; - i++; - } else if (str[i+1] == '\'' || - str[i+1] == '3' || - str[i+1] == '`' ) { - m += 2; - i++; - } else if ((int)str[i+1] == -62 && - (int)str[i+2] == -76) { - /* Weird apostrophe */ - m += 2; - i += 2; - } else if ((int)str[i+1] == -30 && - (int)str[i+2] == -128 && - (int)str[i+3] == -103) { - /* MacOS apostrophe */ - m += 2; - i += 3; - } - append_move(alg, m, niss); - move_read = true; - break; - } - } - - if (!move_read) { - free(alg); - return new_alg(""); - } - } - - if (niss) { - fprintf(stderr, "Error reading moves: unmatched (\n"); - alg->len = 0; - } - - return alg; -} - -AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -void -print_alg(Alg *alg) -{ - char fill[4]; - int i; - bool niss = false; - - for (i = 0; i < alg->len; i++) { - if (!niss && alg->inv[i]) - strcpy(fill, i == 0 ? "(" : " ("); - if (niss && !alg->inv[i]) - strcpy(fill, ") "); - if (niss == alg->inv[i]) - strcpy(fill, i == 0 ? "" : " "); - - printf("%s%s", fill, move_string[alg->move[i]]); - niss = alg->inv[i]; - } - - if (niss) - printf(")"); - - printf("\n"); -} - -void -print_alglist(AlgList *al) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg); -} - -static void -realloc_alg(Alg *alg, int n) -{ - if (alg == NULL) { - fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); - return; - } - - if (n < alg->len) { - fprintf(stderr, "Error: alg too long for reallocation "); - fprintf(stderr, "(%d vs %d)\n", alg->len, n); - return; - } - - if (n > 1000000) { - fprintf(stderr, "Warning: very long alg,"); - fprintf(stderr, "something might go wrong.\n"); - } - - alg->move = realloc(alg->move, n * sizeof(int)); - alg->inv = realloc(alg->inv, n * sizeof(int)); - alg->allocated = n; -} - -bool -singlecwend(Alg *alg) -{ - int i; - bool nor, inv; - Move l2 = NULLMOVE, l1 = NULLMOVE, l2i = NULLMOVE, l1i = NULLMOVE; - - for (i = 0; i < alg->len; i++) { - if (alg->inv[i]) { - l2i = l1i; - l1i = alg->move[i]; - } else { - l2 = l1; - l1 = alg->move[i]; - } - } - - nor = l1 ==base_move(l1) && (!commute(l1, l2) ||l2 ==base_move(l2)); - inv = l1i==base_move(l1i) && (!commute(l1i,l2i)||l2i==base_move(l2i)); - - return nor && inv; -} - -void -swapmove(Move *m1, Move *m2) -{ - Move aux; - - aux = *m1; - *m1 = *m2; - *m2 = aux; -} diff --git a/src/alg.h b/src/alg.h @@ -1,49 +0,0 @@ -#ifndef ALG_H -#define ALG_H - -// solve, private -typedef struct alglistnode { - Alg *alg; - struct alglistnode *next; -} AlgListNode; -typedef struct { - AlgListNode *first; - AlgListNode *last; - int len; -} AlgList; - -//cube -void copy_alg(Alg *src, Alg *dst); -void free_alg(Alg *alg); -Alg * new_alg(char *str); -void append_move(Alg *alg, Move m, bool inverse); -Alg * inverse_alg(Alg *alg); -Move inverse_move(Move m); - -// pruning -bool allowed_all(Move m); -bool allowed_HTM(Move m); -bool allowed_URF(Move m); -bool allowed_eofb(Move m); -bool allowed_drud(Move m); -bool allowed_htr(Move m); - -// pruning and solve? -Move base_move(Move m); -bool commute(Move m1, Move m2); - -// solve -void free_alglist(AlgList *l); -AlgList * new_alglist(); -void append_alg(AlgList *l, Alg *alg); - -// solve, private -bool singlecwend(Alg *alg); -void swapmove(Move *m1, Move *m2); - -// solve, change interface -void print_alg(Alg *alg); -void print_alglist(AlgList *al); - -#endif - diff --git a/src/cube.c b/src/cube.c @@ -1,11 +1,40 @@ #include "cube.h" static Cube move_array[NMOVES]; -static Alg *rotation_alg[NTRANS/2]; Move moves_ttable[NTRANS][NMOVES]; Trans trans_ttable[NTRANS][NTRANS]; Trans trans_itable[NTRANS]; +static char move_string[NMOVES][7] = { + [NULLMOVE] = "-", + [U] = "U", [U2] = "U2", [U3] = "U\'", + [D] = "D", [D2] = "D2", [D3] = "D\'", + [R] = "R", [R2] = "R2", [R3] = "R\'", + [L] = "L", [L2] = "L2", [L3] = "L\'", + [F] = "F", [F2] = "F2", [F3] = "F\'", + [B] = "B", [B2] = "B2", [B3] = "B\'", + [Uw] = "Uw", [Uw2] = "Uw2", [Uw3] = "Uw\'", + [Dw] = "Dw", [Dw2] = "Dw2", [Dw3] = "Dw\'", + [Rw] = "Rw", [Rw2] = "Rw2", [Rw3] = "Rw\'", + [Lw] = "Lw", [Lw2] = "Lw2", [Lw3] = "Lw\'", + [Fw] = "Fw", [Fw2] = "Fw2", [Fw3] = "Fw\'", + [Bw] = "Bw", [Bw2] = "Bw2", [Bw3] = "Bw\'", + [M] = "M", [M2] = "M2", [M3] = "M\'", + [E] = "E", [E2] = "E2", [E3] = "E\'", + [S] = "S", [S2] = "S2", [S3] = "S\'", + [x] = "x", [x2] = "x2", [x3] = "x\'", + [y] = "y", [y2] = "y2", [y3] = "y\'", + [z] = "z", [z2] = "z2", [z3] = "z\'", +}; +static char rotation_string[100][NTRANS/2] = { + [uf] = "", [ur] = "y", [ub] = "y2", [ul] = "y3", + [df] = "z2", [dr] = "y z2", [db] = "x2", [dl] = "y3 z2", + [rf] = "z3", [rd] = "z3 y", [rb] = "z3 y2", [ru] = "z3 y3", + [lf] = "z", [ld] = "z y3", [lb] = "z y2", [lu] = "z y", + [fu] = "x y2", [fr] = "x y", [fd] = "x", [fl] = "x y3", + [bu] = "x3", [br] = "x3 y", [bd] = "x3 y2", [bl] = "x3 y3", +}; + TransGroup tgrp_udfix = { .n = 16, @@ -107,6 +136,58 @@ make_solved(Cube *cube) memset(cube->co, 0, 8 * sizeof(int)); } +Move +base_move(Move m) +{ + return m == NULLMOVE ? NULLMOVE : m - (m-1)%3; +} + +Move +inverse_move(Move m) +{ + return m == NULLMOVE ? NULLMOVE : m + 2 - 2*((m-1) % 3); +} + +bool +commute(Move m1, Move m2) +{ + if (m1 > B3 || m2 > B3) { + fprintf(stderr, "Unexpected commute for non-HTM\n"); + return false; + } + + if (m1 == NULLMOVE || m2 == NULLMOVE) + return m1 == m2; + + return (m1-1)/6 == (m2-1)/6; +} + +void +copy_alg(Alg *src, Alg *dst) +{ + int i; + + dst->len = src->len; + for (i = 0; i < src->len; i++) { + dst->move[i] = src->move[i]; + dst->inv[i] = src->inv[i]; + } +} + +void +append_move(Alg *alg, Move m, bool inverse) +{ + alg->move[alg->len] = m; + alg->inv[alg->len] = inverse; + alg->len++; +} + +void +apply_move(Move m, Cube *cube) +{ + compose(&move_array[m], cube); +} + void apply_alg(Alg *alg, Cube *cube) { @@ -128,17 +209,132 @@ apply_alg(Alg *alg, Cube *cube) apply_move(alg->move[i], cube); } -void -apply_move(Move m, Cube *cube) +static Move +read_move(char *str, int *i) { - compose(&move_array[m], cube); + Move j, m; + char upper, lower, inv; + + for (j = U; j < NMOVES; j++) { + upper = move_string[j][0]; + lower = upper - ('A' - 'a'); + if (str[*i] == upper || (str[*i] == lower && j <= B)) { + m = j; + if (str[*i] == lower) + m += Uw - U; + if (m <= B && str[*i+1] == 'w') { + m += Uw - U; + *i += 1; + } + if (str[*i+1]=='2') { + m += 1; + *i += 1; + } + inv = str[*i+1] == '\'' || + str[*i+1] == '3' || + str[*i+1] == '`'; + /* TODO: add weird apostrophes */ + if (inv) { + m += 2; + *i += 1; + } + return m; + } + } + + return NULLMOVE; +} + +bool +apply_scramble(char *str, Cube *c) +{ + int i; + bool niss; + Cube normal, inverse; + Move move; + + niss = false; + make_solved(&normal); + make_solved(&inverse); + for (i = 0; str[i]; i++) { + if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') + continue; + + if ((str[i] == '(' && niss) || (str[i] == ')' && !niss)) { + fprintf(stderr, + "Error reading moves: unmatched %c\n", str[i]); + return false; + } + + if (str[i] == '(' || str[i] == ')') { + niss = !niss; + continue; + } + + /* Single slash for comments */ + if (str[i] == '/') { + while (str[i] && str[i] != '\n') i++; + if (!str[i]) i--; + continue; + } + + move = read_move(str, &i); + if (move == NULLMOVE) + return false; + apply_move(move, niss ? &inverse : &normal); + } + + if (niss) { + fprintf(stderr, "Error reading moves: unmatched (\n"); + return false; + } + + invert_cube(&inverse); + compose(c, &inverse); + copy_cube(&inverse, c); + compose(&normal, c); + + return true; +} + +int +alg_string(Alg *alg, char *str) +{ + int i, n; + bool niss; + Move m; + + niss = false; + for (i = 0, n = 0; i < alg->len; i++) { + if (!niss && alg->inv[i]) { + if (i != 0) + str[n++] = ' '; + str[n++] = '('; + } + if (niss && !alg->inv[i]) { + str[n++] = ')'; + str[n++] = ' '; + } + if (niss == alg->inv[i] && i != 0) + str[n++] = ' '; + m = alg->move[i]; + str[n++] = move_string[m][0]; + if (move_string[m][1]) + str[n++] = move_string[m][1]; + niss = alg->inv[i]; + } + + if (niss) + str[n++] = ')'; + str[n] = 0; + + return n; } void apply_trans(Trans t, Cube *cube) { - Cube aux; - Alg *inv; + Cube aux, inv; int i; static Cube mirror_cube = { @@ -149,22 +345,22 @@ apply_trans(Trans t, Cube *cube) [DFR] = DFL, [DFL] = DFR, [DBL] = DBR, [DBR] = DBL }, }; - inv = inverse_alg(rotation_alg[t % (NTRANS/2)]); copy_cube(cube, &aux); make_solved(cube); if (t >= NTRANS/2) compose(&mirror_cube, cube); - apply_alg(inv, cube); + make_solved(&inv); + apply_scramble(rotation_string[t % (NTRANS/2)], &inv); + invert_cube(&inv); + compose(&inv, cube); compose(&aux, cube); - apply_alg(rotation_alg[t % (NTRANS/2)], cube); + apply_scramble(rotation_string[t % (NTRANS/2)], cube); if (t >= NTRANS/2) { compose(&mirror_cube, cube); for (i = 0; i < 8; i++) cube->co[i] = (3 - cube->co[i]) % 3; } - - free_alg(inv); } Trans @@ -199,7 +395,6 @@ transform_trans(Trans t, Trans m) static void init_moves() { Move m; - Alg *equiv_alg[NMOVES]; /* Moves are represented as cubes and applied using compose(). * Every move is translated to a an <U, x, y> alg before filling @@ -289,9 +484,6 @@ init_moves() { move_array[x] = mcx; move_array[y] = mcy; - for (m = 0; m < NMOVES; m++) - equiv_alg[m] = new_alg(equiv_alg_string[m]); - for (m = 0; m < NMOVES; m++) { switch (m) { case NULLMOVE: @@ -303,36 +495,18 @@ init_moves() { break; default: make_solved(&move_array[m]); - apply_alg(equiv_alg[m], &move_array[m]); + apply_scramble(equiv_alg_string[m], &move_array[m]); break; } } - - for (m = 0; m < NMOVES; m++) - free_alg(equiv_alg[m]); } static void init_trans() { - - int i; - Alg *nonsym_alg, *nonsym_inv; Cube aux, cube; Move mi, move; Trans t, u, v; - char rotation_alg_string[100][NTRANS/2] = { - [uf] = "", [ur] = "y", [ub] = "y2", [ul] = "y3", - [df] = "z2", [dr] = "y z2", [db] = "x2", [dl] = "y3 z2", - [rf] = "z3", [rd] = "z3 y", [rb] = "z3 y2", [ru] = "z3 y3", - [lf] = "z", [ld] = "z y3", [lb] = "z y2", [lu] = "z y", - [fu] = "x y2", [fr] = "x y", [fd] = "x", [fl] = "x y3", - [bu] = "x3", [br] = "x3 y", [bd] = "x3 y2", [bl] = "x3 y3", - }; - - for (i = 0; i < NTRANS/2; i++) - rotation_alg[i] = new_alg(rotation_alg_string[i]); - for (t = 0; t < NTRANS; t++) { for (mi = 0; mi < NMOVES; mi++) { make_solved(&aux); @@ -349,19 +523,16 @@ init_trans() { } } - nonsym_alg = new_alg("R' U' F"); - nonsym_inv = inverse_alg(nonsym_alg); - for (t = 0; t < NTRANS; t++) { for (u = 0; u < NTRANS; u++) { make_solved(&aux); - apply_alg(nonsym_alg, &aux); + apply_scramble("R' U' F", &aux); apply_trans(u, &aux); apply_trans(t, &aux); for (v = 0; v < NTRANS; v++) { copy_cube(&aux, &cube); apply_trans(v, &cube); - apply_alg(nonsym_inv, &cube); + apply_scramble("F' U R", &cube); if (is_solved(&cube)) { /* This is the inverse of the correct value, it will be inverted later */ @@ -376,10 +547,6 @@ init_trans() { for (t = 0; t < NTRANS; t++) for (u = 0; u < NTRANS; u++) trans_ttable[t][u] = trans_itable[trans_ttable[t][u]]; - - - free_alg(nonsym_alg); - free_alg(nonsym_inv); } void diff --git a/src/cube.h b/src/cube.h @@ -22,6 +22,7 @@ #define BINOM8ON4 70ULL #define NMOVES 55 #define NTRANS 48 +#define MAX_ALG_LEN 22 #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) @@ -55,27 +56,34 @@ typedef enum { } Trans; typedef struct { int ep[12]; int eo[12]; int cp[8]; int co[8]; } Cube; -typedef struct { Move *move; bool *inv; int len; int allocated; } Alg; +typedef struct { Move move[MAX_ALG_LEN]; bool inv[MAX_ALG_LEN]; int len; } Alg; typedef struct { int n; Trans t[NTRANS]; } TransGroup; extern TransGroup tgrp_udfix; -void compose(Cube *c2, Cube *c1); /* Use c2 as an alg on c1 */ -void copy_cube(Cube *src, Cube *dst); -void invert_cube(Cube *cube); -bool is_solved(Cube *cube); -void make_solved(Cube *cube); +void compose(Cube *c2, Cube *c1); /* Use c2 as an alg on c1 */ +void copy_cube(Cube *src, Cube *dst); +void invert_cube(Cube *cube); +bool is_solved(Cube *cube); +void make_solved(Cube *cube); -void apply_alg(Alg *alg, Cube *cube); -void apply_move(Move m, Cube *cube); +Move base_move(Move m); +bool commute(Move m1, Move m2); +Move inverse_move(Move m); -void apply_trans(Trans t, Cube *cube); -Trans inverse_trans(Trans t); -void transform_alg(Trans t, Alg *alg); -Move transform_move(Trans t, Move m); -Trans transform_trans(Trans t, Trans m); +void copy_alg(Alg *src, Alg *dst); +void append_move(Alg *alg, Move m, bool inverse); +void apply_move(Move m, Cube *cube); +void apply_alg(Alg *alg, Cube *cube); +bool apply_scramble(char *str, Cube *c); +int alg_string(Alg *alg, char *str); -void init_cube(); +void apply_trans(Trans t, Cube *cube); +Trans inverse_trans(Trans t); +void transform_alg(Trans t, Alg *alg); +Move transform_move(Trans t, Move m); +Trans transform_trans(Trans t, Trans m); +void init_cube(); #endif diff --git a/src/main.c b/src/main.c @@ -1,44 +1,15 @@ #include "solve.h" -static Alg * -read_scramble(int c, char **v) -{ - int i, k, n; - unsigned int j; - char *algstr; - Alg *scr; - - if (c < 1) { - fprintf(stderr, "Error: no scramble given\n"); - return false; - } - - for(n = 0, i = 0; i < c; i++) - n += strlen(v[i]); - - algstr = malloc((n + 1) * sizeof(char)); - k = 0; - for (i = 0; i < c; i++) - for (j = 0; j < strlen(v[i]); j++) - algstr[k++] = v[i][j]; - algstr[k] = 0; - - scr = new_alg(algstr); - - free(algstr); - - return scr; -} +#define MAX_SOLS 999 int main(int argc, char *argv[]) { - int i, m; + int i, m, n; long val; - Alg *scramble; - AlgList *sols; Cube c; SolutionType t; + Alg sols[999]; if (argc < 2) { fprintf(stderr, "Not enough arguments given\n"); @@ -47,7 +18,6 @@ main(int argc, char *argv[]) m = 0; t = NORMAL; - scramble = new_alg(""); init_env(); init_cube(); @@ -69,17 +39,23 @@ main(int argc, char *argv[]) } } - scramble = read_scramble(argc - i, &argv[i]); - if (scramble->len <= 0) { - fprintf(stderr, "Cannot read scramble\n"); + if (i == argc) { + fprintf(stderr, "No scramble given\n"); return 4; } make_solved(&c); - apply_alg(scramble, &c); - sols = solve(&c, argv[1], m, t, uf); /* TODO: trans */ - print_alglist(sols); - free_alglist(sols); + if (!apply_scramble(argv[i], &c)) { + fprintf(stderr, "Invalid scramble: %s\n", argv[i]); + return 5; + } + + n = solve(&c, argv[1], m, t, uf, sols); /* TODO: trans */ + for (i = 0; i < n; i++) { + char buf[66]; + int l = alg_string(&sols[i], buf); + printf("%s (%d)\n", buf, l); + } return 0; } diff --git a/src/pruning.c b/src/pruning.c @@ -15,6 +15,44 @@ static bool write_ptable_file(PruneData *pd); PDGenData *active_pdg[256]; +bool +allowed_HTM(Move m) +{ + return m >= U && m <= B3; +} + +bool +allowed_URF(Move m) +{ + Move b = base_move(m); + + return b == U || b == R || b == F; +} + +bool +allowed_eofb(Move m) +{ + Move b = base_move(m); + + return b == U || b == D || b == R || b == L || + ((b == F || b == B) && m == b+1); +} + +bool +allowed_drud(Move m) +{ + Move b = base_move(m); + + return b == U || b == D || + ((b == R || b == L || b == F || b == B) && m == b + 1); +} + +bool +allowed_htr(Move m) +{ + return allowed_HTM(m) && m == base_move(m) + 1; +} + PruneData * genptable(PDGenData *pdg) { diff --git a/src/pruning.h b/src/pruning.h @@ -23,6 +23,13 @@ typedef struct { PruneData * pd; } PDGenData; +bool allowed_all(Move m); +bool allowed_HTM(Move m); +bool allowed_URF(Move m); +bool allowed_eofb(Move m); +bool allowed_drud(Move m); +bool allowed_htr(Move m); + void free_pd(PruneData *pd); PruneData * genptable(PDGenData *data); void print_ptable(PruneData *pd); diff --git a/src/solve.c b/src/solve.c @@ -21,7 +21,10 @@ typedef struct { Cube * cube; Movable ind[MAX_N_COORD]; Step * s; - AlgList * sols; + Trans t; + SolutionType st; + int * nsols; + Alg * sols; int d; int bound; bool can_niss; @@ -32,6 +35,7 @@ typedef struct { Alg * current_alg; } DfsArg; +static void append_sol(DfsArg *arg); static bool allowed_next(Move move, Step *s, Move l0, Move l1); static void compute_ind(DfsArg *arg); static void copy_dfsarg(DfsArg *src, DfsArg *dst); @@ -40,6 +44,7 @@ static void dfs(DfsArg *arg); static void dfs_niss(DfsArg *arg); static bool dfs_move_checkstop(DfsArg *arg); static bool niss_makes_sense(DfsArg *arg); +static bool singlecwend(Alg *alg); Step eofb_HTM = { .shortname = "eofb", @@ -67,6 +72,21 @@ Step drfin_drud = { Step *steps[] = { &eofb_HTM, &drud_HTM, &drfin_drud, NULL }; +static void +append_sol(DfsArg *arg) +{ + int i; + + copy_alg(arg->current_alg, &arg->sols[*arg->nsols]); + transform_alg(inverse_trans(arg->t), &arg->sols[*arg->nsols]); + + if (arg->st == INVERSE) + for (i = 0; i < arg->sols[*arg->nsols].len; i++) + arg->sols[*arg->nsols].inv[i] = true; + + (*arg->nsols)++; +} + static bool allowed_next(Move m, Step *s, Move l0, Move l1) { @@ -97,11 +117,14 @@ copy_dfsarg(DfsArg *src, DfsArg *dst) dst->cube = src->cube; dst->s = src->s; + dst->t = src->t; + dst->st = src->st; dst->d = src->d; dst->bound = src->bound; /* In theory not needed */ dst->can_niss = src->can_niss; dst->niss = src->niss; dst->has_nissed = src->has_nissed; + dst->nsols = src->nsols; dst->sols = src->sols; dst->current_alg = src->current_alg; @@ -139,15 +162,17 @@ dfs(DfsArg *arg) { Move m; DfsArg newarg; + bool len, singlecw, niss; if (dfs_move_checkstop(arg)) return; if (arg->bound == 0) { - if (arg->current_alg->len == arg->d && - singlecwend(arg->current_alg) && - (!arg->can_niss || arg->has_nissed)) - append_alg(arg->sols, arg->current_alg); + len = arg->current_alg->len == arg->d; + singlecw = singlecwend(arg->current_alg); + niss = !arg->can_niss || arg->has_nissed; + if (len && singlecw && niss) + append_sol(arg); return; } @@ -171,35 +196,38 @@ dfs(DfsArg *arg) static void dfs_niss(DfsArg *arg) { + int i; DfsArg newarg; - Alg *inv; - Cube *c; + Cube c, newcube; + Move aux; copy_dfsarg(arg, &newarg); /* Invert current alg and scramble */ - newarg.cube = malloc(sizeof(Cube)); - inv = inverse_alg(arg->current_alg); - c = malloc(sizeof(Cube)); + newarg.cube = &newcube; + make_solved(newarg.cube); - apply_alg(inv, newarg.cube); - copy_cube(arg->cube, c); - invert_cube(c); - compose(c, newarg.cube); + apply_alg(arg->current_alg, newarg.cube); + invert_cube(newarg.cube); + + copy_cube(arg->cube, &c); + invert_cube(&c); + compose(&c, newarg.cube); /* New indexes */ compute_ind(&newarg); - swapmove(&(newarg.last[0]), &(newarg.lastinv[0])); - swapmove(&(newarg.last[1]), &(newarg.lastinv[1])); + /* Swap last moves */ + for (i = 0; i < 2; i++) { + aux = newarg.last[i]; + newarg.last[i] = newarg.lastinv[i]; + newarg.lastinv[i] = aux; + } + newarg.niss = !(arg->niss); newarg.has_nissed = true; dfs(&newarg); - - free_alg(inv); - free(c); - free(newarg.cube); } static bool @@ -231,32 +259,55 @@ static bool niss_makes_sense(DfsArg *arg) { Cube testcube; + DfsArg aux; if (arg->niss || !arg->can_niss || arg->current_alg->len == 0) return false; make_solved(&testcube); apply_move(inverse_move(arg->last[0]), &testcube); - return estimate_step(arg->s, arg->ind) > 0; + aux.cube = &testcube; + aux.s = arg->s; + /* TODO: refactor compute_ind so we don't need full arg */ + compute_ind(&aux); + + return estimate_step(aux.s, aux.ind) > 0; +} + +bool +singlecwend(Alg *alg) +{ + int i; + bool nor, inv; + Move l2 = NULLMOVE, l1 = NULLMOVE, l2i = NULLMOVE, l1i = NULLMOVE; + + for (i = 0; i < alg->len; i++) { + if (alg->inv[i]) { + l2i = l1i; + l1i = alg->move[i]; + } else { + l2 = l1; + l1 = alg->move[i]; + } + } + + nor = l1 ==base_move(l1) && (!commute(l1, l2) ||l2 ==base_move(l2)); + inv = l1i==base_move(l1i) && (!commute(l1i,l2i)||l2i==base_move(l2i)); + + return nor && inv; } /* Public functions **********************************************************/ -AlgList * -solve(Cube *cube, char *stepstr, int m, SolutionType st, Trans t) +int +solve(Cube *cube, char *stepstr, int m, SolutionType st, Trans t, Alg *sol) { - int i; - AlgList *sols; - AlgListNode *node; + int i, n; + Alg alg; Cube c; DfsArg arg; Step *step; - /* TODO: checks for steps being ready and not solved are - done somewhere else */ - - sols = new_alglist(); - /* Prepare step TODO: remove all initialization! */ step = NULL; for (i = 0; steps[i] != NULL; i++) @@ -264,7 +315,7 @@ solve(Cube *cube, char *stepstr, int m, SolutionType st, Trans t) step = steps[i]; if (step == NULL) { fprintf(stderr, "No step to solve!\n"); - return sols; + return 0; } PDGenData pdg; pdg.moveset = step->moveset; @@ -283,6 +334,9 @@ solve(Cube *cube, char *stepstr, int m, SolutionType st, Trans t) } } + alg.len = 0; + n = 0; + /* Prepare cube for solve */ arg.cube = &c; copy_cube(cube, arg.cube); @@ -291,8 +345,11 @@ solve(Cube *cube, char *stepstr, int m, SolutionType st, Trans t) apply_trans(t, arg.cube); arg.s = step; compute_ind(&arg); + arg.t = t; + arg.st = st; arg.can_niss = st == NISS; - arg.sols = sols; + arg.nsols = &n; + arg.sols = sol; arg.d = m; arg.niss = false; arg.has_nissed = false; @@ -300,17 +357,10 @@ solve(Cube *cube, char *stepstr, int m, SolutionType st, Trans t) arg.last[1] = NULLMOVE; arg.lastinv[0] = NULLMOVE; arg.lastinv[1] = NULLMOVE; - arg.current_alg = new_alg(""); + arg.current_alg = &alg; dfs(&arg); - - for (node = sols->first; node != NULL; node = node->next) { - transform_alg(inverse_trans(t), node->alg); - if (st == INVERSE) - for (i = 0; i < node->alg->len; i++) - node->alg->inv[i] = true; - } - return sols; + return n; } diff --git a/src/solve.h b/src/solve.h @@ -2,10 +2,9 @@ #define SOLVE_H #include "pruning.h" -#include "alg.h" typedef enum { NORMAL, INVERSE, NISS } SolutionType; -AlgList *solve(Cube *cube, char *stepstr, int m, SolutionType st, Trans t); +int solve(Cube *cube, char *step, int m, SolutionType st, Trans t, Alg *sol); #endif