nissy-classic

Stable branch of nissy
git clone https://git.tronto.net/nissy-classic
Download | Log | Files | Refs | README | LICENSE

commit 4fb67201414169a2687f41c4056b2e284b4938cb
parent 3568412f8f230774d0d11d7ed1c897424f95d3ef
Author: Sebastiano Tronto <sebastiano.tronto@gmail.com>
Date:   Thu, 11 Nov 2021 22:05:00 +0100

Removed old files

Diffstat:
Dold/2020-unknown-date/cube_backup.c | 527-------------------------------------------------------------------------------
Dold/2020-unknown-date/cubeutils.c | 100-------------------------------------------------------------------------------
Dold/2020-unknown-date/cubeutils.h | 18------------------
Dold/2020-unknown-date/moves.c | 57---------------------------------------------------------
Dold/2020-unknown-date/moves.h | 9---------
Dold/2020-unknown-date/pieces.c | 208-------------------------------------------------------------------------------
Dold/2020-unknown-date/pieces.h | 59-----------------------------------------------------------
Dold/2021-02-06/cube.c | 664-------------------------------------------------------------------------------
Dold/2021-02-06/cube.h | 60------------------------------------------------------------
Dold/2021-02-06/main.c | 46----------------------------------------------
Dold/2021-02-06/solve.c | 177-------------------------------------------------------------------------------
Dold/2021-02-06/solve.h | 55-------------------------------------------------------
Dold/2021-02-06/utils.c | 197-------------------------------------------------------------------------------
Dold/2021-02-06/utils.h | 70----------------------------------------------------------------------
Dold/2021-02-18-piecefilter/compile.sh | 1-
Dold/2021-02-18-piecefilter/nissy | 0
Dold/2021-02-18-piecefilter/src/cube.c | 198-------------------------------------------------------------------------------
Dold/2021-02-18-piecefilter/src/cube.h | 45---------------------------------------------
Dold/2021-02-18-piecefilter/src/main.c | 47-----------------------------------------------
Dold/2021-02-18-piecefilter/src/moves.c | 482-------------------------------------------------------------------------------
Dold/2021-02-18-piecefilter/src/moves.h | 46----------------------------------------------
Dold/2021-02-18-piecefilter/src/solve.c | 179-------------------------------------------------------------------------------
Dold/2021-02-18-piecefilter/src/solve.h | 56--------------------------------------------------------
Dold/2021-02-18-piecefilter/src/transformations.c | 103-------------------------------------------------------------------------------
Dold/2021-02-18-piecefilter/src/transformations.h | 37-------------------------------------
Dold/2021-02-18-piecefilter/src/utils.c | 197-------------------------------------------------------------------------------
Dold/2021-02-18-piecefilter/src/utils.h | 70----------------------------------------------------------------------
Dold/2021-02-28-transformcube-works/src/cube.c | 271-------------------------------------------------------------------------------
Dold/2021-02-28-transformcube-works/src/cube.h | 55-------------------------------------------------------
Dold/2021-02-28-transformcube-works/src/main.c | 57---------------------------------------------------------
Dold/2021-02-28-transformcube-works/src/moves.c | 489-------------------------------------------------------------------------------
Dold/2021-02-28-transformcube-works/src/moves.h | 50--------------------------------------------------
Dold/2021-02-28-transformcube-works/src/solve.c | 180-------------------------------------------------------------------------------
Dold/2021-02-28-transformcube-works/src/solve.h | 56--------------------------------------------------------
Dold/2021-02-28-transformcube-works/src/transformations.c | 224-------------------------------------------------------------------------------
Dold/2021-02-28-transformcube-works/src/transformations.h | 34----------------------------------
Dold/2021-02-28-transformcube-works/src/utils.c | 197-------------------------------------------------------------------------------
Dold/2021-02-28-transformcube-works/src/utils.h | 70----------------------------------------------------------------------
Dold/2021-05-26-before-restyle/cube.c | 293-------------------------------------------------------------------------------
Dold/2021-05-26-before-restyle/cube.h | 65-----------------------------------------------------------------
Dold/2021-05-26-before-restyle/main.c | 24------------------------
Dold/2021-05-26-before-restyle/moves.c | 412-------------------------------------------------------------------------------
Dold/2021-05-26-before-restyle/moves.h | 51---------------------------------------------------
Dold/2021-05-26-before-restyle/solve.c | 180-------------------------------------------------------------------------------
Dold/2021-05-26-before-restyle/solve.h | 59-----------------------------------------------------------
Dold/2021-05-26-before-restyle/transformations.c | 200-------------------------------------------------------------------------------
Dold/2021-05-26-before-restyle/transformations.h | 34----------------------------------
Dold/2021-05-26-before-restyle/utils.c | 197-------------------------------------------------------------------------------
Dold/2021-05-26-before-restyle/utils.h | 70----------------------------------------------------------------------
Dold/2021-06-02-cleanedup/cube.c | 2010-------------------------------------------------------------------------------
Dold/2021-06-02-cleanedup/cube.h | 179-------------------------------------------------------------------------------
Dold/2021-06-02-cleanedup/main.c | 35-----------------------------------
Dold/2021-06-02-cleanedup/steps.h | 22----------------------
Dold/2021-06-14-oldalg/cube.c | 2849-------------------------------------------------------------------------------
Dold/2021-06-14-oldalg/cube.h | 73-------------------------------------------------------------------------
Dold/2021-06-14-oldalg/cubetypes.h | 210-------------------------------------------------------------------------------
Dold/2021-06-14-oldalg/main.c | 56--------------------------------------------------------
Dold/2021-06-15-before-separating-steps/cube.c | 2836-------------------------------------------------------------------------------
Dold/2021-06-15-before-separating-steps/cube.h | 72------------------------------------------------------------------------
Dold/2021-06-15-before-separating-steps/cubetypes.h | 201-------------------------------------------------------------------------------
Dold/2021-06-15-before-separating-steps/main.c | 60------------------------------------------------------------
Dold/2021-06-15-before-separating-steps/steps.h | 20--------------------
Dold/2021-06-17-cachedata/cube.c | 2738-------------------------------------------------------------------------------
Dold/2021-06-17-cachedata/cube.h | 79-------------------------------------------------------------------------------
Dold/2021-06-17-cachedata/cubetypes.h | 232-------------------------------------------------------------------------------
Dold/2021-06-17-cachedata/main.c | 63---------------------------------------------------------------
Dold/2021-06-17-cachedata/steps.c | 327-------------------------------------------------------------------------------
Dold/2021-06-17-cachedata/steps.h | 34----------------------------------
Dold/2021-06-23-realizing-bad-tables/HERE | 1-
Dold/2021-06-23-realizing-bad-tables/cube.c | 2844-------------------------------------------------------------------------------
Dold/2021-06-23-realizing-bad-tables/cube.h | 88-------------------------------------------------------------------------------
Dold/2021-06-23-realizing-bad-tables/cubetypes.h | 224-------------------------------------------------------------------------------
Dold/2021-06-23-realizing-bad-tables/main.c | 70----------------------------------------------------------------------
Dold/2021-06-23-realizing-bad-tables/steps.c | 486-------------------------------------------------------------------------------
Dold/2021-06-23-realizing-bad-tables/steps.h | 42------------------------------------------
Dold/2021-06-23-uint16t/cube.c | 2762-------------------------------------------------------------------------------
Dold/2021-06-23-uint16t/cube.h | 87-------------------------------------------------------------------------------
Dold/2021-06-23-uint16t/cubetypes.h | 224-------------------------------------------------------------------------------
Dold/2021-06-30-noreached/cube.c | 3394-------------------------------------------------------------------------------
Dold/2021-06-30-noreached/cube.h | 90-------------------------------------------------------------------------------
Dold/2021-06-30-noreached/cubetypes.h | 250-------------------------------------------------------------------------------
Dold/2021-06-30-noreached/macros.h | 23-----------------------
Dold/2021-06-30-noreached/main.c | 80-------------------------------------------------------------------------------
Dold/2021-06-30-noreached/steps.c | 307-------------------------------------------------------------------------------
Dold/2021-06-30-noreached/steps.h | 24------------------------
Dold/2021-06-30-reached/cube.c | 3419-------------------------------------------------------------------------------
Dold/2021-06-30-reached/cube.h | 90-------------------------------------------------------------------------------
Dold/2021-06-30-reached/cubetypes.h | 251-------------------------------------------------------------------------------
Dold/2021-06-30-reached/macros.h | 23-----------------------
Dold/2021-06-30-reached/main.c | 80-------------------------------------------------------------------------------
Dold/2021-06-30-reached/steps.c | 307-------------------------------------------------------------------------------
Dold/2021-06-30-reached/steps.h | 24------------------------
Dold/2021-07-02-genptable-dfs/cube.c | 3394-------------------------------------------------------------------------------
Dold/2021-07-02-genptable-dfs/cube.h | 90-------------------------------------------------------------------------------
Dold/2021-07-02-genptable-dfs/cubetypes.h | 250-------------------------------------------------------------------------------
Dold/2021-07-02-genptable-dfs/macros.h | 23-----------------------
Dold/2021-07-02-genptable-dfs/main.c | 80-------------------------------------------------------------------------------
Dold/2021-07-02-genptable-dfs/steps.c | 307-------------------------------------------------------------------------------
Dold/2021-07-02-genptable-dfs/steps.h | 24------------------------
Dold/2021-07-15-almostbeforerefactor/README | 3---
Dold/2021-07-15-almostbeforerefactor/alg.c | 3388-------------------------------------------------------------------------------
Dold/2021-07-15-almostbeforerefactor/alg.h | 27---------------------------
Dold/2021-07-15-almostbeforerefactor/cube.c | 3391-------------------------------------------------------------------------------
Dold/2021-07-15-almostbeforerefactor/cube.h | 79-------------------------------------------------------------------------------
Dold/2021-07-15-almostbeforerefactor/cubetypes.h | 252-------------------------------------------------------------------------------
Dold/2021-07-15-almostbeforerefactor/macros.h | 23-----------------------
Dold/2021-07-15-almostbeforerefactor/main.c | 60------------------------------------------------------------
Dold/2021-07-15-almostbeforerefactor/nissy | 0
Dold/2021-07-15-almostbeforerefactor/steps.c | 284-------------------------------------------------------------------------------
Dold/2021-07-15-almostbeforerefactor/steps.h | 24------------------------
Dold/2021-11-10-beforeremovingchecker/alg.c | 366-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/alg.h | 35-----------------------------------
Dold/2021-11-10-beforeremovingchecker/commands.c | 329-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/commands.h | 13-------------
Dold/2021-11-10-beforeremovingchecker/coord.c | 629-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/coord.h | 40----------------------------------------
Dold/2021-11-10-beforeremovingchecker/cube.c | 716-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/cube.h | 40----------------------------------------
Dold/2021-11-10-beforeremovingchecker/cubetypes.h | 298-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/env.c | 45---------------------------------------------
Dold/2021-11-10-beforeremovingchecker/env.h | 15---------------
Dold/2021-11-10-beforeremovingchecker/moves.c | 474-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/moves.h | 16----------------
Dold/2021-11-10-beforeremovingchecker/pf.c | 80-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/pf.h | 18------------------
Dold/2021-11-10-beforeremovingchecker/pruning.c | 272-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/pruning.h | 23-----------------------
Dold/2021-11-10-beforeremovingchecker/shell.c | 99-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/shell.h | 13-------------
Dold/2021-11-10-beforeremovingchecker/solve.c | 209-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/solve.h | 9---------
Dold/2021-11-10-beforeremovingchecker/steps.c | 916-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/steps.h | 10----------
Dold/2021-11-10-beforeremovingchecker/symcoord.c | 359-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/symcoord.h | 15---------------
Dold/2021-11-10-beforeremovingchecker/trans.c | 372-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/trans.h | 13-------------
Dold/2021-11-10-beforeremovingchecker/utils.c | 274-------------------------------------------------------------------------------
Dold/2021-11-10-beforeremovingchecker/utils.h | 41-----------------------------------------
Dold/backup-manysteps-pretrans/steps.c | 369-------------------------------------------------------------------------------
Dold/backup-manysteps-pretrans/steps.h | 36------------------------------------
Dold/coord.c | 1014-------------------------------------------------------------------------------
Dold/coord.h | 45---------------------------------------------
Dold/utils.c | 294-------------------------------------------------------------------------------
Dold/utils.h | 59-----------------------------------------------------------
145 files changed, 0 insertions(+), 53517 deletions(-)

diff --git a/old/2020-unknown-date/cube_backup.c b/old/2020-unknown-date/cube_backup.c @@ -1,527 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include "cube.h" - -/* The next few functions are used to convert from the Cube structure - * representation to actual arrays of pieces. */ -void cube_to_ep_array(Cube cube, int ep[12]); -void cube_to_eofb_array(Cube cube, int eo[12]); -void cube_to_eorl_array(Cube cube, int eo[12]); -void cube_to_eoud_array(Cube cube, int eo[12]); -void cube_to_cp_array(Cube cube, int cp[8]); -void cube_to_coud_array(Cube cube, int co[8]); -void cube_to_cofb_array(Cube cube, int co[8]); -void cube_to_corl_array(Cube cube, int co[8]); -void cube_to_centerpos_array(Cube cube, int centerpos[6]); -Cube ep_array_to_cube(int ep[12]); -Cube eofb_array_to_cube(int eo[12]); -Cube eorl_array_to_cube(int eo[12]); -Cube eoud_array_to_cube(int eo[12]); -Cube cp_array_to_cube(int cp[8]); -Cube coud_array_to_cube(int co[8]); -Cube cofb_array_to_cube(int co[8]); -Cube corl_array_to_cube(int co[8]); -Cube centerpos_array_to_cube(int centerpos[6]); -Cube move_array(Cube cube, void (cube_to_arr)(Cube, int *), - Cube (*arr_to_cube)(int *), - int *perm, int *orient, int n, int m); - - -/* Transition tables */ -int epose_ttable[NMOVES][factorial12/factorial8]; -int eposs_ttable[NMOVES][factorial12/factorial8]; -int eposm_ttable[NMOVES][factorial12/factorial8]; -int eofb_ttable[NMOVES][pow2to11]; -int eorl_ttable[NMOVES][pow2to11]; -int eoud_ttable[NMOVES][pow2to11]; -int cp_ttable[NMOVES][factorial8]; -int coud_ttable[NMOVES][pow3to7]; -int cofb_ttable[NMOVES][pow3to7]; -int corl_ttable[NMOVES][pow3to7]; -int centerpos_ttable[NMOVES][factorial6]; - -char edge_string[12][5] = { - "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" -}; -char corner_string[8][5] = { "UFR", "UFL", "UBL", "UBR", "DFR", "DFL", "DBL", "DBR" }; -char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; -char move_string[NMOVES][5] = { - "-", - "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", - "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", - "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", - "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", - "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", - "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'", -}; - -int epe_solved[] = {FR, FL, BL, BR}; -int eps_solved[] = {UL, UR, DL, DR}; -int epm_solved[] = {UF, UB, DF, DB}; - -/**************************/ -/* Internal use functions */ -/**************************/ - -int cube_to_ep_array(Cube cube, int ep[12]) { - int epe[4], eps[4], epm[4]; - index_to_perm(cube.epose % factorial(4), 4, epe); - index_to_perm(cube.eposs % factorial(4), 4, eps); - index_to_perm(cube.eposm % factorial(4), 4, epm); - - int epose[12], eposs[12], eposm[12]; - index_to_subset(cube.epose / factorial(4), 12, 4, epose); - index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); - index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); - for (int i = 0; i < 4; i++) { - swap(&eposs[eps_solved[i]], &eposs[i+8]); - swap(&eposm[epm_solved[i]], &eposm[i+8]); - } - - for (int i = 0, ie = 0, is = 0, im = 0; i < 12; i++) { - if (epose[i]) ep[i] = epe_solved[epe[ie++]]; - if (eposs[i]) ep[i] = eps_solved[eps[is++]]; - if (eposm[i]) ep[i] = epm_solved[epm[im++]]; - } -} - -void cube_to_eofb_array(Cube cube, int eo[12]) { - int_to_sum_zero_array(cube.eofb, 2, 12, eo); -} - -void cube_to_eorl_array(Cube cube, int eo[12]) { - int_to_sum_zero_array(cube.eorl, 2, 12, eo); -} - -void cube_to_eoud_array(Cube cube, int eo[12]) { - int_to_sum_zero_array(cube.eoud, 2, 12, eo); -} - -void cube_to_cp_array(Cube cube, int cp[8]) { - index_to_perm(cube.cp, 8, cp); -} - -void cube_to_coud_array(Cube cube, int co[8]) { - int_to_sum_zero_array(cube.coud, 3, 8, co); -} - -void cube_to_cofb_array(Cube cube, int co[8]) { - int_to_sum_zero_array(cube.cofb, 3, 8, co); -} - -void cube_to_corl_array(Cube cube, int co[8]) { - int_to_sum_zero_array(cube.corl, 3, 8, co); -} - -void cube_to_centerpos_array(Cube cube, int centerpos[6]) { - index_to_perm(cube.centerpos, 6, centerpos); -} - -Cube ep_array_to_cube(int ep[12]) { - int epe[4], eps[4], epm[4]; - int epose[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int eposs[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int eposm[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - for (int i = 0, ie = 0, is = 0, im = 0; i < 12; i++) { - for (int j = 0; j < 4; j++) { - if (ep[i] == epe_solved[j]) { epe[ie++] = j; epose[i] = 1; } - if (ep[i] == eps_solved[j]) { eps[is++] = j; eposs[i] = 1; } - if (ep[i] == epm_solved[j]) { epm[im++] = j; eposm[i] = 1; } - } - } - for (int i = 0; i < 4; i++) { - swap(&eposs[eps_solved[i]], &eposs[i+8]); - swap(&eposm[epm_solved[i]], &eposm[i+8]); - } - return { .epose = factorial(4) * subset_to_index(epose, 12, 4) - + perm_to_index(epe, 4), - .eposs = factorial(4) * subset_to_index(eposs, 12, 4) - + perm_to_index(eps, 4), - .eposm = factorial(4) * subset_to_index(eposm, 12, 4) - + perm_to_index(epm, 4) }; -} - -Cube eofb_array_to_cube(int eo[12]) { - return { .eofb = digit_array_to_int(eo, 11, 2) }; -} - -Cube eorl_array_to_cube(int eo[12]) { - return { .eorl = digit_array_to_int(eo, 11, 2) }; -} - -Cube eoud_array_to_cube(int eo[12]) { - return { .eoud = digit_array_to_int(eo, 11, 2) }; -} - -Cube cp_array_to_cube(int cp[8]) { - return { .cp = perm_to_index(cp, 8) }; -} - -Cube coud_array_to_cube(int co[8]) { - return { .coud = digit_array_to_int(co, 7, 3) }; -} - -Cube cofb_array_to_cube(int co[8]) { - return { .cofb = digit_array_to_int(co, 7, 3) }; -} - -Cube corl_array_to_cube(int co[8]) { - return { .corl = digit_array_to_int(co, 7, 3) }; -} - -Cube centerpos_array_to_cube(int centerpos[6]) { - return { .centerpos = perm_to_index(centerpos, 6) }; -} - -Cube move_array(Cube cube, void (*cube_to_arr)(Cube, int *), - void (*arr_to_cube)(int *), - int *perm, int *orient, int n, int m) { - int arr[n]; - cube_to_arr(cube, arr); - apply_permutation(perm, arr, n); - sum_arrays_mod(arr, orient, n, m); - return arr_to_cube(arr); -} - -/***********************/ -/* Interface functions */ -/***********************/ - -Move inverse(Move m) { - if (m == NULLMOVE) - return m; - int mod = (m-1)%3; - Move base = m - mod; - return base + 2 - mod; -} - -void copy_alg(NissMove *src, NissMove *dest) { - for (int i = 0; src[i].m != NULLMOVE; i++) - dest[i] = src[i]; -} - -bool commute(Move m1, Move m2) { - return equal(apply_move(m2, apply_move(m1, {0})), - apply_move(m1, apply_move(m2, {0}))); -} - -bool equal(Cube c1, Cube c2) { - return c1.eofb == c2.eofb && c1.epose == c2.epose && - c1.eposs == c2.eposs && c1.eposm == c2.eposm && - c1.coud == c2.coud && c1.cp == c2.cp && - c1.centerpos == c2.centerpos; -} - -bool solvable(Cube cube) { - /* Since we memorize orientation truncating the last digit, we only need to - * check that the permutations have the correct sign. */ - /* TODO: add check that every integer is in range */ - int ep[12], cp[12], c[6]; - /* TODO: change to use cube-specific functions */ - cube_to_ep_array(cube, ep); - cube_to_cp_array(cube, 8, cp); - cube_to_centerpos_array(cube, 6, c); - return (perm_sign(ep, 12) ^ perm_sign(c, 6)) == perm_sign(cp, 8); -} - -bool is_solved(Cube cube) { - return (!cube.eofb && !cube.coud && !cube.cp && - !cube.epose && !cube.eposs && !cube.eposm && !cube.centerpos); -} - -char *to_string(Cube cube) { - int eo[12], co[8], ep[12], cp[8], cenpos[6]; - cube_to_eofb_array(cube, eo); - cube_to_coud_array(cube, co); - cube_to_ep_array(cube, ep); - cube_to_cp_array(cube, cp); - cube_to_centerpos_array(cube, cenpos); - - static char ret[1000]; - - for (int i = 0; i < 12; i++) { - strcat(ret, " "); - strcat(ret, edge_string[ep[i]]); - strcat(ret, " "); - } - strcat(ret, "\n"); - for (int i = 0; i < 12; i++) { - strcat(ret, " "); - char num[2] = { [0] = eo[i] + '0', [1] = 0 }; - strcat(ret, num); - strcat(ret, " "); - } - strcat(ret, "\n"); - for (int i = 0; i < 8; i++) { - strcat(ret, corner_string[cp[i]]); - strcat(ret, " "); - } - strcat(ret, "\n"); - for (int i = 0; i < 8; i++) { - strcat(ret, " "); - char num[2] = { [0] = co[i] + '0', [1] = 0 }; - strcat(ret, num); - strcat(ret, " "); - } - strcat(ret, "\n"); - for (int i = 0; i < 6; i++) { - strcat(ret, " "); - strcat(ret, center_string[cenpos[i]]); - strcat(ret, " "); - } - strcat(ret, "\n"); - - return ret; -} - -void init_ttables() { - FILE *ttf; - - if ((ttf = fopen("ttables", "rb")) != NULL) { - for (int m = 0; m < NMOVES; m++) { - fread(epose_ttable[m], sizeof(int), factorial12/factorial8, ttf); - fread(eposs_ttable[m], sizeof(int), factorial12/factorial8, ttf); - fread(eposm_ttable[m], sizeof(int), factorial12/factorial8, ttf); - fread(eofb_ttable[m], sizeof(int), pow2to11, ttf); - fread(eorl_ttable[m], sizeof(int), pow2to11, ttf); - fread(eoud_ttable[m], sizeof(int), pow2to11, ttf); - fread(cp_ttable[m], sizeof(int), factorial8, ttf); - fread(coud_ttable[m], sizeof(int), pow3to7, ttf); - fread(corl_ttable[m], sizeof(int), pow3to7, ttf); - fread(cofb_ttable[m], sizeof(int), pow3to7, ttf); - fread(centerpos_ttable[m], sizeof(int), factorial6, ttf); - } - fclose(ttf); - } else { - ttf = fopen("ttables", "wb"); - int empty[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - /* For each type of pieces only the effects of U, x and y are described */ - int edge_cycle[NMOVES][12] = { - [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, - [X] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, - [Y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL}, - }; - int eofb_flipped[NMOVES][12] = { - [X] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [Y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 }, - }; - int eorl_flipped[NMOVES][12] = { - [X] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [Y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 }, - }; - int eoud_flipped[NMOVES][12] = { - [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, - [X] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [Y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - }; - int corner_cycle[NMOVES][8] = { - [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, - [X] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, - [Y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL}, - }; - int coud_flipped[NMOVES][8] = { - [X] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2}, - }; - int corl_flipped[NMOVES][8] = { - [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, - [Y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1}, - }; - int cofb_flipped[NMOVES][8] = { - [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, - [X] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=2,[UFL]=1,[DBL]=1,[DFL]=2}, - [Y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2}, - }; - int center_cycle[NMOVES][6] = { - [X] = {F_center, B_center, R_center, L_center, D_center, U_center}, - [Y] = {U_center, D_center, B_center, F_center, R_center, L_center}, - }; - - /* Each move is reduced to a combination of U, x and y using this table */ - Move equiv_moves[NMOVES][13] = { - [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D] = { X, X, U, X, X, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D2] = { X, X, U, U, X, X, 0, 0, 0, 0, 0, 0, 0 }, - [D3] = { X, X, U, U, U, X, X, 0, 0, 0, 0, 0, 0 }, - [R] = { Y, X, U, X, X, X, Y, Y, Y, 0, 0, 0, 0 }, - [R2] = { Y, X, U, U, X, X, X, Y, Y, Y, 0, 0, 0 }, - [R3] = { Y, X, U, U, U, X, X, X, Y, Y, Y, 0, 0 }, - [L] = { Y, Y, Y, X, U, X, X, X, Y, 0, 0, 0, 0 }, - [L2] = { Y, Y, Y, X, U, U, X, X, X, Y, 0, 0, 0 }, - [L3] = { Y, Y, Y, X, U, U, U, X, X, X, Y, 0, 0 }, - [F] = { X, U, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F2] = { X, U, U, X, X, X, 0, 0, 0, 0, 0, 0, 0 }, - [F3] = { X, U, U, U, X, X, X, 0, 0, 0, 0, 0, 0 }, - [B] = { X, X, X, U, X, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B2] = { X, X, X, U, U, X, 0, 0, 0, 0, 0, 0, 0 }, - [B3] = { X, X, X, U, U, U, X, 0, 0, 0, 0, 0, 0 }, - - [Uw] = { X, X, U, X, X, Y, 0, 0, 0, 0, 0, 0, 0 }, - [Uw2] = { X, X, U, U, X, X, Y, Y, 0, 0, 0, 0, 0 }, - [Uw3] = { X, X, U, U, U, X, X, Y, Y, Y, 0, 0, 0 }, - [Dw] = { U, Y, Y, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw2] = { U, U, Y, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw3] = { U, U, U, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Rw] = { Y, Y, Y, X, U, X, X, X, Y, X, 0, 0, 0 }, - [Rw2] = { Y, Y, Y, X, U, U, X, X, X, Y, X, X, 0 }, - [Rw3] = { Y, Y, Y, X, U, U, U, Y, X, X, X, Y, 0 }, - [Lw] = { Y, X, U, X, X, X, Y, Y, Y, X, X, X, 0 }, - [Lw2] = { Y, X, U, U, X, X, X, Y, Y, Y, X, X, 0 }, - [Lw3] = { Y, X, U, U, U, X, X, X, Y, Y, Y, X, 0 }, - [Fw] = { X, X, X, U, Y, Y, Y, X, 0, 0, 0, 0, 0 }, - [Fw2] = { X, X, X, U, U, Y, Y, X, 0, 0, 0, 0, 0 }, - [Fw3] = { X, X, X, U, U, U, Y, X, 0, 0, 0, 0, 0 }, - [Bw] = { X, U, Y, Y, Y, X, X, X, 0, 0, 0, 0, 0 }, - [Bw2] = { X, U, U, Y, Y, X, X, X, 0, 0, 0, 0, 0 }, - [Bw3] = { X, U, U, U, Y, X, X, X, 0, 0, 0, 0, 0 }, - - [M] = { Y, X, U, X, X, U, U, U, Y, X, Y, Y, Y }, - [M2] = { Y, X, U, U, X, X, U, U, X, X, X, Y, 0 }, - [M3] = { Y, X, U, U, U, X, X, U, Y, X, X, X, Y }, - [S] = { X, U, U, U, X, X, U, Y, Y, Y, X, 0, 0 }, - [S2] = { X, U, U, X, X, U, U, Y, Y, X, 0, 0, 0 }, - [S3] = { X, U, X, X, U, U, U, Y, X, 0, 0, 0, 0 }, - [E] = { U, X, X, U, U, U, X, X, Y, Y, Y, 0, 0 }, - [E2] = { U, U, X, X, U, U, X, X, Y, Y, 0, 0, 0 }, - [E3] = { U, U, U, X, X, U, X, X, Y, 0, 0, 0, 0 }, - - [X] = { X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [X2] = { X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [X3] = { X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Y] = { Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Y2] = { Y, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Y3] = { Y, Y, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Z] = { Y, Y, Y, X, Y, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Z2] = { Y, Y, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Z3] = { Y, X, Y, Y, Y, 0, 0, 0, 0, 0, 0, 0, 0 }, - }; - - /* Generate all move cycles and flips */ - for (int i = 0; i < NMOVES; i++) { - if (i == U || i == X || i == Y) - continue; - - Cube cube = {0}; - - cube_to_ep_array(&cube, edge_cycle[i]); - cube_to_eofb_array(&cube, eofb_flipped[i]); - cube_to_eorl_array(&cube, eorl_flipped[i]); - cube_to_eoud_array(&cube, eoud_flipped[i]); - cube_to_cp_array(&cube, corner_cycle[i]); - cube_to_coud_array(&cube, coud_flipped[i]); - cube_to_cofb_array(&cube, cofb_flipped[i]); - cube_to_corl_array(&cube, corl_flipped[i]); - cube_to_centerpos_array(&cube, center_cycle[i]); - - for (int j = 0; equiv_moves[i][j]; j++) { - int m = equiv_moves[i][j]; - - apply_permutation(edge_cycle[m], edge_cycle[i], 12); - apply_permutation(edge_cycle[m], eofb_flipped[i], 12); - apply_permutation(edge_cycle[m], eorl_flipped[i], 12); - apply_permutation(edge_cycle[m], eoud_flipped[i], 12); - - sum_arrays_mod(eofb_flipped[i], eofb_flipped[m], 12, 2); - sum_arrays_mod(eorl_flipped[i], eorl_flipped[m], 12, 2); - sum_arrays_mod(eoud_flipped[i], eoud_flipped[m], 12, 2); - - apply_permutation(corner_cycle[m], corner_cycle[i], 8); - apply_permutation(corner_cycle[m], coud_flipped[i], 8); - apply_permutation(corner_cycle[m], cofb_flipped[i], 8); - apply_permutation(corner_cycle[m], corl_flipped[i], 8); - - sum_arrays_mod(coud_flipped[i], coud_flipped[m], 8, 3); - sum_arrays_mod(corl_flipped[i], corl_flipped[m], 8, 3); - sum_arrays_mod(cofb_flipped[i], cofb_flipped[m], 8, 3); - - apply_permutation(center_cycle[m], center_cycle[i], 6); - } - } - - /* Initialize transition tables */ - for (int m = 0; m < NMOVES; m++) { - for (int i = 0; i < factorial12/factorial8; i++) { - Cube cube = { .epose = i }; - move_array(&cube, cube_to_ep_array, ep_array_to_cube, - edge_cycle[m], empty, 12, 1); - epose_ttable[m][i] = cube.epose; - cube.eposs = i; - move_array(&cube, cube_to_ep_array, ep_array_to_cube, - edge_cycle[m], empty, 12, 1); - eposs_ttable[m][i] = cube.eposs; - cube.eposm = i; - move_array(&cube, cube_to_ep_array, ep_array_to_cube, - edge_cycle[m], empty, 12, 1); - eposm_ttable[m][i] = cube.eposm; - } - for (int i = 0; i < pow2to11; i++ ) { - Cube cube = { .eofb = i, .eorl = i, .eoud = i }; - move_array(&cube, cube_to_eofb_array, eofb_array_to_cube, - edge_cycle[m], eofb_flipped[m], 12, 2); - move_array(&cube, cube_to_eorl_array, eorl_array_to_cube, - edge_cycle[m], eorl_flipped[m], 12, 2); - move_array(&cube, cube_to_eoud_array, eoud_array_to_cube, - edge_cycle[m], eoud_flipped[m], 12, 2); - eofb_ttable[m][i] = cube.eofb; - eorl_ttable[m][i] = cube.eorl; - eoud_ttable[m][i] = cube.eoud; - } - for (int i = 0; i < factorial8; i++) { - /* TODO: Maybe do this by hand to optimize? */ - Cube cube = { .cp = i }; - move_array(&cube, cube_to_cp_array, ep_array_to_cube, - corner_cycle[m], empty, 8, 1); - cp_ttable[m][i] = cube.cp; - } - for (int i = 0; i < pow3to7; i++) { - Cube cube = { .coud = i, .corl = i, .cofb = i }; - move_array(&cube, cube_to_coud_array, coud_array_to_cube, - corner_cycle[m], coud_flipped[m], 8, 3); - move_array(&cube, cube_to_corl_array, corl_array_to_cube, - corner_cycle[m], corl_flipped[m], 8, 3); - move_array(&cube, cube_to_cofb_array, cofb_array_to_cube, - corner_cycle[m], cofb_flipped[m], 8, 3); - coud_ttable[m][i] = cube.coud; - corl_ttable[m][i] = cube.corl; - cofb_ttable[m][i] = cube.cofb; - } - for (int i = 0; i < factorial6; i++) { - Cube cube = { .centerpos = i }; - move_array(&cube, cube_to_centerpos_array, centerpos_array_to_cube, - center_cycle[m], empty, 6, 1); - centerpos_ttable[m][i] = cube.centerpos; - } - fwrite(epose_ttable[m], sizeof(int), factorial12/factorial8, ttf); - fwrite(eposs_ttable[m], sizeof(int), factorial12/factorial8, ttf); - fwrite(eposm_ttable[m], sizeof(int), factorial12/factorial8, ttf); - fwrite(eofb_ttable[m], sizeof(int), pow2to11, ttf); - fwrite(eorl_ttable[m], sizeof(int), pow2to11, ttf); - fwrite(eoud_ttable[m], sizeof(int), pow2to11, ttf); - fwrite(cp_ttable[m], sizeof(int), factorial8, ttf); - fwrite(coud_ttable[m], sizeof(int), pow3to7, ttf); - fwrite(corl_ttable[m], sizeof(int), pow3to7, ttf); - fwrite(cofb_ttable[m], sizeof(int), pow3to7, ttf); - fwrite(centerpos_ttable[m], sizeof(int), factorial6, ttf); - } - fclose(ttf); - } -} - -Cube apply_move(Move m, Cube cube) { - Cube moved = cube; - - moved.eofb = eofb_ttable[m][cube.eofb]; - moved.eorl = eorl_ttable[m][cube.eorl]; - moved.eoud = eoud_ttable[m][cube.eoud]; - moved.coud = coud_ttable[m][cube.coud]; - moved.cofb = cofb_ttable[m][cube.cofb]; - moved.corl = corl_ttable[m][cube.corl]; - moved.epose = epose_ttable[m][cube.epose]; - moved.eposs = eposs_ttable[m][cube.eposs]; - moved.eposm = eposm_ttable[m][cube.eposm]; - moved.cp = cp_ttable[m][cube.cp]; - moved.centerpos = centerpos_ttable[m][cube.centerpos]; - - return moved; -} diff --git a/old/2020-unknown-date/cubeutils.c b/old/2020-unknown-date/cubeutils.c @@ -1,100 +0,0 @@ -#include <stdio.h> -#include "utils.h" -#include "pieces.h" -#include "cubeutils.h" - -int epe_solved[] = {FR, FL, BL, BR}; -int eps_solved[] = {UL, UR, DL, DR}; -int epm_solved[] = {UF, UB, DF, DB}; - -void cube_to_ep_array(Cube *cube, int ep[12]) { - int epe[4], eps[4], epm[4]; - index_to_perm(cube->epose % factorial(4), 4, epe); - index_to_perm(cube->eposs % factorial(4), 4, eps); - index_to_perm(cube->eposm % factorial(4), 4, epm); - - int epose[12], eposs[12], eposm[12]; - index_to_subset(cube->epose / factorial(4), 12, 4, epose); - index_to_subset(cube->eposs / factorial(4), 12, 4, eposs); - index_to_subset(cube->eposm / factorial(4), 12, 4, eposm); - for (int i = 0; i < 4; i++) { - swap(&eposs[eps_solved[i]], &eposs[i+8]); - swap(&eposm[epm_solved[i]], &eposm[i+8]); - } - - for (int i = 0, ie = 0, is = 0, im = 0; i < 12; i++) { - if (epose[i]) ep[i] = epe_solved[epe[ie++]]; - if (eposs[i]) ep[i] = eps_solved[eps[is++]]; - if (eposm[i]) ep[i] = epm_solved[epm[im++]]; - } -} - -void ep_array_to_epos(int ep[12], Cube *cube) { - int epe[4], eps[4], epm[4]; - int epose[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int eposs[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int eposm[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - for (int i = 0, ie = 0, is = 0, im = 0; i < 12; i++) { - for (int j = 0; j < 4; j++) { - if (ep[i] == epe_solved[j]) { epe[ie++] = j; epose[i] = 1; } - if (ep[i] == eps_solved[j]) { eps[is++] = j; eposs[i] = 1; } - if (ep[i] == epm_solved[j]) { epm[im++] = j; eposm[i] = 1; } - } - } - for (int i = 0; i < 4; i++) { - swap(&eposs[eps_solved[i]], &eposs[i+8]); - swap(&eposm[epm_solved[i]], &eposm[i+8]); - } - cube->epose = factorial(4) * subset_to_index(epose, 12, 4) - + perm_to_index(epe, 4); - cube->eposs = factorial(4) * subset_to_index(eposs, 12, 4) - + perm_to_index(eps, 4); - cube->eposm = factorial(4) * subset_to_index(eposm, 12, 4) - + perm_to_index(epm, 4); -} - -bool solvable(Cube *cube) { - /* Since we memorize orientation truncating the last digit, we only need to - * check that the permutations have the correct sign. */ - /* TODO: add check that every integer is in range */ - int ep[12], cp[12], c[6]; - cube_to_ep_array(cube, ep); - index_to_perm(cube->cp, 8, cp); - index_to_perm(cube->centerpos, 6, c); - return (perm_sign(ep, 12) ^ perm_sign(c, 6)) == perm_sign(cp, 8); -} - -Cube *solved_cube() { - static Cube cube = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - return &cube; -} - -bool solved(Cube *cube) { - return (cube->eofb == 0 && cube->coud == 0 && cube->cp == 0 && - cube->epose == 0 && cube->eposs == 0 && cube->eposm == 0 && - cube->centerpos == 0); -} - -char *to_string(Cube *cube) { - int eo[12], co[8], ep[12], cp[8], cenpos[6]; - cube_to_eofb_array(cube->eofb, eo); - cube_to_coud_array(cube->coud, co); - cube_to_ep_array(cube, ep); - cube_to_cp_array(cube->cp, cp); - cube_to_centerpos_array(cube->centerpos, cenpos); - - char *ret[1000]; - - for (int i = 0; i < 12; i++) sprintf(ret, " %s ", edge_string[ep[i]]); - sprintf(ret, "\n"); - for (int i = 0; i < 12; i++) sprintf(ret, " %d ", eo[i]); - sprintf(ret, "\n"); - for (int i = 0; i < 8; i++) sprintf(ret, "%s ", corner_string[cp[i]]); - sprintf(ret, "\n"); - for (int i = 0; i < 8; i++) sprintf(ret, " %d ", co[i]); - sprintf(ret, "\n"); - for (int i = 0; i < 6; i++) sprintf(ret, " %s ", center_string[cenpos[i]]); - sprintf(ret, "\n"); - - return ret; -} diff --git a/old/2020-unknown-date/cubeutils.h b/old/2020-unknown-date/cubeutils.h @@ -1,18 +0,0 @@ -/* Cube-specific utility functions */ - -#ifndef CUBEUTILS_H -#define CUBEUTILS_H - -#include <stdbool.h> -#include "pieces.h" - -void cube_to_ep_array(Cube *cube, int ep[12]); -void ep_array_to_epos(int ep[12], Cube *cube); - -Cube *solved_cube(); -bool solvable(Cube *cube); -bool solved(Cube *cube); - -void print(Cube *cube); - -#endif diff --git a/old/2020-unknown-date/moves.c b/old/2020-unknown-date/moves.c @@ -1,57 +0,0 @@ -#include <stdbool.h> -#include "pieces.h" -#include "moves.h" -#include "utils.h" - -/* Transition tables */ -int eofb_ttable[pow2to11][NULLMOVE]; -int eorl_ttable[pow2to11][NULLMOVE]; -int eoud_ttable[pow2to11][NULLMOVE]; -int coud_ttable[pow3to7][NULLMOVE]; -int cofb_ttable[pow3to7][NULLMOVE]; -int corl_ttable[pow3to7][NULLMOVE]; -int epose_ttable[factorial12/factorial8][NULLMOVE]; -int eposs_ttable[factorial12/factorial8][NULLMOVE]; -int eposm_ttable[factorial12/factorial8][NULLMOVE]; -int cp_ttable[factorial8][NULLMOVE]; -int centerpos_ttable[factorial6][NULLMOVE]; - -void apply_move_ep(Move m, int a[12]) { - int aux[12]; - intarrcopy(a, aux, 12); - for (int i = 0; i < 12; i++) - a[i] = aux[edge_cycle[m][i]]; -} - -void apply_move_cp(Move m, int a[8]) { - int aux[8]; - intarrcopy(a, aux, 8); - for (int i = 0; i < 8; i++) - a[i] = aux[corner_cycle[m][i]]; -} - -void apply_move_centerpos(Move m, int a[6]) { - int aux[6]; - intarrcopy(a, aux, 6); - for (int i = 0; i < 6; i++) - a[i] = aux[center_cycle[m][i]]; -} - -void init_ttables() { - /* TODO */ -} - -void apply_move(Move m, Cube *cube) { - cube->eofb = eofb_ttable[cube->eofb][m]; - cube->eorl = eorl_ttable[cube->eorl][m]; - cube->eoud = eoud_ttable[cube->eoud][m]; - cube->coud = coud_ttable[cube->coud][m]; - cube->cofb = cofb_ttable[cube->cofb][m]; - cube->corl = corl_ttable[cube->corl][m]; - cube->epose = epose_ttable[cube->epose][m]; - cube->eposs = eposs_ttable[cube->eposs][m]; - cube->eposm = eposm_ttable[cube->eposm][m]; - cube->cp = cp_ttable[cube->cp][m]; - cube->centerpos = centerpos_ttable[cube->centerpos][m]; -} - diff --git a/old/2020-unknown-date/moves.h b/old/2020-unknown-date/moves.h @@ -1,9 +0,0 @@ -/* Moves and transition tables */ - -#ifndef MOVES_H -#define MOVES_H - -void apply_move(Move m, Cube *cube); -void init_ttables(); - -#endif diff --git a/old/2020-unknown-date/pieces.c b/old/2020-unknown-date/pieces.c @@ -1,208 +0,0 @@ -#include "pieces.h" - -char edge_string[12][5] = { - "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" -}; - -char corner_string[8][5] = { - "UFR", "UFL", "UBL", "UBR", "DFR", "DFL", "DBL", "DBR" -}; - -char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; - -char move_string[NULLMOVE+1][5] = { - "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", - "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", - "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", - "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", - "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", - "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'", - "-" -}; - -int edge_cycle[NULLMOVE+1][12] = { - [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, - [U2] = {UB, UR, UF, UL, DF, DL, DB, DR, FR, FL, BL, BR}, - [U3] = {UL, UB, UR, UF, DF, DL, DB, DR, FR, FL, BL, BR}, - [D] = {UF, UL, UB, UR, DL, DB, DR, DF, FR, FL, BL, BR}, - [D2] = {UF, UL, UB, UR, DB, DR, DF, DL, FR, FL, BL, BR}, - [D3] = {UF, UL, UB, UR, DR, DF, DL, DB, FR, FL, BL, BR}, - [R] = {UF, UL, UB, FR, DF, DL, DB, BR, DR, FL, BL, UR}, - [R2] = {UF, UL, UB, DR, DF, DL, DB, UR, BR, FL, BL, FR}, - [R3] = {UF, UL, UB, BR, DF, DL, DB, FR, UR, FL, BL, DR}, - [L] = {UF, BL, UB, UR, DF, FL, DB, DR, FR, UL, DL, BR}, - [L2] = {UF, DL, UB, UR, DF, UL, DB, DR, FR, BL, FL, BR}, - [L3] = {UF, FL, UB, UR, DF, BL, DB, DR, FR, DL, UL, BR}, - [F] = {FL, UL, UB, UR, FR, DL, DB, DR, UF, DF, BL, BR}, - [F2] = {DF, UL, UB, UR, UF, DL, DB, DR, FL, FR, BL, BR}, - [F3] = {FR, UL, UB, UR, FL, DL, DB, DR, DF, UF, BL, BR}, - [B] = {UF, UL, BR, UR, DF, DL, BL, DR, FR, FL, UB, DB}, - [B2] = {UF, UL, DB, UR, DF, DL, UB, DR, FR, FL, BR, BL}, - [B3] = {UF, UL, BL, UR, DF, DL, BR, DR, FR, FL, DB, UB}, - - [Uw] = {UR, UF, UL, UB, DF, DL, DB, DR, BR, FR, FL, BL}, - [Uw2] = {UB, UR, UF, UL, DF, DL, DB, DR, BL, BR, FR, FL}, - [Uw3] = {UL, UB, UR, UF, DF, DL, DB, DR, FL, BL, BR, FR}, - [Dw] = {UF, UL, UB, UR, DL, DB, DR, DF, FL, BL, BR, FR}, - [Dw2] = {UF, UL, UB, UR, DB, DR, DF, DL, BL, BR, FR, FL}, - [Dw3] = {UF, UL, UB, UR, DR, DF, DL, DB, BR, FR, FL, BL}, - [Rw] = {DF, UL, UF, FR, DB, DL, UB, BR, DR, FL, BL, UR}, - [Rw2] = {DB, UL, DF, DR, UB, DL, UF, UR, BR, FL, BL, FR}, - [Rw3] = {UB, UL, DB, BR, UF, DL, DF, FR, UR, FL, BL, DR}, - [Lw] = {UB, BL, DB, UR, UF, FL, DF, DR, FR, UL, DL, BR}, - [Lw2] = {DB, DL, DF, UR, UB, UL, UF, DR, FR, BL, FL, BR}, - [Lw3] = {DF, FL, UF, UR, DB, BL, UB, DR, FR, DL, UL, BR}, - [Fw] = {FL, DL, UB, UL, FR, DR, DB, UR, UF, DF, BL, BR}, - [Fw2] = {DF, DR, UB, DL, UF, UR, DB, UL, FL, FR, BL, BR}, - [Fw3] = {FR, UR, UB, DR, FL, UL, DB, DL, DF, UF, BL, BR}, - [Bw] = {UF, UR, BR, DR, DF, UL, BL, DL, FR, FL, UB, DB}, - [Bw2] = {UF, DR, DB, DL, DF, UR, UB, UL, FR, FL, BR, BL}, - [Bw3] = {UF, DL, BL, UL, DF, DR, BR, UR, FR, FL, DB, UB}, - - [M] = {UB, UL, DB, UR, UF, DL, DF, DR, FR, FL, BL, BR}, - [M2] = {DB, UL, DF, UR, UB, DL, UF, DR, FR, FL, BL, BR}, - [M3] = {DF, UL, UF, UR, DB, DL, UB, DR, FR, FL, BL, BR}, - [S] = {UF, DL, UB, UL, DF, DR, DB, UR, FR, FL, BL, BR}, - [S2] = {UF, DR, UB, DL, DF, UR, DB, UL, FR, FL, BL, BR}, - [S3] = {UF, UR, UB, DR, DF, UL, DB, DL, FR, FL, BL, BR}, - [E] = {UF, UL, UB, UR, DF, DL, DB, DR, FL, BL, BR, FR}, - [E2] = {UF, UL, UB, UR, DF, DL, DB, DR, BL, BR, FR, FL}, - [E3] = {UF, UL, UB, UR, DF, DL, DB, DR, BR, FR, FL, BL}, - - [X] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, - [X2] = {DB, DL, DF, DR, UB, UL, UF, UR, BR, BL, FL, FR}, - [X3] = {UB, BL, DB, BR, UF, FL, DF, FR, UR, UL, DL, DR}, - [Y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL}, - [Y2] = {UB, UR, UF, UL, DB, DR, DF, DL, BL, BR, FR, FL}, - [Y3] = {UL, UB, UR, UF, DL, DB, DR, DF, FL, BL, BR, FR}, - [Z] = {FL, DL, BL, UL, FR, DR, BR, UR, UF, DF, DB, UB}, - [Z2] = {DF, DR, DB, DL, UF, UR, UB, UL, FL, FR, BR, BL}, - [Z3] = {FR, UR, BR, DR, FL, UL, BL, DL, DF, UF, UB, DB}, - - [NULLMOVE] = {UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR}, -}; - -int corner_cycle[NULLMOVE+1][8] = { - [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, - [U2] = {UBL, UBR, UFR, UFL, DFR, DFL, DBL, DBR}, - [U3] = {UFL, UBL, UBR, UFR, DFR, DFL, DBL, DBR}, - [D] = {UFR, UFL, UBL, UBR, DFL, DBL, DBR, DFR}, - [D2] = {UFR, UFL, UBL, UBR, DBL, DBR, DFR, DFL}, - [D3] = {UFR, UFL, UBL, UBR, DBR, DFR, DFL, DBL}, - [R] = {DFR, UFL, UBL, UFR, DBR, DFL, DBL, UBR}, - [R2] = {DBR, UFL, UBL, DFR, UBR, DFL, DBL, UFR}, - [R3] = {UBR, UFL, UBL, DBR, UFR, DFL, DBL, DFR}, - [L] = {UFR, UBL, DBL, UBR, DFR, UFL, DFL, DBR}, - [L2] = {UFR, DBL, DFL, UBR, DFR, UBL, UFL, DBR}, - [L3] = {UFR, DFL, UFL, UBR, DFR, DBL, UBL, DBR}, - [F] = {UFL, DFL, UBL, UBR, UFR, DFR, DBL, DBR}, - [F2] = {DFL, DFR, UBL, UBR, UFL, UFR, DBL, DBR}, - [F3] = {DFR, UFR, UBL, UBR, DFL, UFL, DBL, DBR}, - [B] = {UFR, UFL, UBR, DBR, DFR, DFL, UBL, DBL}, - [B2] = {UFR, UFL, DBR, DBL, DFR, DFL, UBR, UBL}, - [B3] = {UFR, UFL, DBL, UBL, DFR, DFL, DBR, UBR}, - - [Uw] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, - [Uw2] = {UBL, UBR, UFR, UFL, DFR, DFL, DBL, DBR}, - [Uw3] = {UFL, UBL, UBR, UFR, DFR, DFL, DBL, DBR}, - [Dw] = {UFR, UFL, UBL, UBR, DFL, DBL, DBR, DFR}, - [Dw2] = {UFR, UFL, UBL, UBR, DBL, DBR, DFR, DFL}, - [Dw3] = {UFR, UFL, UBL, UBR, DBR, DFR, DFL, DBL}, - [Rw] = {DFR, UFL, UBL, UFR, DBR, DFL, DBL, UBR}, - [Rw2] = {DBR, UFL, UBL, DFR, UBR, DFL, DBL, UFR}, - [Rw3] = {UBR, UFL, UBL, DBR, UFR, DFL, DBL, DFR}, - [Lw] = {UFR, UBL, DBL, UBR, DFR, UFL, DFL, DBR}, - [Lw2] = {UFR, DBL, DFL, UBR, DFR, UBL, UFL, DBR}, - [Lw3] = {UFR, DFL, UFL, UBR, DFR, DBL, UBL, DBR}, - [Fw] = {UFL, DFL, UBL, UBR, UFR, DFR, DBL, DBR}, - [Fw2] = {DFL, DFR, UBL, UBR, UFL, UFR, DBL, DBR}, - [Fw3] = {DFR, UFR, UBL, UBR, DFL, UFL, DBL, DBR}, - [Bw] = {UFR, UFL, UBR, DBR, DFR, DFL, UBL, DBL}, - [Bw2] = {UFR, UFL, DBR, DBL, DFR, DFL, UBR, UBL}, - [Bw3] = {UFR, UFL, DBL, UBL, DFR, DFL, DBR, UBR}, - - [M] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, - [M2] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, - [M3] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, - [S] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, - [S2] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, - [S3] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, - [E] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, - [E2] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, - [E3] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, - - [X] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, - [X2] = {DBR, DBL, DFL, DFR, UBR, UBL, UFL, UFR}, - [X3] = {UBR, UBL, DBL, DBR, UFR, UFL, DFL, DFR}, - [Y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL}, - [Y2] = {UBL, UBR, UFR, UFL, DBL, DBR, DFR, DFL}, - [Y3] = {UFL, UBL, UBR, UFR, DFL, DBL, DBR, DFR}, - [Z] = {UFL, DFL, DBL, UBL, UFR, DFR, DBR, UBR}, - [Z2] = {DFL, DFR, DBR, DBL, UFL, UFR, UBR, UBL}, - [Z3] = {DFR, UFR, UBR, DBR, DFL, UFL, UBL, DBL}, - - [NULLMOVE] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, -}; - -int center_cycle[NULLMOVE+1][6] = { - [U] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [U2] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [U3] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [D] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [D2] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [D3] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [R] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [R2] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [R3] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [L] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [L2] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [L3] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [F] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [F2] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [F3] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [B] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [B2] = {U_center, D_center, R_center, L_center, F_center, B_center}, - [B3] = {U_center, D_center, R_center, L_center, F_center, B_center}, - - [Uw] = {U_center, D_center, B_center, F_center, R_center, L_center}, - [Uw2] = {U_center, D_center, L_center, R_center, B_center, F_center}, - [Uw3] = {U_center, D_center, F_center, B_center, L_center, R_center}, - [Dw] = {U_center, D_center, F_center, B_center, L_center, R_center}, - [Dw2] = {U_center, D_center, L_center, R_center, B_center, F_center}, - [Dw3] = {U_center, D_center, B_center, F_center, R_center, L_center}, - [Rw] = {F_center, B_center, R_center, L_center, D_center, U_center}, - [Rw2] = {D_center, U_center, R_center, L_center, B_center, F_center}, - [Rw3] = {B_center, F_center, R_center, L_center, U_center, D_center}, - [Lw] = {B_center, F_center, R_center, L_center, U_center, D_center}, - [Lw2] = {D_center, U_center, R_center, L_center, B_center, F_center}, - [Lw3] = {F_center, B_center, R_center, L_center, D_center, U_center}, - [Fw] = {L_center, R_center, U_center, D_center, F_center, B_center}, - [Fw2] = {D_center, U_center, L_center, R_center, F_center, B_center}, - [Fw3] = {R_center, L_center, D_center, U_center, F_center, B_center}, - [Bw] = {R_center, L_center, D_center, U_center, F_center, B_center}, - [Bw2] = {D_center, U_center, L_center, R_center, F_center, B_center}, - [Bw3] = {L_center, R_center, U_center, D_center, F_center, B_center}, - - [X] = {F_center, B_center, R_center, L_center, D_center, U_center}, - [X2] = {D_center, U_center, R_center, L_center, B_center, F_center}, - [X3] = {B_center, F_center, R_center, L_center, U_center, D_center}, - [Y] = {U_center, D_center, B_center, F_center, R_center, L_center}, - [Y2] = {U_center, D_center, L_center, R_center, B_center, F_center}, - [Y3] = {U_center, D_center, F_center, B_center, L_center, R_center}, - [Z] = {L_center, R_center, U_center, D_center, F_center, B_center}, - [Z2] = {D_center, U_center, L_center, R_center, F_center, B_center}, - [Z3] = {R_center, L_center, D_center, U_center, F_center, B_center}, - - [M] = {B_center, F_center, R_center, L_center, U_center, D_center}, - [M2] = {D_center, U_center, R_center, L_center, B_center, F_center}, - [M3] = {F_center, B_center, R_center, L_center, D_center, U_center}, - [E] = {U_center, D_center, F_center, B_center, L_center, R_center}, - [E2] = {U_center, D_center, L_center, R_center, B_center, F_center}, - [E3] = {U_center, D_center, B_center, F_center, R_center, L_center}, - [S] = {L_center, R_center, U_center, D_center, F_center, B_center}, - [S2] = {D_center, U_center, L_center, R_center, F_center, B_center}, - [S3] = {R_center, L_center, D_center, U_center, F_center, B_center}, - - [NULLMOVE] = {U_center, D_center, R_center, L_center, F_center, B_center}, -}; - diff --git a/old/2020-unknown-date/pieces.h b/old/2020-unknown-date/pieces.h @@ -1,59 +0,0 @@ -/* Moves and other things */ - -#ifndef PIECES_H -#define PIECES_H - -typedef enum { - U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, - Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, S, S2, S3, E, E2, E3, - X, X2, X3, Y, Y2, Y3, Z, Z2, Z3, - NULLMOVE -} Move; -typedef enum { - U_center, D_center, R_center, L_center, F_center, B_center -} Center; -typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; -typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; - -/* Arrays for strings of pieces and moves */ -extern char edge_string[12][5]; -extern char corner_string[8][5]; -extern char center_string[6][5]; -extern char move_string[NULLMOVE+1][5]; - -/* Three big arrays that determine the movement of edges, corners and - * centers for some of the basic moves. Yes, one can be much more elegant and - * write much fewer lines. But then things get less elegant somewhere else. */ -extern int edge_cycle[NULLMOVE+1][12]; -extern int corner_cycle[NULLMOVE+1][8]; -extern int center_cycle[NULLMOVE+1][6]; - -/* Representation of the cube */ -typedef struct { - /* Edge orientation */ - int eofb; - int eorl; - int eoud; - - /* Corner orientation */ - int coud; - int cofb; - int corl; - - /* Position of M/E/S slice edges */ - /* TODO: keep in mind that the 4! positions with edges in correct slice - * must be the first 4! indeces */ - int epose; - int eposs; - int eposm; - - /* Permutation of corners */ - int cp; - - /* Position of centers */ - int centerpos; -} Cube; - -#endif diff --git a/old/2021-02-06/cube.c b/old/2021-02-06/cube.c @@ -1,664 +0,0 @@ -#include "cube.h" - -typedef struct { - int ep[12], eofb[12], eorl[12], eoud[12], - cp[8], coud[8], corl[8], cofb[8], cpos[6]; -} CubeArray; - -typedef struct { - bool epose, eposs, eposm, eofb, eorl, eoud, cp, coud, cofb, corl, cpos; -} PieceFilter; - -PieceFilter fAll = {true,true,true,true,true,true,true,true,true,true,true}; -PieceFilter cpos_only = { .cpos = true }; - -void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -Cube arrays_to_cube(CubeArray arr, PieceFilter f); -void move_cubearray(Move m, CubeArray *arr, PieceFilter f); -Cube move_via_array(Move m, Cube cube, PieceFilter f); -void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front); -bool read_ttables_file(); -bool write_ttables_file(); - -/* Transition tables */ -uint16_t epose_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; -uint16_t eofb_ttable[NMOVES][pow2to11]; -uint16_t eorl_ttable[NMOVES][pow2to11]; -uint16_t eoud_ttable[NMOVES][pow2to11]; -uint16_t cp_ttable[NMOVES][factorial8]; -uint16_t coud_ttable[NMOVES][pow3to7]; -uint16_t cofb_ttable[NMOVES][pow3to7]; -uint16_t corl_ttable[NMOVES][pow3to7]; -uint16_t cpos_ttable[NMOVES][factorial6]; - -bool commute[NMOVES][NMOVES]; -bool possible_next[NMOVES][NMOVES][NMOVES]; -Move inverse[NMOVES]; - -char edge_string[12][5] = - { "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" }; -char corner_string[8][5] = { "UFR","UFL","UBL","UBR","DFR","DFL","DBL","DBR" }; -char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; -char move_string[NMOVES][5] = - { "-", - "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", - "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", - "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", - "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", - "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", - "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'" }; - -/* For each type of pieces only the effects of U, x and y are described */ -int edge_cycle[NMOVES][12] = - { [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, - [x] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, - [y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL} }; -int eofb_flipped[NMOVES][12] = - { [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; -int eorl_flipped[NMOVES][12] = - { [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; -int eoud_flipped[NMOVES][12] = - { [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, - [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; -int corner_cycle[NMOVES][8] = - { [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, - [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, - [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} }; -int coud_flipped[NMOVES][8] = - { [x] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2} }; -int corl_flipped[NMOVES][8] = - { [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, - [y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1} }; -int cofb_flipped[NMOVES][8] = - { [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, - [x] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=2,[UFL]=1,[DBL]=1,[DFL]=2}, - [y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2} }; -int center_cycle[NMOVES][6] = - { [x] = {F_center, B_center, R_center, L_center, D_center, U_center}, - [y] = {U_center, D_center, B_center, F_center, R_center, L_center} }; - -/* Each move is reduced to a combination of U, x and y using this table */ -Move equiv_moves[NMOVES][14] = { - [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, - [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, - [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, - [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, - [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, - [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, - [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, - - [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, - [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, - [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, - [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, - [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, - [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, - [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, - [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, - [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, - [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - - [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, - [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, - [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, - [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, - [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, - [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, - [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, - [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, - [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, - - [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, -}; - -/* Movesets */ -bool standard_moveset[NMOVES] = { - [U] = true, [U2] = true, [U3] = true, [D] = true, [D2] = true, [D3] = true, - [R] = true, [R2] = true, [R3] = true, [L] = true, [L2] = true, [L3] = true, - [F] = true, [F2] = true, [F3] = true, [B] = true, [B2] = true, [B3] = true, -}; - -int epe_solved[] = {FR, FL, BL, BR}; -int eps_solved[] = {UL, UR, DL, DR}; -int epm_solved[] = {UF, UB, DF, DB}; - -Cube blank_cube() { - Cube c = {0}; - return c; -} - -void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) { - /* ep is the hardest */ - if (f.epose || f.eposs || f.eposm) - for (int i = 0; i < 12; i++) arr->ep[i] = -1; - if (f.epose) { - int epe[4], epose[12]; - index_to_perm(cube.epose % factorial(4), 4, epe); - index_to_subset(cube.epose / factorial(4), 12, 4, epose); - for (int i = 0, ie = 0; i < 12; i++) - if (epose[i]) arr->ep[i] = epe_solved[epe[ie++]]; - } - if (f.eposs) { - int eps[4], eposs[12]; - index_to_perm(cube.eposs % factorial(4), 4, eps); - index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); - for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); - for (int i = 0, is = 0; i < 12; i++) - if (eposs[i]) arr->ep[i] = eps_solved[eps[is++]]; - } - if (f.eposm) { - int epm[4], eposm[12]; - index_to_perm(cube.eposm % factorial(4), 4, epm); - index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); - for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); - for (int i = 0, im = 0; i < 12; i++) - if (eposm[i]) arr->ep[i] = epm_solved[epm[im++]]; - } - - /* All the others */ - if (f.eofb) int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) index_to_perm( cube.cp, 8, arr->cp); - if (f.coud) int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) index_to_perm( cube.cpos, 6, arr->cpos); -} - -Cube arrays_to_cube(CubeArray arr, PieceFilter f) { - Cube ret = {0}; - - /* Again, ep is the hardest part */ - if (f.epose) { - int epe[4], epose[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, ie = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == epe_solved[j]) - { epe[ie++] = j; epose[i] = 1; } - ret.epose = factorial(4)*subset_to_index(epose,12,4)+perm_to_index(epe,4); - } - if (f.eposs) { - int eps[4], eposs[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, is = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == eps_solved[j]) - { eps[is++] = j; eposs[i] = 1; } - for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); - ret.eposs = factorial(4)*subset_to_index(eposs,12,4)+perm_to_index(eps,4); - } - if (f.eposm) { - int epm[4], eposm[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, im = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == epm_solved[j]) - { epm[im++] = j; eposm[i] = 1; } - for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); - ret.eposm = factorial(4)*subset_to_index(eposm,12,4)+perm_to_index(epm,4); - } - if (f.eofb) ret.eofb = digit_array_to_int(arr.eofb, 11, 2); - if (f.eorl) ret.eorl = digit_array_to_int(arr.eorl, 11, 2); - if (f.eoud) ret.eoud = digit_array_to_int(arr.eoud, 11, 2); - if (f.cp) ret.cp = perm_to_index( arr.cp, 8 ); - if (f.coud) ret.coud = digit_array_to_int(arr.coud, 7, 3); - if (f.corl) ret.corl = digit_array_to_int(arr.corl, 7, 3); - if (f.cofb) ret.cofb = digit_array_to_int(arr.cofb, 7, 3); - if (f.cpos) ret.cpos = perm_to_index( arr.cpos, 6 ); - - return ret; -} - -void move_cubearray(Move m, CubeArray *arr, PieceFilter f) { - if (f.epose || f.eposs || f.eposm) - apply_permutation(edge_cycle[m], arr->ep, 12); - if (f.eofb) { - apply_permutation(edge_cycle[m], arr->eofb, 12); - sum_arrays_mod(eofb_flipped[m], arr->eofb, 12, 2); - } - if (f.eofb) { - apply_permutation(edge_cycle[m], arr->eorl, 12); - sum_arrays_mod(eorl_flipped[m], arr->eorl, 12, 2); - } - if (f.eofb) { - apply_permutation(edge_cycle[m], arr->eoud, 12); - sum_arrays_mod(eoud_flipped[m], arr->eoud, 12, 2); - } - if (f.cp) - apply_permutation(corner_cycle[m], arr->cp, 8); - if (f.coud) { - apply_permutation(corner_cycle[m], arr->coud, 8); - sum_arrays_mod(coud_flipped[m], arr->coud, 8, 3); - } - if (f.corl) { - apply_permutation(corner_cycle[m], arr->corl, 8); - sum_arrays_mod(corl_flipped[m], arr->corl, 8, 3); - } - if (f.cofb) { - apply_permutation(corner_cycle[m], arr->cofb, 8); - sum_arrays_mod(cofb_flipped[m], arr->cofb, 8, 3); - } - if (f.cpos) - apply_permutation(center_cycle[m], arr->cpos, 6); -} - -Cube move_via_array(Move m, Cube cube, PieceFilter f) { - CubeArray arr = {0}; - cube_to_arrays(cube, &arr, f); - move_cubearray(m, &arr, f); - return arrays_to_cube(arr, f); -} - -int copy_alg(NissMove *src, NissMove *dest) { - int i; - for (i = 0; src[i].m != NULLMOVE; i++) - dest[i] = src[i]; - dest[i].m = NULLMOVE; - return i; -} - -bool equal(Cube c1, Cube c2) { - return c1.eofb == c2.eofb && c1.epose == c2.epose && - c1.eposs == c2.eposs && c1.eposm == c2.eposm && - c1.coud == c2.coud && c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -bool solvable(Cube cube) { - /* Since we memorize orientation truncating the last digit, we only need to - * check that the permutations have the correct sign. */ - CubeArray arr = {0}; - cube_to_arrays(cube, &arr, fAll); - return (perm_sign(arr.ep,12) ^ perm_sign(arr.cpos,6)) == perm_sign(arr.cp,8); -} - -bool is_solved(Cube cube, bool reorient) { - if (!reorient || !cube.cpos) - return !cube.eofb && !cube.coud && !cube.cp && - !cube.epose && !cube.eposs && !cube.eposm; - - bool ret = false; - for (int i = x; i <= z3; i++) { - ret = ret || is_solved(move_cube(i, cube), false); - for (int j = x; j <= z3; j++) - ret = ret || is_solved(move_cube(i, move_cube(j, cube)), false); - } - return ret; -} - -void print_cube(Cube cube) { - CubeArray arr = {0}; - cube_to_arrays(cube, &arr, fAll); - - for (int i = 0; i < 12; i++) printf(" %s ", edge_string[arr.ep[i]]); - printf("\n"); - for (int i = 0; i < 12; i++) printf(" %c ", arr.eofb[i] + '0'); - printf("\n"); - for (int i = 0; i < 8; i++) printf("%s ", corner_string[arr.cp[i]]); - printf("\n"); - for (int i = 0; i < 8; i++) printf(" %c ", arr.coud[i] + '0'); - printf("\n"); - for (int i = 0; i < 6; i++) printf(" %s ", center_string[arr.cpos[i]]); - printf("\n"); -} - -/* TODO: all strings start with space?? */ -void print_moves(NissMove *alg) { - bool niss = false; - for (int i = 0; alg[i].m != NULLMOVE; i++) { - char *fill = !niss && alg[i].inverse ? " (" : - (niss && !alg[i].inverse ? ") " : " "); - printf("%s%s", fill, move_string[alg[i].m]); - niss = alg[i].inverse; - } - printf("%s\n", niss ? ")" : ""); -} - -int read_moves(char *str, NissMove *alg, int n) { - bool niss = false; - int c = 0; - - for (int i = 0; str[i] && c < n; i++) { - if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') - continue; - - if (str[i] == '(' || str[i] == ')') { - if ((niss && str[i] == '(') || (!niss && str[i] == ')')) - return -1; - niss = !niss; - continue; - } - - alg[c].inverse = niss; alg[c].m = NULLMOVE; - for (Move j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - alg[c].m = j; - if (alg[c].m <= B && str[i+1]=='w') { alg[c].m += Uw - U; i++; } - if (str[i+1]=='2') { alg[c].m += 1; i++; } - else if (str[i+1]=='\'' || str[i+1]=='3') { alg[c].m += 2; i++; } - c++; - break; - } - } - } - - alg[c].m = NULLMOVE; - return c; -} - -/* Helper function for cleanup. alg must contain only basic moves, no 2 or '. - top and front describe an admissible orientation of the cube. */ -void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front) { - int c = 0, i = 0; - NissMove aux[n+3]; - aux[0].m = NULLMOVE; - - while (i < n && alg[i].m != NULLMOVE) { - int j = i; - while (j < n && commute[alg[i].m][alg[j].m]) j++; - Move base = 6*((alg[i].m-1)/6); - int t1 = 0, t2 = 0; - for (int k = i; k < j; k++) - if (alg[k].m == base+1) t1 = (t1+1)%4; - else t2 = (t2+1)%4; - if (t1) { aux[c].inverse = inv; aux[c].m = base+t1; c++; } - if (t2) { aux[c].inverse = inv; aux[c].m = base+t2+3; c++; } - i = j; - } - aux[c].m = NULLMOVE; - - CubeArray q; - cube_to_arrays(blank_cube(), &q, cpos_only); - /* First we try to rotate in one move, then we try an x or y rotation - followed by a z rotation */ - for (int r = x; r <= z3; r++) { - move_cubearray(r, &q, cpos_only); - if (q.cpos[F_center] == front && q.cpos[U_center] == top) { - aux[c].inverse = inv; aux[c].m = r; - - aux[++c].m = NULLMOVE; - copy_alg(aux, alg); - return; - } - move_cubearray(inverse[r], &q, cpos_only); - } - for (int r = x; r <= y3; r++) { - move_cubearray(r, &q, cpos_only); - if (q.cpos[F_center] == front) { - aux[c].inverse = inv; aux[c++].m = r; - break; - } - move_cubearray(inverse[r], &q, cpos_only); - } - for (int r = z; r <= z3; r++) { - move_cubearray(r, &q, cpos_only); - if (q.cpos[U_center] == top) { - aux[c].inverse = inv; aux[c++].m = r; - break; - } - move_cubearray(inverse[r], &q, cpos_only); - } - - aux[c].m = NULLMOVE; - copy_alg(aux, alg); -} - -void cleanup(NissMove *alg, int n) { - int count_n = 0, count_i = 0, *count; - NissMove aux_n[n+1], aux_i[n+1], *aux; - CubeArray cube_n, cube_i, *cube; - cube_to_arrays(blank_cube(), &cube_n, cpos_only); - cube_to_arrays(blank_cube(), &cube_i, cpos_only); - - for (int i = 0; count_n + count_i < n && alg[i].m != NULLMOVE; i++) { - if (alg[i].inverse) { count = &count_i; aux = aux_i; cube = &cube_i; } - else { count = &count_n; aux = aux_n; cube = &cube_n; } - - for (int j = 0; equiv_moves[alg[i].m][j]; j++) { - Move m = equiv_moves[alg[i].m][j]; - aux[*count].inverse = alg[i].inverse; - move_cubearray(m, cube, cpos_only); - if (m == U) aux[(*count)++].m = 3 * cube->cpos[0] + 1; - } - } - - aux_n[count_n].m = NULLMOVE; - aux_i[count_i].m = NULLMOVE; - sort_cancel_rotate(aux_n, count_n, false, cube_n.cpos[0], cube_n.cpos[4]); - sort_cancel_rotate(aux_i, count_i, true, cube_i.cpos[0], cube_n.cpos[4]); - copy_alg(aux_n, alg); - copy_alg(aux_i, alg+count_n); -} - -Cube inverse_cube(Cube cube) { - CubeArray arr = {0}, inv = {0}; - cube_to_arrays(cube, &arr, fAll); - - for (int i = 0; i < 12; i++) { - inv.ep[arr.ep[i]] = i; - inv.eofb[arr.ep[i]] = arr.eofb[i]; - inv.eorl[arr.ep[i]] = arr.eorl[i]; - inv.eoud[arr.ep[i]] = arr.eoud[i]; - } - for (int i = 0; i < 8; i++) { - inv.cp[arr.cp[i]] = i; - inv.coud[arr.cp[i]] = arr.coud[i]; - inv.corl[arr.cp[i]] = arr.corl[i]; - inv.cofb[arr.cp[i]] = arr.cofb[i]; - } - for (int i = 0; i < 6; i++) - inv.cpos[arr.cpos[i]] = i; - - return arrays_to_cube(inv, fAll); -} - -bool read_ttables_file() { - FILE *ttf; - if ((ttf = fopen("ttables", "rb")) != NULL) { - for (int m = 0; m < NMOVES; m++) { - fread(epose_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fread(eposs_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fread(eposm_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fread(eofb_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fread(eorl_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fread(eoud_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fread(cp_ttable[m], sizeof(uint16_t), factorial8, ttf); - fread(coud_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fread(corl_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fread(cofb_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fread(cpos_ttable[m], sizeof(uint16_t), factorial6, ttf); - } - fclose(ttf); - return true; - } else return false; -} - -bool write_ttables_file() { - FILE *ttf; - if ((ttf = fopen("ttables", "wb")) != NULL) { - for (int m = 0; m < NMOVES; m++) { - fwrite(epose_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fwrite(eposs_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fwrite(eposm_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fwrite(eofb_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fwrite(eorl_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fwrite(eoud_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fwrite(cp_ttable[m], sizeof(uint16_t), factorial8, ttf); - fwrite(coud_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fwrite(corl_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fwrite(cofb_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fwrite(cpos_ttable[m], sizeof(uint16_t), factorial6, ttf); - } - fclose(ttf); - return true; - } else return false; -} - -void init_ttables(bool read, bool write) { - /* Generate all move cycles and flips; I do this regardless */ - for (int i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - CubeArray arr = {0}; - cube_to_arrays(blank_cube(), &arr, fAll); - for (int j = 0; equiv_moves[i][j]; j++) - move_cubearray(equiv_moves[i][j], &arr, fAll); - - intarrcopy(arr.ep, edge_cycle[i], 12); - intarrcopy(arr.eofb, eofb_flipped[i], 12); - intarrcopy(arr.eorl, eorl_flipped[i], 12); - intarrcopy(arr.eoud, eoud_flipped[i], 12); - intarrcopy(arr.cp, corner_cycle[i], 8); - intarrcopy(arr.coud, coud_flipped[i], 8); - intarrcopy(arr.corl, corl_flipped[i], 8); - intarrcopy(arr.cofb, cofb_flipped[i], 8); - intarrcopy(arr.cpos, center_cycle[i], 6); - } - - if (read) - if (read_ttables_file()) - return; - - /* Initialize transition tables */ - Cube c = {0}; - PieceFilter fe = {.epose=true}, fs = {.eposs=true}, fm = {.eposm=true}; - PieceFilter feo = { .eofb = true, .eorl = true, .eoud = true }; - PieceFilter fcp = { .cp = true }; - PieceFilter fco = { .cofb = true, .corl = true, .coud = true }; - PieceFilter fcc = { .cpos = true }; - for (int m = 0; m < NMOVES; m++) { - for (uint16_t i = 0; i < factorial12/factorial8; i++) { - c.epose = i; epose_ttable[m][i] = move_via_array(m, c, fe).epose; - c.eposs = i; eposs_ttable[m][i] = move_via_array(m, c, fs).eposs; - c.eposm = i; eposm_ttable[m][i] = move_via_array(m, c, fm).eposm; - } - for (uint16_t i = 0; i < pow2to11; i++ ) { - c.eofb = i; eofb_ttable[m][i] = move_via_array(m, c, feo).eofb; - c.eorl = i; eorl_ttable[m][i] = move_via_array(m, c, feo).eorl; - c.eoud = i; eoud_ttable[m][i] = move_via_array(m, c, feo).eoud; - } - for (uint16_t i = 0; i < factorial8; i++) { - c.cp = i; cp_ttable[m][i] = move_via_array(m, c, fcp).cp; - } - for (uint16_t i = 0; i < pow3to7; i++) { - c.coud = i; coud_ttable[m][i] = move_via_array(m, c, fco).coud; - c.corl = i; corl_ttable[m][i] = move_via_array(m, c, fco).corl; - c.cofb = i; cofb_ttable[m][i] = move_via_array(m, c, fco).cofb; - } - for (uint16_t i = 0; i < factorial6; i++) { - c.cpos = i; cpos_ttable[m][i] = move_via_array(m, c, fcc).cpos; - } - } - - if (write) write_ttables_file(); -} - -Cube move_cube(Move m, Cube cube) { - Cube moved = cube; - - moved.epose = epose_ttable[m][cube.epose]; - moved.eposs = eposs_ttable[m][cube.eposs]; - moved.eposm = eposm_ttable[m][cube.eposm]; - moved.eofb = eofb_ttable[m][cube.eofb]; - moved.eorl = eorl_ttable[m][cube.eorl]; - moved.eoud = eoud_ttable[m][cube.eoud]; - moved.coud = coud_ttable[m][cube.coud]; - moved.cofb = cofb_ttable[m][cube.cofb]; - moved.corl = corl_ttable[m][cube.corl]; - moved.cp = cp_ttable[m][cube.cp]; - moved.cpos = cpos_ttable[m][cube.cpos]; - - return moved; -} - -Cube compose(Cube c2, Cube c1) { - /* This is basically the same as the move_cubearray function above */ - CubeArray arr2 = {0}, arr1 = {0}; - cube_to_arrays(c2, &arr2, fAll); - cube_to_arrays(c1, &arr1, fAll); - - apply_permutation(arr2.ep, arr1.ep, 12); - apply_permutation(arr2.ep, arr1.eofb, 12); - apply_permutation(arr2.ep, arr1.eorl, 12); - apply_permutation(arr2.ep, arr1.eoud, 12); - sum_arrays_mod(arr2.eofb, arr1.eofb, 12, 2); - sum_arrays_mod(arr2.eorl, arr1.eorl, 12, 2); - sum_arrays_mod(arr2.eoud, arr1.eoud, 12, 2); - apply_permutation(arr2.cp, arr1.cp, 8); - apply_permutation(arr2.cp, arr1.coud, 8); - apply_permutation(arr2.cp, arr1.corl, 8); - apply_permutation(arr2.cp, arr1.cofb, 8); - sum_arrays_mod(arr2.coud, arr1.coud, 8, 3); - sum_arrays_mod(arr2.corl, arr1.corl, 8, 3); - sum_arrays_mod(arr2.cofb, arr1.cofb, 8, 3); - apply_permutation(arr2.cpos, arr1.cpos, 6); - - return arrays_to_cube(arr1, fAll); -} - -Cube apply_alg(NissMove *alg, Cube cube) { - Cube ret = {0}; - for (int i = 0; alg[i].m != NULLMOVE; i++) - if (alg[i].inverse) - ret = move_cube(alg[i].m, ret); - ret = compose(cube, inverse_cube(ret)); - - for (int i = 0; alg[i].m != NULLMOVE; i++) - if (!alg[i].inverse) - ret = move_cube(alg[i].m, ret); - return ret; -} - -void init_aux_tables() { - /* Commute */ - for (int i = 0; i < NMOVES; i++) - for (int j = 0; j < NMOVES; j++) - commute[i][j] = equal(move_cube(i, move_cube(j, blank_cube())), - move_cube(j, move_cube(i, blank_cube()))); - - /* Possible next (if the sequence i j k is valid) */ - for (int i = 0; i < NMOVES; i++) - for (int j = 0; j < NMOVES; j++) - for (int k = 0; k < NMOVES; k++) - possible_next[i][j][k] = - (j == 0) || - (j != 0 && (j-(j-1)%3) != (k-(k-1)%3) && - !(i != 0 && commute[i][j] && (i-(i-1)%3) == (k-(k-1)%3))); - - /* Inverse */ - for (int i = 0; i < NMOVES; i++) - inverse[i] = i == 0 ? 0 : i + 2 - 2*((i-1)%3); -} - diff --git a/old/2021-02-06/cube.h b/old/2021-02-06/cube.h @@ -1,60 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include "utils.h" - -#define NMOVES (z3+1) - -/* Constants for moves and pieces */ -typedef enum { - NULLMOVE, - U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, - Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, S, S2, S3, E, E2, E3, - x, x2, x3, y, y2, y3, z, z2, z3, -} Move; -typedef enum {U_center,D_center,R_center,L_center,F_center,B_center} Center; -typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; -typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; - -/* An alg is an array of "NissMoves", which can be on normal or on inverse. */ -typedef struct { bool inverse; Move m; } NissMove; - -/* Representation of the cube */ -typedef struct { - uint16_t eofb, eorl, eoud, coud, cofb, corl, - epose, eposs, eposm, cp, cpos; -} Cube; - -extern bool commute[NMOVES][NMOVES]; -extern bool possible_next[NMOVES][NMOVES][NMOVES]; -extern Move inverse[NMOVES]; -/* Movesets */ -extern bool standard_moveset[NMOVES]; - -int copy_alg(NissMove *src, NissMove *dest); /*return number of moves copied */ - -bool equal(Cube c1, Cube c2); -bool is_solvable(Cube cube); -/* reorient=true allows solved in wrong orientation */ -bool is_solved(Cube cube, bool reorient); -void print_cube(Cube cube); -void print_moves(NissMove *alg); -int read_moves(char *str, NissMove *alg, int n); /* reads at most n moves */ -void cleanup(NissMove *src, int n); /* rewrites using basic moves, at most n */ -Cube blank_cube(); -Cube inverse_cube(Cube cube); -Cube move_cube(Move m, Cube cube); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg */ -Cube apply_alg(NissMove *alg, Cube cube); - -void init_ttables(bool read, bool write); -void init_aux_tables(); - -void init_dbg(); - -#endif diff --git a/old/2021-02-06/main.c b/old/2021-02-06/main.c @@ -1,46 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "solve.h" - -int main() { - init_ttables(true, true); - init_aux_tables(); - - - char moves[100] = "MR U' B2 Bw F z xE2 M' x Dw' y Fw2 y2"; - NissMove alg[100]; - read_moves(moves, alg, 100); - Cube cube = apply_alg(alg, blank_cube()); - - /*f_eofb(cube);*/ - - -/* NissMove sol[MAXS][MAXM];*/ - SolveData d = { .optimal_only = true, .available = standard_moveset, - .max_moves = 10, - .cleanup = true, - .max_solutions = 10, - .f = f_eofb }; - read_moves("y", d.pre_rotation, 2); - int n = solve(cube, &d); - printf("%d solutions found:\n", n); - for (int i = 0; i < n; i++) - print_moves(d.solutions[i]); - - NissMove a[5], b[5]; - read_moves("R", a, 5); - read_moves("U", b, 5); - Cube c1 = apply_alg(a,blank_cube()), c2 = apply_alg(b,blank_cube()); - print_cube(compose(c2,c1)); - print_cube(compose(c1,c2)); - /*print_cube(compose(c2,blank_cube()));*/ - - NissMove nm[10]; - read_moves("y(y)RU", nm, 10); - - print_moves(nm); - cleanup(nm, 10); - print_moves(nm); - - return 0; -} diff --git a/old/2021-02-06/solve.c b/old/2021-02-06/solve.c @@ -1,177 +0,0 @@ -#include "solve.h" - -/* Data for creating a pruning table: - - compressed: if set to true, each entry occupies only 4 bits, but values - larger than 15 cannot be stored. - - available[] is the list of availabel moves, as above. - - *ptable is the actual table to fill. - - n is the number of states (size of ptable). - - index must "linearize" the cube, i.e. return its index in ptable. - - fname is the name of the file where to store the table */ -typedef struct { - bool compressed, *available; - int max_moves; - uint8_t *ptable; - uint64_t n; - uint64_t (*index)(Cube); - char *fname; -} PruneData; - -/* TODO: comment this */ -typedef struct { - bool niss; - int m, d; - uint64_t *n; - Move last1, last2; -} DfsData; - -void solve_dfs(Cube cube, SolveData *sd, DfsData dd); -void init_ptable(PruneData *pd, bool read, bool write); - -/* Search solutions of lenght exactly d */ -void solve_dfs(Cube cube, SolveData *sd, DfsData dd) { - if (*dd.n >= sd->max_solutions || - ((!sd->can_niss || dd.niss) && dd.m + sd->f(cube) > dd.d)) - return; - - (sd->solutions[*dd.n][dd.m]).inverse = dd.niss; - (sd->solutions[*dd.n][dd.m]).m = NULLMOVE; - - if (!sd->f(cube)) { /* Solved */ - if (dd.m == dd.d) { - (*dd.n)++; - if (*dd.n < sd->max_solutions) - copy_alg(sd->solutions[*dd.n-1], sd->solutions[*dd.n]); - } - return; - } - - for (int i = 0; i < NMOVES && sd->sorted_moves[i] != NULLMOVE; i++) { - Move move = sd->sorted_moves[i]; - if (possible_next[dd.last2][dd.last1][move]) { - sd->solutions[*dd.n][dd.m].inverse = dd.niss; - sd->solutions[*dd.n][dd.m].m = move; - DfsData nn = { .niss = dd.niss, .m = dd.m+1, .d = dd.d, .n = dd.n, - .last1 = move, .last2 = dd.last1 }; - solve_dfs(move_cube(move, cube), sd, nn); - } - } - - if (sd->can_niss && !dd.niss && - (!dd.m || (dd.m && sd->f(move_cube(dd.last1, blank_cube()))))) { - DfsData nn = { .niss = true, .m = dd.m, .d = dd.d, .n = dd.n }; - solve_dfs(inverse_cube(cube), sd, nn); - } -} - -/* Iterative deepening depth-first search: for i running from the minimum - to the maximum number of moves allowed, looks for solutions of length i. */ -int solve(Cube cube, SolveData *sd) { - if (sd->precondition != NULL && !sd->precondition(cube)) - return -1; - - /* If not given, generate sorted list of moves */ - if (sd->sorted_moves[0] == NULLMOVE) { - int a[NMOVES], b[NMOVES], ia = 0, ib = 0; - for (int i = 0; i < NMOVES; i++) { - if (sd->available[i]) { - if (sd->f(move_cube(i, blank_cube()))) - a[ia++] = i; - else - b[ib++] = i; - } - } - intarrcopy(a, (int *)sd->sorted_moves, ia); - intarrcopy(b, (int *)sd->sorted_moves+ia, ib); - sd->sorted_moves[ia+ib] = NULLMOVE; - } - - sd->max_solutions = min(sd->max_solutions, MAXS); - Cube rotated = apply_alg(sd->pre_rotation, blank_cube()); - cube = apply_alg(inverse_cube(rotated), compose(cube, rotated)); - - uint64_t ret = 0; - for (int i=sd->min_moves; i<=sd->max_moves&&!(ret&&sd->optimal_only); i++) { - DfsData dd = { .d = i, .n = &ret }; - solve_dfs(cube, sd, dd); - } - - for (uint64_t i = 0; i < ret; i++) { - /* TODO: transform solutions with inverse of pre_rotation */ - if (sd->cleanup) - cleanup(sd->solutions[i], sd->max_moves*3); - } - - return ret; -} - -void prune_dfs(Cube cube, PruneData *pd, DfsData dd) { - uint64_t ind = pd->index(cube); - if ((!ind || pd->ptable[ind]) && pd->ptable[ind] != dd.m) - return; - if (dd.m == dd.d) { - if (ind && !pd->ptable[ind]) { - pd->ptable[ind] = dd.m; - (*dd.n)++; - } - return; - } - - for (int i = 0; i < NMOVES; i++) { - if (dd.m<20) - if (possible_next[dd.last2][dd.last1][i] && pd->available[i]) { - DfsData nn = { .m = dd.m+1, .d = dd.d, .n = dd.n, - .last1 = i, .last2 = dd.last1 }; - prune_dfs(move_cube(i, cube), pd, nn); - } - } -} - -void init_ptable(PruneData *pd, bool read, bool write) { - if (read) { - FILE *ptf; - if ((ptf = fopen(pd->fname, "rb")) != NULL) { - fread(pd->ptable, sizeof(uint8_t), pd->n, ptf); - fclose(ptf); - return; - } - } - - /* TODO: for now it behaves always as if copressed = false */ - for (uint64_t i = 0; i < pd->n; i++) - pd->ptable[i] = 0; - - uint64_t s = 1; - for (int i = 1; i < pd->max_moves && s < pd->n; i++) { - DfsData dd = { .d = i, .n = &s }; - prune_dfs(blank_cube(), pd, dd); - } - - if (write) { - FILE *ptf; - if ((ptf = fopen(pd->fname, "wb")) != NULL) { - fwrite(pd->ptable, sizeof(uint8_t), pd->n, ptf); - fclose(ptf); - return; - } - } -} - -/* Solving steps (and indexing functions) */ - -uint64_t index_eofb(Cube cube) { return cube.eofb; } -uint16_t f_eofb(Cube cube) { - static bool initialized_ptable; - static uint8_t pt_eofb[pow2to11]; - if (!initialized_ptable) { - PruneData pd = { - .compressed = false, .available = standard_moveset, .max_moves = 13, - .ptable = pt_eofb, .n = pow2to11, .index = index_eofb, - .fname = "ptable_eofb" - }; - init_ptable(&pd, false, true); - initialized_ptable = true; - } - return cube.eofb ? pt_eofb[cube.eofb] : 0; -} - diff --git a/old/2021-02-06/solve.h b/old/2021-02-06/solve.h @@ -1,55 +0,0 @@ -#ifndef SOLVE_H -#define SOLVE_H - -#include <stdlib.h> -#include "cube.h" - -/* Maximum number of moves per solution and of solutions */ -#define MAXM 30 -#define MAXS 999 - -/* Data for solving a step: - - can_niss is true niss can be used, false otherwise. - - optimal_only if true, dynamically updates max_moves so non-optimal - solutions are discarded. - - cleanup determines whether the cleaunup() function should be used on - the found solutions before returning. - - available[m] is true if the move m can be used, false otherwise. - - min_moves and max_moves are the minimum and maximum number of moves that - can be used. - - max_solution is the maximum number of solutions that can be returned. - - precondition can be used to check wheter the step can actually be applied - to the cube. If it returns false, solve() stops immediately returning -1. - - f must return 0 if and only if the step is solve, otherwise it must return - a lower bound for the number of moves required (without niss). - - sorted_moves[] can be used to specify in which order moves are tried - by the solving algorithm (for example if one wants to always try F' before - F). If sorted_moves[0] == NULLMOVE, the list is generated automatically. - It is advised to list first all the moves that actually influence the - solved state of the step (this is the default choice). This is in order to - avoid cases like B2 F for EO and to NISS only when it makes sense. - - start_moves [Currently unused, REMOVE] - are the moves that will be used as first moves of all - solutions. For example giving R' U' F (F' U R) will generate FMC scrambles - and y (y) will solve the step on another axis. - - pre_rotation are the rotations to apply before the scamble to solve - the step wrt a different orientation - - pre_rotation are the rotations to apply before the scamble to solve - the step wth respect to a different orientation. - - solutions[][] is the array where to store the found solutions. */ -typedef struct { - bool can_niss, optimal_only, cleanup, *available; - int min_moves, max_moves; - uint64_t max_solutions; - bool (*precondition)(Cube); - uint16_t (*f)(Cube); - Move sorted_moves[NMOVES]; - NissMove pre_rotation[3], solutions[MAXS][MAXM]; -} SolveData; - -int solve(Cube cube, SolveData *data); /* Returns the number of solutions. */ - -/* Steps */ -uint16_t f_eofb(Cube cube); - -#endif diff --git a/old/2021-02-06/utils.c b/old/2021-02-06/utils.c @@ -1,197 +0,0 @@ -#include "utils.h" - -void swap(int *a, int *b) { - int aux = *a; - *a = *b; - *b = aux; -} - -void intarrcopy(int *src, int *dst, int n) { - for (int i = 0; i < n; i++) - dst[i] = src[i]; -} - -int sum(int *a, int n) { - int ret = 0; - for (int i = 0; i < n; i++) - ret += a[i]; - return ret; -} - -bool is_perm(int *a, int n) { - int aux[n]; for (int i = 0; i < n; i++) aux[i] = 0; - for (int i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - for (int i = 0; i < n; i++) - if (!aux[i]) - return false; - return true; -} - -bool is_subset(int *a, int n, int k) { - int sum = 0; - for (int i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - return sum == k; -} - -int powint(int a, int b) { - return 0; - if (b == 0 || a == 1) - return 1; - if (a == 0) - return 0; - if (b < 0) - return 0; /* Immediate truncate (integer part is 0) */ - if (b % 2) { - return a * powint(a, b-1); - } else { - int x = powint(a, b/2); - return x*x; - } -} - -int factorial(int n) { - if (n < 0) - return 0; - int ret = 1; - for (int i = 1; i <= n; i++) - ret *= i; - return ret; -} - -int binomial(int n, int k) { - if (n < 0 || k < 0 || k > n) - return 0; - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -void int_to_digit_array(int a, int b, int n, int *r) { - if (b <= 1) - for (int i = 0; i < n; i++) - r[i] = 0; - else - for (int i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -int digit_array_to_int(int *a, int n, int b) { - int ret = 0, p = 1; - for (int i = 0; i < n; i++, p *= b) - ret += a[i] * p; - return ret; -} - -int perm_to_index(int *a, int n) { - if (!is_perm(a, n)) - return factorial(n); /* Error */ - int ret = 0; - for (int i = 0; i < n; i++) { - int c = 0; - for (int j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - return ret; -} - -void index_to_perm(int p, int n, int *r) { - if (p < 0 || p >= factorial(n)) /* Error */ - for (int i = 0; i < n; i++) - r[i] = -1; - int a[n]; for (int j = 0; j < n; j++) a[j] = 0; /* picked elements */ - for (int i = 0; i < n; i++) { - int c = 0, j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } -} - -int perm_sign(int *a, int n) { - if (!is_perm(a,n)) - return false; - int ret = 0; - for (int i = 0; i < n; i++) - for (int j = i+1; j < n; j++) - ret += (a[i]>a[j]) ? 1 : 0; - return ret % 2; -} - -int subset_to_index(int *a, int n, int k) { - /* TODO: better checks */ - if (!is_subset(a, n, k)) - return binomial(n, k); /* Error */ - int ret = 0; - for (int i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - /*ret += factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ - ret += binomial(n-i-1, k); - k--; - } - } - return ret; -} - -void index_to_subset(int s, int n, int k, int *r) { - if (s < 0 || s >= binomial(n, k)) { /* Error */ - for (int i = 0; i < n; i++) - r[i] = -1; - return; - } - for (int i = 0; i < n; i++) { - if (k == n-i) { - for (int j = i; j < n; j++) - r[j] = 1; - return; - } - if (k == 0) { - for (int j = i; j < n; j++) - r[j] = 0; - return; - } - /*int v = factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ - int v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -void int_to_sum_zero_array(int x, int b, int n, int *a) { - if (b <= 1) { - for (int i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - int s = 0; - for (int i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -void apply_permutation(int *perm, int *set, int n) { - if (!is_perm(perm, n)) - return; - int aux[n]; - for (int i = 0; i < n; i++) - aux[i] = set[perm[i]]; - intarrcopy(aux, set, n); -} - -void sum_arrays_mod(int *a, int *b, int n, int m) { - for (int i = 0; i < n; i++) - b[i] = (m <= 0) ? 0 : (a[i] + b[i]) % m; -} diff --git a/old/2021-02-06/utils.h b/old/2021-02-06/utils.h @@ -1,70 +0,0 @@ -/* General utility functions */ - -#ifndef UTILS_H -#define UTILS_H - -#include <stdbool.h> - -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -/* Some useful constants */ -#define pow2to11 2048 -#define pow2to12 4096 -#define pow3to7 2187 -#define pow3to8 6561 -#define pow12to4 20736 -#define factorial4 24 -#define factorial6 720 -#define factorial8 40320 -#define factorial12 479001600 -#define binom12on4 495 -#define binom8on4 70 - -/* Generic utility functions */ -void swap(int *a, int *b); -void intarrcopy(int *src, int *dst, int n); -int sum(int *a, int n); -bool is_perm(int *a, int n); -bool is_perm(int *a, int n); - - -/* Standard mathematical functions */ -int powint(int a, int b); -int factorial(int n); -int binomial(int n, int k); - -/* Converts the integer a to its representation in base b (first n digits - * only) and saves the result in r. */ -void int_to_digit_array(int a, int b, int n, int *r); -int digit_array_to_int(int *a, int n, int b); - -/* Converts the first n-1 digits of a number to an array a of digits in base b; - * then adds one element to the array, so that the sum of the elements of a is - * zero modulo b. - * This is used for determing the edge orientation from an 11-bits integer or - * the corner orientation from a 7-trits integer. */ -void int_to_sum_zero_array(int x, int b, int n, int *a); - -/* Converts a permutation on [0..(n-1)] into the integer i which is the index - * of the permutation in the sorted list of all n! such permutations. */ -int perm_to_index(int *a, int n); -void index_to_perm(int p, int n, int *r); - -/* Determine the sign of a permutation */ -int perm_sign(int a[], int n); - -/* Converts a k-element subset of a set from an array of n elements, of which k - * are 1 and n-k are 0, to its index in the sorted list of all such subsets. */ -int subset_to_index(int *a, int n, int k); -void index_to_subset(int s, int n, int k, int *r); - -int ordered_subset_to_index(int *a, int n, int k); -void index_to_ordered_subset(int s, int n, int k, int *r); - -void apply_permutation(int *perm, int *set, int n); - -/* b[i] = (a[i]+b[i])%m for i=1,...,n */ -void sum_arrays_mod(int *a, int *b, int n, int m); - -#endif diff --git a/old/2021-02-18-piecefilter/compile.sh b/old/2021-02-18-piecefilter/compile.sh @@ -1 +0,0 @@ -gcc -Wall -Wextra -O2 -std=c99 -o nissy ./src/*.c diff --git a/old/2021-02-18-piecefilter/nissy b/old/2021-02-18-piecefilter/nissy Binary files differ. diff --git a/old/2021-02-18-piecefilter/src/cube.c b/old/2021-02-18-piecefilter/src/cube.c @@ -1,198 +0,0 @@ -#include "cube.h" - -char edge_string[12][5] = - { "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" }; -char corner_string[8][5] = { "UFR","UFL","UBL","UBR","DFR","DFL","DBL","DBR" }; -char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; - -int epe_solved[] = {FR, FL, BL, BR}; -int eps_solved[] = {UL, UR, DL, DR}; -int epm_solved[] = {UF, UB, DF, DB}; - -PieceFilter fAll = {true,true,true,true,true,true,true,true,true,true,true}; - -Cube blank_cube() { - Cube c = {0}; - return c; -} - -/* Return axis (ud=0, rl=1, fb=0) of center c */ -int center_axis(int c) { - if (c == U_center || c == D_center) - return 0; - if (c == R_center || c == L_center) - return 1; - return 2; -} - -/* Return slice (e=0, s=1, m=2) to which e belongs */ -int edge_slice(int e) { - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - return 2; -} - -void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) { - /* ep is the hardest */ - if (f.epose || f.eposs || f.eposm) - for (int i = 0; i < 12; i++) arr->ep[i] = -1; - if (f.epose) { - int epe[4], epose[12]; - index_to_perm(cube.epose % factorial(4), 4, epe); - index_to_subset(cube.epose / factorial(4), 12, 4, epose); - for (int i = 0, ie = 0; i < 12; i++) - if (epose[i]) arr->ep[i] = epe_solved[epe[ie++]]; - } - if (f.eposs) { - int eps[4], eposs[12]; - index_to_perm(cube.eposs % factorial(4), 4, eps); - index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); - for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); - for (int i = 0, is = 0; i < 12; i++) - if (eposs[i]) arr->ep[i] = eps_solved[eps[is++]]; - } - if (f.eposm) { - int epm[4], eposm[12]; - index_to_perm(cube.eposm % factorial(4), 4, epm); - index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); - for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); - for (int i = 0, im = 0; i < 12; i++) - if (eposm[i]) arr->ep[i] = epm_solved[epm[im++]]; - } - - /* All the others */ - if (f.eofb) int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) index_to_perm( cube.cp, 8, arr->cp); - if (f.coud) int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) index_to_perm( cube.cpos, 6, arr->cpos); -} - -Cube arrays_to_cube(CubeArray arr, PieceFilter f) { - Cube ret = {0}; - - /* Again, ep is the hardest part */ - if (f.epose) { - int epe[4], epose[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, ie = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == epe_solved[j]) - { epe[ie++] = j; epose[i] = 1; } - ret.epose = factorial(4)*subset_to_index(epose,12,4)+perm_to_index(epe,4); - } - if (f.eposs) { - int eps[4], eposs[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, is = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == eps_solved[j]) - { eps[is++] = j; eposs[i] = 1; } - for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); - ret.eposs = factorial(4)*subset_to_index(eposs,12,4)+perm_to_index(eps,4); - } - if (f.eposm) { - int epm[4], eposm[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, im = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == epm_solved[j]) - { epm[im++] = j; eposm[i] = 1; } - for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); - ret.eposm = factorial(4)*subset_to_index(eposm,12,4)+perm_to_index(epm,4); - } - if (f.eofb) ret.eofb = digit_array_to_int(arr.eofb, 11, 2); - if (f.eorl) ret.eorl = digit_array_to_int(arr.eorl, 11, 2); - if (f.eoud) ret.eoud = digit_array_to_int(arr.eoud, 11, 2); - if (f.cp) ret.cp = perm_to_index( arr.cp, 8 ); - if (f.coud) ret.coud = digit_array_to_int(arr.coud, 7, 3); - if (f.corl) ret.corl = digit_array_to_int(arr.corl, 7, 3); - if (f.cofb) ret.cofb = digit_array_to_int(arr.cofb, 7, 3); - if (f.cpos) ret.cpos = perm_to_index( arr.cpos, 6 ); - - return ret; -} - -bool equal(Cube c1, Cube c2) { - return c1.eofb == c2.eofb && c1.epose == c2.epose && - c1.eposs == c2.eposs && c1.eposm == c2.eposm && - c1.coud == c2.coud && c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -bool solvable(Cube cube) { - /* Since we memorize orientation truncating the last digit, we only need to - * check that the permutations have the correct sign. */ - CubeArray arr = {0}; - cube_to_arrays(cube, &arr, fAll); - return (perm_sign(arr.ep,12) ^ perm_sign(arr.cpos,6)) == perm_sign(arr.cp,8); -} - -bool is_solved(Cube cube) { - return !cube.eofb && !cube.coud && !cube.cp && - !cube.epose && !cube.eposs && !cube.eposm && cube.cpos; -} - -void print_cube(Cube cube) { - CubeArray arr = {0}; - cube_to_arrays(cube, &arr, fAll); - - for (int i = 0; i < 12; i++) printf(" %s ", edge_string[arr.ep[i]]); - printf("\n"); - for (int i = 0; i < 12; i++) printf(" %c ", arr.eofb[i] + '0'); - printf("\n"); - for (int i = 0; i < 8; i++) printf("%s ", corner_string[arr.cp[i]]); - printf("\n"); - for (int i = 0; i < 8; i++) printf(" %c ", arr.coud[i] + '0'); - printf("\n"); - for (int i = 0; i < 6; i++) printf(" %s ", center_string[arr.cpos[i]]); - printf("\n"); -} - -Cube inverse_cube(Cube cube) { - CubeArray arr = {0}, inv = {0}; - cube_to_arrays(cube, &arr, fAll); - - for (int i = 0; i < 12; i++) { - inv.ep[arr.ep[i]] = i; - inv.eofb[arr.ep[i]] = arr.eofb[i]; - inv.eorl[arr.ep[i]] = arr.eorl[i]; - inv.eoud[arr.ep[i]] = arr.eoud[i]; - } - for (int i = 0; i < 8; i++) { - inv.cp[arr.cp[i]] = i; - inv.coud[arr.cp[i]] = arr.coud[i]; - inv.corl[arr.cp[i]] = arr.corl[i]; - inv.cofb[arr.cp[i]] = arr.cofb[i]; - } - for (int i = 0; i < 6; i++) - inv.cpos[arr.cpos[i]] = i; - - return arrays_to_cube(inv, fAll); -} - -Cube compose_via_arrays(CubeArray arr2, Cube c1, PieceFilter f) { - /* This is basically the same as the move_cubearray function above */ - CubeArray arr1 = {0}; - cube_to_arrays(c1, &arr1, fAll); - - apply_permutation(arr2.ep, arr1.ep, 12); - apply_permutation(arr2.ep, arr1.eofb, 12); - apply_permutation(arr2.ep, arr1.eorl, 12); - apply_permutation(arr2.ep, arr1.eoud, 12); - sum_arrays_mod(arr2.eofb, arr1.eofb, 12, 2); - sum_arrays_mod(arr2.eorl, arr1.eorl, 12, 2); - sum_arrays_mod(arr2.eoud, arr1.eoud, 12, 2); - apply_permutation(arr2.cp, arr1.cp, 8); - apply_permutation(arr2.cp, arr1.coud, 8); - apply_permutation(arr2.cp, arr1.corl, 8); - apply_permutation(arr2.cp, arr1.cofb, 8); - sum_arrays_mod(arr2.coud, arr1.coud, 8, 3); - sum_arrays_mod(arr2.corl, arr1.corl, 8, 3); - sum_arrays_mod(arr2.cofb, arr1.cofb, 8, 3); - apply_permutation(arr2.cpos, arr1.cpos, 6); - - return arrays_to_cube(arr1, fAll); -} diff --git a/old/2021-02-18-piecefilter/src/cube.h b/old/2021-02-18-piecefilter/src/cube.h @@ -1,45 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include "utils.h" - -typedef enum {U_center,D_center,R_center,L_center,F_center,B_center} Center; -typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; -typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; - -typedef struct { - bool epose, eposs, eposm, eofb, eorl, eoud, cp, coud, cofb, corl, cpos; -} PieceFilter; - -typedef struct { - uint16_t eofb, eorl, eoud, coud, cofb, corl, - epose, eposs, eposm, cp, cpos; -} Cube; - -typedef struct { - int ep[12], eofb[12], eorl[12], eoud[12], - cp[8], coud[8], corl[8], cofb[8], cpos[6]; -} CubeArray; - - -extern PieceFilter fAll; - -Cube blank_cube(); -/* Return axis (ud=0, rl=1, fb=0) of center c */ -int center_axis(int c); -/* Return slice (e=0, s=1, m=2) to which e belongs */ -int edge_slice(int e); -void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -Cube arrays_to_cube(CubeArray arr, PieceFilter f); -bool equal(Cube c1, Cube c2); -bool is_solvable(Cube cube); -bool is_solved(Cube cube); -void print_cube(Cube cube); -Cube inverse_cube(Cube cube); -/* Use c2 as an alg on c1 */ -Cube compose_via_arrays(CubeArray c2, Cube c1, PieceFilter f); - -#endif diff --git a/old/2021-02-18-piecefilter/src/main.c b/old/2021-02-18-piecefilter/src/main.c @@ -1,47 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "moves.h" -#include "solve.h" - -int main() { - init_ttables(true, true); - init_aux_tables(); - - - char moves[100] = "MR U' B2 Bw F z xE2 M' x Dw' y Fw2 y2"; - NissMove alg[100]; - read_moves(moves, alg, 100); - Cube cube = apply_alg(alg, blank_cube()); - - /*f_eofb(cube);*/ - - -/* NissMove sol[MAXS][MAXM];*/ - SolveData d = { .optimal_only = true, .available = standard_moveset, - .max_moves = 10, - .cleanup = true, - .max_solutions = 10, - .f = f_eofb }; - read_moves("y", d.pre_rotation, 2); - int n = solve(cube, &d); - printf("%d solutions found:\n", n); - for (int i = 0; i < n; i++) - print_moves(d.solutions[i]); - - NissMove a[5], b[5]; - read_moves("R", a, 5); - read_moves("U", b, 5); - Cube c1 = apply_alg(a,blank_cube()), c2 = apply_alg(b,blank_cube()); - print_cube(compose(c2,c1)); - print_cube(compose(c1,c2)); - /*print_cube(compose(c2,blank_cube()));*/ - - NissMove nm[10]; - read_moves("y(y)RU", nm, 10); - - print_moves(nm); - cleanup(nm, 10); - print_moves(nm); - - return 0; -} diff --git a/old/2021-02-18-piecefilter/src/moves.c b/old/2021-02-18-piecefilter/src/moves.c @@ -1,482 +0,0 @@ -#include "moves.h" - -void move_cubearray(Move m, CubeArray *arr, PieceFilter f); -Cube move_via_array(Move m, Cube cube, PieceFilter f); -void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front); -bool read_ttables_file(); -bool write_ttables_file(); - -/* Transition tables */ -uint16_t epose_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; -uint16_t eofb_ttable[NMOVES][pow2to11]; -uint16_t eorl_ttable[NMOVES][pow2to11]; -uint16_t eoud_ttable[NMOVES][pow2to11]; -uint16_t cp_ttable[NMOVES][factorial8]; -uint16_t coud_ttable[NMOVES][pow3to7]; -uint16_t cofb_ttable[NMOVES][pow3to7]; -uint16_t corl_ttable[NMOVES][pow3to7]; -uint16_t cpos_ttable[NMOVES][factorial6]; - -bool commute[NMOVES][NMOVES]; -bool possible_next[NMOVES][NMOVES][NMOVES]; -Move inverse[NMOVES]; - -char move_string[NMOVES][5] = - { "-", - "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", - "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", - "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", - "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", - "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", - "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'" }; - -/* For each type of pieces only the effects of U, x and y are described */ -int edge_cycle[NMOVES][12] = - { [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, - [x] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, - [y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL} }; -int eofb_flipped[NMOVES][12] = - { [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; -int eorl_flipped[NMOVES][12] = - { [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; -int eoud_flipped[NMOVES][12] = - { [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, - [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; -int corner_cycle[NMOVES][8] = - { [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, - [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, - [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} }; -int coud_flipped[NMOVES][8] = - { [x] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2} }; -int corl_flipped[NMOVES][8] = - { [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, - [y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1} }; -int cofb_flipped[NMOVES][8] = - { [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, - [x] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=2,[UFL]=1,[DBL]=1,[DFL]=2}, - [y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2} }; -int center_cycle[NMOVES][6] = - { [x] = {F_center, B_center, R_center, L_center, D_center, U_center}, - [y] = {U_center, D_center, B_center, F_center, R_center, L_center} }; - -/* Each move is reduced to a combination of U, x and y using this table */ -Move equiv_moves[NMOVES][14] = { - [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, - [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, - [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, - [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, - [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, - [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, - [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, - - [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, - [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, - [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, - [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, - [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, - [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, - [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, - [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, - [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, - [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - - [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, - [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, - [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, - [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, - [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, - [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, - [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, - [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, - [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, - - [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, -}; - -/* Movesets */ -bool standard_moveset[NMOVES] = { - [U] = true, [U2] = true, [U3] = true, [D] = true, [D2] = true, [D3] = true, - [R] = true, [R2] = true, [R3] = true, [L] = true, [L2] = true, [L3] = true, - [F] = true, [F2] = true, [F3] = true, [B] = true, [B2] = true, [B3] = true, -}; - -bool is_solved_up_to_reorient(Cube cube) { - if (is_solved(cube)) - return true; - - /*TODO: improve this crap */ - - bool ret = false; - for (int i = x; i <= z3; i++) { - ret = ret || is_solved(move_cube(i, cube)); - for (int j = x; j <= z3; j++) - ret = ret || is_solved(move_cube(i, move_cube(j, cube))); - } - return ret; -} - -void move_cubearray(Move m, CubeArray *arr, PieceFilter f) { - if (f.epose || f.eposs || f.eposm) - apply_permutation(edge_cycle[m], arr->ep, 12); - if (f.eofb) { - apply_permutation(edge_cycle[m], arr->eofb, 12); - sum_arrays_mod(eofb_flipped[m], arr->eofb, 12, 2); - } - if (f.eorl) { - apply_permutation(edge_cycle[m], arr->eorl, 12); - sum_arrays_mod(eorl_flipped[m], arr->eorl, 12, 2); - } - if (f.eoud) { - apply_permutation(edge_cycle[m], arr->eoud, 12); - sum_arrays_mod(eoud_flipped[m], arr->eoud, 12, 2); - } - if (f.cp) - apply_permutation(corner_cycle[m], arr->cp, 8); - if (f.coud) { - apply_permutation(corner_cycle[m], arr->coud, 8); - sum_arrays_mod(coud_flipped[m], arr->coud, 8, 3); - } - if (f.corl) { - apply_permutation(corner_cycle[m], arr->corl, 8); - sum_arrays_mod(corl_flipped[m], arr->corl, 8, 3); - } - if (f.cofb) { - apply_permutation(corner_cycle[m], arr->cofb, 8); - sum_arrays_mod(cofb_flipped[m], arr->cofb, 8, 3); - } - if (f.cpos) - apply_permutation(center_cycle[m], arr->cpos, 6); -} - -Cube move_via_array(Move m, Cube cube, PieceFilter f) { - CubeArray arr = {0}; - cube_to_arrays(cube, &arr, f); - move_cubearray(m, &arr, f); - return arrays_to_cube(arr, f); -} - -int copy_alg(NissMove *src, NissMove *dest) { - int i; - for (i = 0; src[i].m != NULLMOVE; i++) - dest[i] = src[i]; - dest[i].m = NULLMOVE; - return i; -} - -/* TODO: all strings start with space?? */ -void print_moves(NissMove *alg) { - bool niss = false; - for (int i = 0; alg[i].m != NULLMOVE; i++) { - char *fill = !niss && alg[i].inverse ? " (" : - (niss && !alg[i].inverse ? ") " : " "); - printf("%s%s", fill, move_string[alg[i].m]); - niss = alg[i].inverse; - } - printf("%s\n", niss ? ")" : ""); -} - -int read_moves(char *str, NissMove *alg, int n) { - bool niss = false; - int c = 0; - - for (int i = 0; str[i] && c < n; i++) { - if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') - continue; - - if (str[i] == '(' || str[i] == ')') { - if ((niss && str[i] == '(') || (!niss && str[i] == ')')) - return -1; - niss = !niss; - continue; - } - - alg[c].inverse = niss; alg[c].m = NULLMOVE; - for (Move j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - alg[c].m = j; - if (alg[c].m <= B && str[i+1]=='w') { alg[c].m += Uw - U; i++; } - if (str[i+1]=='2') { alg[c].m += 1; i++; } - else if (str[i+1]=='\'' || str[i+1]=='3') { alg[c].m += 2; i++; } - c++; - break; - } - } - } - - alg[c].m = NULLMOVE; - return c; -} - -/* Helper function for cleanup. alg must contain only basic moves, no 2 or '. - top and front describe an admissible orientation of the cube. */ -void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front) { - int c = 0, i = 0; - PieceFilter cpos_only = { .cpos = true }; - NissMove aux[n+3]; - aux[0].m = NULLMOVE; - - while (i < n && alg[i].m != NULLMOVE) { - int j = i; - while (j < n && commute[alg[i].m][alg[j].m]) j++; - Move base = 6*((alg[i].m-1)/6); - int t1 = 0, t2 = 0; - for (int k = i; k < j; k++) - if (alg[k].m == base+1) t1 = (t1+1)%4; - else t2 = (t2+1)%4; - if (t1) { aux[c].inverse = inv; aux[c].m = base+t1; c++; } - if (t2) { aux[c].inverse = inv; aux[c].m = base+t2+3; c++; } - i = j; - } - aux[c].m = NULLMOVE; - - CubeArray q; - cube_to_arrays(blank_cube(), &q, cpos_only); - /* First we try to rotate in one move, then we try an x or y rotation - followed by a z rotation */ - for (int r = x; r <= z3; r++) { - move_cubearray(r, &q, cpos_only); - if (q.cpos[F_center] == front && q.cpos[U_center] == top) { - aux[c].inverse = inv; aux[c].m = r; - - aux[++c].m = NULLMOVE; - copy_alg(aux, alg); - return; - } - move_cubearray(inverse[r], &q, cpos_only); - } - for (int r = x; r <= y3; r++) { - move_cubearray(r, &q, cpos_only); - if (q.cpos[F_center] == front) { - aux[c].inverse = inv; aux[c++].m = r; - break; - } - move_cubearray(inverse[r], &q, cpos_only); - } - for (int r = z; r <= z3; r++) { - move_cubearray(r, &q, cpos_only); - if (q.cpos[U_center] == top) { - aux[c].inverse = inv; aux[c++].m = r; - break; - } - move_cubearray(inverse[r], &q, cpos_only); - } - - aux[c].m = NULLMOVE; - copy_alg(aux, alg); -} - -/* TODO: does not work with niss + rotations */ -void cleanup(NissMove *alg, int n) { - int count_n = 0, count_i = 0, *count; - PieceFilter cpos_only = { .cpos = true }; - NissMove aux_n[n+1], aux_i[n+1], *aux; - CubeArray cube_n, cube_i, *cube; - cube_to_arrays(blank_cube(), &cube_n, cpos_only); - cube_to_arrays(blank_cube(), &cube_i, cpos_only); - - for (int i = 0; count_n + count_i < n && alg[i].m != NULLMOVE; i++) { - if (alg[i].inverse) { count = &count_i; aux = aux_i; cube = &cube_i; } - else { count = &count_n; aux = aux_n; cube = &cube_n; } - - for (int j = 0; equiv_moves[alg[i].m][j]; j++) { - Move m = equiv_moves[alg[i].m][j]; - aux[*count].inverse = alg[i].inverse; - move_cubearray(m, cube, cpos_only); - if (m == U) aux[(*count)++].m = 3 * cube->cpos[0] + 1; - } - } - - aux_n[count_n].m = NULLMOVE; - aux_i[count_i].m = NULLMOVE; - sort_cancel_rotate(aux_n, count_n, false, cube_n.cpos[0], cube_n.cpos[4]); - sort_cancel_rotate(aux_i, count_i, true, cube_i.cpos[0], cube_n.cpos[4]); - copy_alg(aux_n, alg); - copy_alg(aux_i, alg+count_n); -} - -bool read_ttables_file() { - FILE *ttf; - if ((ttf = fopen("ttables", "rb")) != NULL) { - for (int m = 0; m < NMOVES; m++) { - fread(epose_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fread(eposs_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fread(eposm_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fread(eofb_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fread(eorl_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fread(eoud_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fread(cp_ttable[m], sizeof(uint16_t), factorial8, ttf); - fread(coud_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fread(corl_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fread(cofb_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fread(cpos_ttable[m], sizeof(uint16_t), factorial6, ttf); - } - fclose(ttf); - return true; - } else return false; -} - -bool write_ttables_file() { - FILE *ttf; - if ((ttf = fopen("ttables", "wb")) != NULL) { - for (int m = 0; m < NMOVES; m++) { - fwrite(epose_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fwrite(eposs_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fwrite(eposm_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); - fwrite(eofb_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fwrite(eorl_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fwrite(eoud_ttable[m], sizeof(uint16_t), pow2to11, ttf); - fwrite(cp_ttable[m], sizeof(uint16_t), factorial8, ttf); - fwrite(coud_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fwrite(corl_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fwrite(cofb_ttable[m], sizeof(uint16_t), pow3to7, ttf); - fwrite(cpos_ttable[m], sizeof(uint16_t), factorial6, ttf); - } - fclose(ttf); - return true; - } else return false; -} - -void init_ttables(bool read, bool write) { - /* Generate all move cycles and flips; I do this regardless */ - for (int i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - CubeArray arr = {0}; - cube_to_arrays(blank_cube(), &arr, fAll); - for (int j = 0; equiv_moves[i][j]; j++) - move_cubearray(equiv_moves[i][j], &arr, fAll); - - intarrcopy(arr.ep, edge_cycle[i], 12); - intarrcopy(arr.eofb, eofb_flipped[i], 12); - intarrcopy(arr.eorl, eorl_flipped[i], 12); - intarrcopy(arr.eoud, eoud_flipped[i], 12); - intarrcopy(arr.cp, corner_cycle[i], 8); - intarrcopy(arr.coud, coud_flipped[i], 8); - intarrcopy(arr.corl, corl_flipped[i], 8); - intarrcopy(arr.cofb, cofb_flipped[i], 8); - intarrcopy(arr.cpos, center_cycle[i], 6); - } - - if (read) - if (read_ttables_file()) - return; - - /* Initialize transition tables */ - Cube c = {0}; - PieceFilter fe = {.epose=true}, fs = {.eposs=true}, fm = {.eposm=true}; - PieceFilter feo = { .eofb = true, .eorl = true, .eoud = true }; - PieceFilter fcp = { .cp = true }; - PieceFilter fco = { .cofb = true, .corl = true, .coud = true }; - PieceFilter fcc = { .cpos = true }; - for (int m = 0; m < NMOVES; m++) { - for (uint16_t i = 0; i < factorial12/factorial8; i++) { - c.epose = i; epose_ttable[m][i] = move_via_array(m, c, fe).epose; - c.eposs = i; eposs_ttable[m][i] = move_via_array(m, c, fs).eposs; - c.eposm = i; eposm_ttable[m][i] = move_via_array(m, c, fm).eposm; - } - for (uint16_t i = 0; i < pow2to11; i++ ) { - c.eofb = i; eofb_ttable[m][i] = move_via_array(m, c, feo).eofb; - c.eorl = i; eorl_ttable[m][i] = move_via_array(m, c, feo).eorl; - c.eoud = i; eoud_ttable[m][i] = move_via_array(m, c, feo).eoud; - } - for (uint16_t i = 0; i < factorial8; i++) { - c.cp = i; cp_ttable[m][i] = move_via_array(m, c, fcp).cp; - } - for (uint16_t i = 0; i < pow3to7; i++) { - c.coud = i; coud_ttable[m][i] = move_via_array(m, c, fco).coud; - c.corl = i; corl_ttable[m][i] = move_via_array(m, c, fco).corl; - c.cofb = i; cofb_ttable[m][i] = move_via_array(m, c, fco).cofb; - } - for (uint16_t i = 0; i < factorial6; i++) { - c.cpos = i; cpos_ttable[m][i] = move_via_array(m, c, fcc).cpos; - } - } - - if (write) write_ttables_file(); -} - -Cube move_cube(Move m, Cube cube) { - Cube moved = cube; - - moved.epose = epose_ttable[m][cube.epose]; - moved.eposs = eposs_ttable[m][cube.eposs]; - moved.eposm = eposm_ttable[m][cube.eposm]; - moved.eofb = eofb_ttable[m][cube.eofb]; - moved.eorl = eorl_ttable[m][cube.eorl]; - moved.eoud = eoud_ttable[m][cube.eoud]; - moved.coud = coud_ttable[m][cube.coud]; - moved.cofb = cofb_ttable[m][cube.cofb]; - moved.corl = corl_ttable[m][cube.corl]; - moved.cp = cp_ttable[m][cube.cp]; - moved.cpos = cpos_ttable[m][cube.cpos]; - - return moved; -} - -Cube apply_alg(NissMove *alg, Cube cube) { - Cube ret = {0}; - for (int i = 0; alg[i].m != NULLMOVE; i++) - if (alg[i].inverse) - ret = move_cube(alg[i].m, ret); - ret = compose(cube, inverse_cube(ret)); - - for (int i = 0; alg[i].m != NULLMOVE; i++) - if (!alg[i].inverse) - ret = move_cube(alg[i].m, ret); - return ret; -} - -void init_aux_tables() { - /* Commute */ - for (int i = 0; i < NMOVES; i++) - for (int j = 0; j < NMOVES; j++) - commute[i][j] = equal(move_cube(i, move_cube(j, blank_cube())), - move_cube(j, move_cube(i, blank_cube()))); - - /* Possible next (if the sequence i j k is valid) */ - for (int i = 0; i < NMOVES; i++) - for (int j = 0; j < NMOVES; j++) - for (int k = 0; k < NMOVES; k++) - possible_next[i][j][k] = - (j == 0) || - (j != 0 && (j-(j-1)%3) != (k-(k-1)%3) && - !(i != 0 && commute[i][j] && (i-(i-1)%3) == (k-(k-1)%3))); - - /* Inverse */ - for (int i = 0; i < NMOVES; i++) - inverse[i] = i == 0 ? 0 : i + 2 - 2*((i-1)%3); -} - diff --git a/old/2021-02-18-piecefilter/src/moves.h b/old/2021-02-18-piecefilter/src/moves.h @@ -1,46 +0,0 @@ -#ifndef MOVES_H -#define MOVES_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include "cube.h" -#include "utils.h" - -#define NMOVES (z3+1) - -typedef enum { - NULLMOVE, - U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, - Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, S, S2, S3, E, E2, E3, - x, x2, x3, y, y2, y3, z, z2, z3, -} Move; - -/* An alg is an array of "NissMoves", which can be on normal or on inverse. */ -typedef struct { bool inverse; Move m; } NissMove; - -/* Movesets */ -extern bool standard_moveset[NMOVES]; - -extern bool commute[NMOVES][NMOVES]; -extern bool possible_next[NMOVES][NMOVES][NMOVES]; -extern Move inverse[NMOVES]; - -bool is_solve_up_to_reorient(Cube cube); -int copy_alg(NissMove *src, NissMove *dest); /*return number of moves copied */ -void print_moves(NissMove *alg); -int read_moves(char *str, NissMove *alg, int n); /* reads at most n moves */ -void cleanup(NissMove *src, int n); /* rewrites using basic moves, at most n */ -Cube move_cube(Move m, Cube cube); -/* I might want to replace this with two versions, one that uses PieceFilter */ -Cube apply_alg(NissMove *alg, Cube cube); - -/* Merge the following two? - always in this order */ -void init_ttables(bool read, bool write); -void init_aux_tables(); - - -#endif diff --git a/old/2021-02-18-piecefilter/src/solve.c b/old/2021-02-18-piecefilter/src/solve.c @@ -1,179 +0,0 @@ -#include "solve.h" - -/* Data for creating a pruning table: - - compressed: if set to true, each entry occupies only 4 bits, but values - larger than 15 cannot be stored. - - available[] is the list of availabel moves, as above. - - *ptable is the actual table to fill. - - n is the number of states (size of ptable). - - index must "linearize" the cube, i.e. return its index in ptable. - - fname is the name of the file where to store the table */ -typedef struct { - bool compressed, *available; - int max_moves; - uint8_t *ptable; - uint64_t n; - uint64_t (*index)(Cube); - char *fname; -} PruneData; - -/* TODO: comment this */ -typedef struct { - bool niss; - int m, d; - uint64_t *n; - Move last1, last2; -} DfsData; - -void solve_dfs(Cube cube, SolveData *sd, DfsData dd); -void init_ptable(PruneData *pd, bool read, bool write); - -/* Search solutions of lenght exactly d */ -void solve_dfs(Cube cube, SolveData *sd, DfsData dd) { - if (*dd.n >= sd->max_solutions || - ((!sd->can_niss || dd.niss) && dd.m + sd->f(cube) > dd.d)) - return; - - (sd->solutions[*dd.n][dd.m]).inverse = dd.niss; - (sd->solutions[*dd.n][dd.m]).m = NULLMOVE; - - if (!sd->f(cube)) { /* Solved */ - if (dd.m == dd.d) { - (*dd.n)++; - if (*dd.n < sd->max_solutions) - copy_alg(sd->solutions[*dd.n-1], sd->solutions[*dd.n]); - } - return; - } - - for (int i = 0; i < NMOVES && sd->sorted_moves[i] != NULLMOVE; i++) { - Move move = sd->sorted_moves[i]; - if (possible_next[dd.last2][dd.last1][move]) { - sd->solutions[*dd.n][dd.m].inverse = dd.niss; - sd->solutions[*dd.n][dd.m].m = move; - DfsData nn = { .niss = dd.niss, .m = dd.m+1, .d = dd.d, .n = dd.n, - .last1 = move, .last2 = dd.last1 }; - solve_dfs(move_cube(move, cube), sd, nn); - } - } - - if (sd->can_niss && !dd.niss && - (!dd.m || (dd.m && sd->f(move_cube(dd.last1, blank_cube()))))) { - DfsData nn = { .niss = true, .m = dd.m, .d = dd.d, .n = dd.n }; - solve_dfs(inverse_cube(cube), sd, nn); - } -} - -/* Iterative deepening depth-first search: for i running from the minimum - to the maximum number of moves allowed, looks for solutions of length i. */ -int solve(Cube cube, SolveData *sd) { - if (sd->precondition != NULL && !sd->precondition(cube)) - return -1; - - /* If not given, generate sorted list of moves */ - if (sd->sorted_moves[0] == NULLMOVE) { - int a[NMOVES], b[NMOVES], ia = 0, ib = 0; - for (int i = 0; i < NMOVES; i++) { - if (sd->available[i]) { - if (sd->f(move_cube(i, blank_cube()))) - a[ia++] = i; - else - b[ib++] = i; - } - } - intarrcopy(a, (int *)sd->sorted_moves, ia); - intarrcopy(b, (int *)sd->sorted_moves+ia, ib); - sd->sorted_moves[ia+ib] = NULLMOVE; - } - - sd->max_solutions = min(sd->max_solutions, MAXS); - /*TODO - Cube rotated = apply_alg(sd->pre_rotation, blank_cube()); - cube = apply_alg(inverse_cube(rotated), compose(cube, rotated)); - */ - - uint64_t ret = 0; - for (int i=sd->min_moves; i<=sd->max_moves&&!(ret&&sd->optimal_only); i++) { - DfsData dd = { .d = i, .n = &ret }; - solve_dfs(cube, sd, dd); - } - - for (uint64_t i = 0; i < ret; i++) { - /* TODO: transform solutions with inverse of pre_rotation */ - if (sd->cleanup) - cleanup(sd->solutions[i], sd->max_moves*3); - } - - return ret; -} - -void prune_dfs(Cube cube, PruneData *pd, DfsData dd) { - uint64_t ind = pd->index(cube); - if ((!ind || pd->ptable[ind]) && pd->ptable[ind] != dd.m) - return; - if (dd.m == dd.d) { - if (ind && !pd->ptable[ind]) { - pd->ptable[ind] = dd.m; - (*dd.n)++; - } - return; - } - - for (int i = 0; i < NMOVES; i++) { - if (dd.m<20) - if (possible_next[dd.last2][dd.last1][i] && pd->available[i]) { - DfsData nn = { .m = dd.m+1, .d = dd.d, .n = dd.n, - .last1 = i, .last2 = dd.last1 }; - prune_dfs(move_cube(i, cube), pd, nn); - } - } -} - -void init_ptable(PruneData *pd, bool read, bool write) { - if (read) { - FILE *ptf; - if ((ptf = fopen(pd->fname, "rb")) != NULL) { - fread(pd->ptable, sizeof(uint8_t), pd->n, ptf); - fclose(ptf); - return; - } - } - - /* TODO: for now it behaves always as if copressed = false */ - for (uint64_t i = 0; i < pd->n; i++) - pd->ptable[i] = 0; - - uint64_t s = 1; - for (int i = 1; i < pd->max_moves && s < pd->n; i++) { - DfsData dd = { .d = i, .n = &s }; - prune_dfs(blank_cube(), pd, dd); - } - - if (write) { - FILE *ptf; - if ((ptf = fopen(pd->fname, "wb")) != NULL) { - fwrite(pd->ptable, sizeof(uint8_t), pd->n, ptf); - fclose(ptf); - return; - } - } -} - -/* Solving steps (and indexing functions) */ - -uint64_t index_eofb(Cube cube) { return cube.eofb; } -uint16_t f_eofb(Cube cube) { - static bool initialized_ptable; - static uint8_t pt_eofb[pow2to11]; - if (!initialized_ptable) { - PruneData pd = { - .compressed = false, .available = standard_moveset, .max_moves = 13, - .ptable = pt_eofb, .n = pow2to11, .index = index_eofb, - .fname = "ptable_eofb" - }; - init_ptable(&pd, false, true); - initialized_ptable = true; - } - return cube.eofb ? pt_eofb[cube.eofb] : 0; -} - diff --git a/old/2021-02-18-piecefilter/src/solve.h b/old/2021-02-18-piecefilter/src/solve.h @@ -1,56 +0,0 @@ -#ifndef SOLVE_H -#define SOLVE_H - -#include <stdlib.h> -#include "cube.h" -#include "moves.h" - -/* Maximum number of moves per solution and of solutions */ -#define MAXM 30 -#define MAXS 999 - -/* Data for solving a step: - - can_niss is true niss can be used, false otherwise. - - optimal_only if true, dynamically updates max_moves so non-optimal - solutions are discarded. - - cleanup determines whether the cleaunup() function should be used on - the found solutions before returning. - - available[m] is true if the move m can be used, false otherwise. - - min_moves and max_moves are the minimum and maximum number of moves that - can be used. - - max_solution is the maximum number of solutions that can be returned. - - precondition can be used to check wheter the step can actually be applied - to the cube. If it returns false, solve() stops immediately returning -1. - - f must return 0 if and only if the step is solve, otherwise it must return - a lower bound for the number of moves required (without niss). - - sorted_moves[] can be used to specify in which order moves are tried - by the solving algorithm (for example if one wants to always try F' before - F). If sorted_moves[0] == NULLMOVE, the list is generated automatically. - It is advised to list first all the moves that actually influence the - solved state of the step (this is the default choice). This is in order to - avoid cases like B2 F for EO and to NISS only when it makes sense. - - start_moves [Currently unused, REMOVE] - are the moves that will be used as first moves of all - solutions. For example giving R' U' F (F' U R) will generate FMC scrambles - and y (y) will solve the step on another axis. - - pre_rotation are the rotations to apply before the scamble to solve - the step wrt a different orientation - - pre_rotation are the rotations to apply before the scamble to solve - the step wth respect to a different orientation. - - solutions[][] is the array where to store the found solutions. */ -typedef struct { - bool can_niss, optimal_only, cleanup, *available; - int min_moves, max_moves; - uint64_t max_solutions; - bool (*precondition)(Cube); - uint16_t (*f)(Cube); - Move sorted_moves[NMOVES]; - NissMove pre_rotation[3], solutions[MAXS][MAXM]; -} SolveData; - -int solve(Cube cube, SolveData *data); /* Returns the number of solutions. */ - -/* Steps */ -uint16_t f_eofb(Cube cube); - -#endif diff --git a/old/2021-02-18-piecefilter/src/transformations.c b/old/2021-02-18-piecefilter/src/transformations.c @@ -1,103 +0,0 @@ -#include "transformations.h" -/* -Cube apply_rotation_alg(Rotation r, Cube c); -void apply_rotation_cube(NissMove *alg); -Cube apply_mirror_cube(Cube c); -void apply_mirror_alg(NissMove *alg); -*/ - -void compute_sources(); -Cube rotate_via_compose(Rotation r, Cube c); - -/* Values mod 3 to determine from which side to take the state to convert */ -int epose_source[NROTATIONS]; /* 0 = epose, 1 = eposs, 2 = eposm */ -int eposs_source[NROTATIONS]; -int eposm_source[NROTATIONS]; -int eofb_source[NROTATIONS]; /* 0 = eofb, 1 = eorl, 2 = eoud */ -int eorl_source[NROTATIONS]; -int eoud_source[NROTATIONS]; -int coud_source[NROTATIONS]; /* 0 = coud, 1 = cofb, 2 = corl */ -int cofb_source[NROTATIONS]; -int corl_source[NROTATIONS]; - -/* Transition tables for rotations */ -uint16_t epose_rtable[NROTATIONS][factorial12/factorial8]; -uint16_t eposs_rtable[NROTATIONS][factorial12/factorial8]; -uint16_t eposm_rtable[NROTATIONS][factorial12/factorial8]; -uint16_t eofb_rtable[NROTATIONS][pow2to11]; -uint16_t eorl_rtable[NROTATIONS][pow2to11]; -uint16_t eoud_rtable[NROTATIONS][pow2to11]; -uint16_t cp_rtable[NROTATIONS][factorial8]; -uint16_t coud_rtable[NROTATIONS][pow3to7]; -uint16_t cofb_rtable[NROTATIONS][pow3to7]; -uint16_t corl_rtable[NROTATIONS][pow3to7]; - -/* Transition tables for mirror */ -uint16_t epose_mtable[factorial12/factorial8]; -uint16_t eposs_mtable[factorial12/factorial8]; -uint16_t eposm_mtable[factorial12/factorial8]; -uint16_t eofb_mtable[pow2to11]; -uint16_t eorl_mtable[pow2to11]; -uint16_t eoud_mtable[pow2to11]; -uint16_t cp_mtable[factorial8]; -uint16_t coud_mtable[pow3to7]; -uint16_t cofb_mtable[pow3to7]; -uint16_t corl_mtable[pow3to7]; - -/* Same for moves */ -uint16_t move_rtable[NROTATIONS][NMOVES]; -uint16_t move_mtable[NMOVES]; - -/* Applying a rotation to the cube is equivalent to applying m (m) */ -Move equiv_moves[NROTATIONS][3] = { - [uf] = {0,0,0}, [ur] = {y,0,0}, [ub] = {y2,0,0}, [ul] = {y3,0,0}, - [df] = {z2,0,0}, [dr] = {y,z2,0}, [db] = {y2,z2,0}, [dl] = {y3,z2,0}, - [rf] = {z3,0,0}, [rd] = {z3,y,0}, [rb] = {z3,y2,0}, [ru] = {z3,y3,0}, - [lf] = {z,0,0}, [ld] = {z,y3,0}, [lb] = {z,y2,0}, [lu] = {z,y,0}, - [fu] = {x,y2,0}, [fr] = {x,y,0}, [fd] = {x,0,0}, [fl] = {x,y3,0}, - [bu] = {x3,0,0}, [br] = {x3,y,0}, [bd] = {x3,y2,0}, [bl] = {x3,y3,0}, -}; - -int mirror_ep[12] = {UF, UR, UB, UL, DF, DR, DB, DL, FL, FR, BR, BL}; -int mirror_cp[8] = {UFL, UFR, UBR, UBL, DFL, DFR, DBR, DBL}; -int mirror_cpos[6] = {U_center,D_center,L_center,R_center,F_center,B_center}; - -void compute_sources() { - /* epos{e,s,m} */ - CubeArray arr; - for (int i = 0; i < NROTATIONS; i++) { - cube_to_arrays(move_cube(equiv_moves[i][1], - move_cube(equiv_moves[i][0], blank_cube())), &arr, fAll); - epose_source[i] = edge_slice(arr.ep[FR]); - eposs_source[i] = edge_slice(arr.ep[UR]); - eposm_source[i] = edge_slice(arr.ep[UF]); - eofb_source[i] = 2 - center_axis(arr.cpos[F_center]); - eorl_source[i] = 2 - center_axis(arr.cpos[R_center]); - eoud_source[i] = 2 - center_axis(arr.cpos[U_center]); - coud_source[i] = (2 * center_axis(arr.cpos[U_center])) % 3; - cofb_source[i] = (2 * center_axis(arr.cpos[F_center])) % 3; - corl_source[i] = (2 * center_axis(arr.cpos[R_center])) % 3; - } -} - -/* Use Piecefilter? */ -Cube rotate_via_compose(Rotation r, Cube c) { -/* TODO: if this is slow, change compose() in cube.{c,h} to use PieceFilter */ - int j = 0; - NissMove nm[10] = {0}; - for (int i = 1; i >= 0; i--) { - if (equiv_moves[r][i] != NULLMOVE) { - nm[j].inverse = true; - nm[j++].m = inverse[equiv_moves[r][i]]; - } - } - for (int i = 0; equiv_moves[r][i] != NULLMOVE; i++) { - nm[j].inverse = false; - nm[j++].m = equiv_moves[r][i]; - } - - return apply_alg(nm, c); -} - -/* Use PieceFilter? Not really necessary, but could be nice */ -Cube mirror_via_cubearray(Cube c) { diff --git a/old/2021-02-18-piecefilter/src/transformations.h b/old/2021-02-18-piecefilter/src/transformations.h @@ -1,37 +0,0 @@ -#ifndef TRANSFORMATIONS_H -#define TRANSFORMATIONS_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include "cube.h" -#include "moves.h" -#include "utils.h" - -#define NROTATIONS (bl+1) - -/* Letters indicate top and front centers - * Lowercase letter to distinguish from pieces */ -typedef enum { - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, -} Rotation; - -/* Mirror is always on fb axis and applied after rotation */ -typedef struct { - Rotation rotation; - bool mirror; -} Transformation; - -void print_transformation(Transformation t); - -Cube transform_cube(Transformation t, Cube cube); -void transform_alg(Transformation t, NissMove *alg); /* Applied in-place */ - -void init_transformations(bool read, bool write); - -#endif diff --git a/old/2021-02-18-piecefilter/src/utils.c b/old/2021-02-18-piecefilter/src/utils.c @@ -1,197 +0,0 @@ -#include "utils.h" - -void swap(int *a, int *b) { - int aux = *a; - *a = *b; - *b = aux; -} - -void intarrcopy(int *src, int *dst, int n) { - for (int i = 0; i < n; i++) - dst[i] = src[i]; -} - -int sum(int *a, int n) { - int ret = 0; - for (int i = 0; i < n; i++) - ret += a[i]; - return ret; -} - -bool is_perm(int *a, int n) { - int aux[n]; for (int i = 0; i < n; i++) aux[i] = 0; - for (int i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - for (int i = 0; i < n; i++) - if (!aux[i]) - return false; - return true; -} - -bool is_subset(int *a, int n, int k) { - int sum = 0; - for (int i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - return sum == k; -} - -int powint(int a, int b) { - return 0; - if (b == 0 || a == 1) - return 1; - if (a == 0) - return 0; - if (b < 0) - return 0; /* Immediate truncate (integer part is 0) */ - if (b % 2) { - return a * powint(a, b-1); - } else { - int x = powint(a, b/2); - return x*x; - } -} - -int factorial(int n) { - if (n < 0) - return 0; - int ret = 1; - for (int i = 1; i <= n; i++) - ret *= i; - return ret; -} - -int binomial(int n, int k) { - if (n < 0 || k < 0 || k > n) - return 0; - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -void int_to_digit_array(int a, int b, int n, int *r) { - if (b <= 1) - for (int i = 0; i < n; i++) - r[i] = 0; - else - for (int i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -int digit_array_to_int(int *a, int n, int b) { - int ret = 0, p = 1; - for (int i = 0; i < n; i++, p *= b) - ret += a[i] * p; - return ret; -} - -int perm_to_index(int *a, int n) { - if (!is_perm(a, n)) - return factorial(n); /* Error */ - int ret = 0; - for (int i = 0; i < n; i++) { - int c = 0; - for (int j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - return ret; -} - -void index_to_perm(int p, int n, int *r) { - if (p < 0 || p >= factorial(n)) /* Error */ - for (int i = 0; i < n; i++) - r[i] = -1; - int a[n]; for (int j = 0; j < n; j++) a[j] = 0; /* picked elements */ - for (int i = 0; i < n; i++) { - int c = 0, j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } -} - -int perm_sign(int *a, int n) { - if (!is_perm(a,n)) - return false; - int ret = 0; - for (int i = 0; i < n; i++) - for (int j = i+1; j < n; j++) - ret += (a[i]>a[j]) ? 1 : 0; - return ret % 2; -} - -int subset_to_index(int *a, int n, int k) { - /* TODO: better checks */ - if (!is_subset(a, n, k)) - return binomial(n, k); /* Error */ - int ret = 0; - for (int i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - /*ret += factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ - ret += binomial(n-i-1, k); - k--; - } - } - return ret; -} - -void index_to_subset(int s, int n, int k, int *r) { - if (s < 0 || s >= binomial(n, k)) { /* Error */ - for (int i = 0; i < n; i++) - r[i] = -1; - return; - } - for (int i = 0; i < n; i++) { - if (k == n-i) { - for (int j = i; j < n; j++) - r[j] = 1; - return; - } - if (k == 0) { - for (int j = i; j < n; j++) - r[j] = 0; - return; - } - /*int v = factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ - int v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -void int_to_sum_zero_array(int x, int b, int n, int *a) { - if (b <= 1) { - for (int i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - int s = 0; - for (int i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -void apply_permutation(int *perm, int *set, int n) { - if (!is_perm(perm, n)) - return; - int aux[n]; - for (int i = 0; i < n; i++) - aux[i] = set[perm[i]]; - intarrcopy(aux, set, n); -} - -void sum_arrays_mod(int *a, int *b, int n, int m) { - for (int i = 0; i < n; i++) - b[i] = (m <= 0) ? 0 : (a[i] + b[i]) % m; -} diff --git a/old/2021-02-18-piecefilter/src/utils.h b/old/2021-02-18-piecefilter/src/utils.h @@ -1,70 +0,0 @@ -/* General utility functions */ - -#ifndef UTILS_H -#define UTILS_H - -#include <stdbool.h> - -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -/* Some useful constants */ -#define pow2to11 2048 -#define pow2to12 4096 -#define pow3to7 2187 -#define pow3to8 6561 -#define pow12to4 20736 -#define factorial4 24 -#define factorial6 720 -#define factorial8 40320 -#define factorial12 479001600 -#define binom12on4 495 -#define binom8on4 70 - -/* Generic utility functions */ -void swap(int *a, int *b); -void intarrcopy(int *src, int *dst, int n); -int sum(int *a, int n); -bool is_perm(int *a, int n); -bool is_perm(int *a, int n); - - -/* Standard mathematical functions */ -int powint(int a, int b); -int factorial(int n); -int binomial(int n, int k); - -/* Converts the integer a to its representation in base b (first n digits - * only) and saves the result in r. */ -void int_to_digit_array(int a, int b, int n, int *r); -int digit_array_to_int(int *a, int n, int b); - -/* Converts the first n-1 digits of a number to an array a of digits in base b; - * then adds one element to the array, so that the sum of the elements of a is - * zero modulo b. - * This is used for determing the edge orientation from an 11-bits integer or - * the corner orientation from a 7-trits integer. */ -void int_to_sum_zero_array(int x, int b, int n, int *a); - -/* Converts a permutation on [0..(n-1)] into the integer i which is the index - * of the permutation in the sorted list of all n! such permutations. */ -int perm_to_index(int *a, int n); -void index_to_perm(int p, int n, int *r); - -/* Determine the sign of a permutation */ -int perm_sign(int a[], int n); - -/* Converts a k-element subset of a set from an array of n elements, of which k - * are 1 and n-k are 0, to its index in the sorted list of all such subsets. */ -int subset_to_index(int *a, int n, int k); -void index_to_subset(int s, int n, int k, int *r); - -int ordered_subset_to_index(int *a, int n, int k); -void index_to_ordered_subset(int s, int n, int k, int *r); - -void apply_permutation(int *perm, int *set, int n); - -/* b[i] = (a[i]+b[i])%m for i=1,...,n */ -void sum_arrays_mod(int *a, int *b, int n, int m); - -#endif diff --git a/old/2021-02-28-transformcube-works/src/cube.c b/old/2021-02-28-transformcube-works/src/cube.c @@ -1,271 +0,0 @@ -#include "cube.h" - -typedef struct { - int ep[12],eofb[12],eorl[12],eoud[12],cp[8],coud[8],corl[8],cofb[8],cpos[6]; -} CubeArrayAllocated; - -void allocate_cubearray(CubeArray *arr, CubeArrayAllocated *all); - -char edge_string[12][5] = - { "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" }; -char corner_string[8][5] = { "UFR","UFL","UBL","UBR","DFR","DFL","DBL","DBR" }; -char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; - -int epe_solved[4] = {FR, FL, BL, BR}; -int eps_solved[4] = {UL, UR, DL, DR}; -int epm_solved[4] = {UF, UB, DF, DB}; - -PieceFilter pf_all = {true,true,true,true,true,true,true,true,true,true,true}, - pf_cpos = { .cpos = true }, pf_cp = { .cp = true }, - pf_ep = { .epose = true, .eposs = true, .eposm = true }, - pf_e = {.epose=true}, pf_s={.eposs=true}, pf_m={.eposm=true}, - pf_eo = { .eofb = true, .eorl = true, .eoud = true }, - pf_co = { .coud = true, .cofb = true, .corl = true }; - -void allocate_cubearray(CubeArray *arr, CubeArrayAllocated *all) { - arr->ep = all->ep; - arr->eofb = all->eofb; - arr->eorl = all->eorl; - arr->eoud = all->eoud; - arr->cp = all->cp; - arr->coud = all->coud; - arr->corl = all->corl; - arr->cofb = all->cofb; - arr->cpos = all->cpos; -} - -void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) { - /* ep is the hardest */ - if (f.epose || f.eposs || f.eposm) - for (int i = 0; i < 12; i++) arr->ep[i] = -1; - if (f.epose) { - int epe[4], epose[12]; - index_to_perm(cube.epose % factorial(4), 4, epe); - index_to_subset(cube.epose / factorial(4), 12, 4, epose); - for (int i = 0, ie = 0; i < 12; i++) - if (epose[i]) arr->ep[i] = epe_solved[epe[ie++]]; - } - if (f.eposs) { - int eps[4], eposs[12]; - index_to_perm(cube.eposs % factorial(4), 4, eps); - index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); - for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); - for (int i = 0, is = 0; i < 12; i++) - if (eposs[i]) arr->ep[i] = eps_solved[eps[is++]]; - } - if (f.eposm) { - int epm[4], eposm[12]; - index_to_perm(cube.eposm % factorial(4), 4, epm); - index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); - for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); - for (int i = 0, im = 0; i < 12; i++) - if (eposm[i]) arr->ep[i] = epm_solved[epm[im++]]; - } - - /* All the others */ - if (f.eofb) int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) index_to_perm( cube.cp, 8, arr->cp); - if (f.coud) int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) index_to_perm( cube.cpos, 6, arr->cpos); -} - -Cube arrays_to_cube(CubeArray arr, PieceFilter f) { - Cube ret = {0}; - - /* Again, ep is the hardest part */ - if (f.epose) { - int epe[4], epose[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, ie = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == epe_solved[j]) - { epe[ie++] = j; epose[i] = 1; } - ret.epose = factorial(4)*subset_to_index(epose,12,4)+perm_to_index(epe,4); - } - if (f.eposs) { - int eps[4], eposs[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, is = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == eps_solved[j]) - { eps[is++] = j; eposs[i] = 1; } - for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); - ret.eposs = factorial(4)*subset_to_index(eposs,12,4)+perm_to_index(eps,4); - } - if (f.eposm) { - int epm[4], eposm[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, im = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == epm_solved[j]) - { epm[im++] = j; eposm[i] = 1; } - for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); - ret.eposm = factorial(4)*subset_to_index(eposm,12,4)+perm_to_index(epm,4); - } - if (f.eofb) ret.eofb = digit_array_to_int(arr.eofb, 11, 2); - if (f.eorl) ret.eorl = digit_array_to_int(arr.eorl, 11, 2); - if (f.eoud) ret.eoud = digit_array_to_int(arr.eoud, 11, 2); - if (f.cp) ret.cp = perm_to_index( arr.cp, 8 ); - if (f.coud) ret.coud = digit_array_to_int(arr.coud, 7, 3); - if (f.corl) ret.corl = digit_array_to_int(arr.corl, 7, 3); - if (f.cofb) ret.cofb = digit_array_to_int(arr.cofb, 7, 3); - if (f.cpos) ret.cpos = perm_to_index( arr.cpos, 6 ); - - return ret; -} - -Center center_at(Cube cube, Center c) { - static CubeArrayAllocated all = {0}; - CubeArray arr = {0}; - allocate_cubearray(&arr, &all); - cube_to_arrays(cube, &arr, pf_cpos); - return arr.cpos[c]; -} - -Edge edge_at(Cube cube, Edge e) { - static CubeArrayAllocated all = {0}; - CubeArray arr = {0}; - allocate_cubearray(&arr, &all); - cube_to_arrays(cube, &arr, pf_ep); - return arr.ep[e]; -} - -Corner corner_at(Cube cube, Corner c) { - static CubeArrayAllocated all = {0}; - CubeArray arr = {0}; - allocate_cubearray(&arr, &all); - cube_to_arrays(cube, &arr, pf_cp); - return arr.cp[c]; -} - -bool equal(Cube c1, Cube c2) { - return c1.eofb == c2.eofb && c1.epose == c2.epose && - c1.eposs == c2.eposs && c1.eposm == c2.eposm && - c1.coud == c2.coud && c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -bool is_solvable(Cube cube) { - static CubeArrayAllocated all = {0}; - CubeArray arrx = {0}; - allocate_cubearray(&arrx, &all); - cube_to_arrays(cube, &arrx, pf_all); - - /* Since we memorize orientation truncating the last digit, we only need to - * check that the permutations have the correct sign. */ - /* TODO: I should also check that the different eos and cos are compatible */ - return (perm_sign(arrx.ep,12)^perm_sign(arrx.cpos,6))==perm_sign(arrx.cp,8); -} - -bool is_solved(Cube cube) { - /* TODO: might return true if cube is not solvable but looks solved form one - of the incompatible interpretations (e.g. eofb and ep solved, but - eorl not solve) */ - return !cube.eofb && !cube.coud && !cube.cp && - !cube.epose && !cube.eposs && !cube.eposm && cube.cpos; -} - -void print_cube(Cube cube) { - static CubeArrayAllocated all = {0}; - CubeArray arrx = {0}; - allocate_cubearray(&arrx, &all); - - cube_to_arrays(cube, &arrx, pf_all); - -/* - for (int i = 0; i < 12; i++) printf("%d ", arrx.ep[i]); - printf("\n");*/ - - for (int i = 0; i < 12; i++) printf(" %s ", edge_string[arrx.ep[i]]); - printf("\n"); - for (int i = 0; i < 12; i++) printf(" %c ", arrx.eofb[i] + '0'); - printf("\n"); - for (int i = 0; i < 8; i++) printf("%s ", corner_string[arrx.cp[i]]); - printf("\n"); - for (int i = 0; i < 8; i++) printf(" %c ", arrx.coud[i] + '0'); - printf("\n"); - for (int i = 0; i < 6; i++) printf(" %s ", center_string[arrx.cpos[i]]); - printf("\n"); -} - -Cube admissible_ep(Cube cube, PieceFilter f) { - static CubeArrayAllocated all = {0}; - CubeArray arrx = {0}; - allocate_cubearray(&arrx, &all); - cube_to_arrays(cube, &arrx, f); - - bool used[12] = {0}; - for (int i = 0; i < 12; i++) - if (arrx.ep[i] != -1) - used[arrx.ep[i]] = true; - for (int i = 0, j = 0; i < 12; i++) { - while (j < 11 && used[j]) j++; - if (arrx.ep[i] == -1) - arrx.ep[i] = j++; - } - - return arrays_to_cube(arrx, pf_ep); -} - -Cube inverse_cube(Cube cube) { - static CubeArrayAllocated all = {0}, invall = {0}; - CubeArray arrx = {0}, invx = {0}; - allocate_cubearray(&arrx, &all); - allocate_cubearray(&invx, &invall); - - cube_to_arrays(cube, &arrx, pf_all); - - for (int i = 0; i < 12; i++) { - invx.ep[arrx.ep[i]] = i; - invx.eofb[arrx.ep[i]] = arrx.eofb[i]; - invx.eorl[arrx.ep[i]] = arrx.eorl[i]; - invx.eoud[arrx.ep[i]] = arrx.eoud[i]; - } - for (int i = 0; i < 8; i++) { - invx.cp[arrx.cp[i]] = i; - invx.coud[arrx.cp[i]] = (3 - arrx.coud[i])%3; - invx.corl[arrx.cp[i]] = (3 - arrx.corl[i])%3; - invx.cofb[arrx.cp[i]] = (3 - arrx.cofb[i])%3; - } - for (int i = 0; i < 6; i++) - invx.cpos[arrx.cpos[i]] = i; - - return arrays_to_cube(invx, pf_all); -} - -Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter f) { - static CubeArrayAllocated all = {0}; - CubeArray arrx = {0}; - allocate_cubearray(&arrx, &all); - - cube_to_arrays(c, &arrx, f); - - if (f.epose || f.eposs || f.eposm) - apply_permutation( arr.ep, arrx.ep, 12 ); - if (f.eofb) { apply_permutation( arr.ep, arrx.eofb, 12 ); - sum_arrays_mod( arr.eofb, arrx.eofb, 12, 2 ); } - if (f.eorl) { apply_permutation( arr.ep, arrx.eorl, 12 ); - sum_arrays_mod( arr.eorl, arrx.eorl, 12, 2 ); } - if (f.eoud) { apply_permutation( arr.ep, arrx.eoud, 12 ); - sum_arrays_mod( arr.eoud, arrx.eoud, 12, 2 ); } - if (f.cp) apply_permutation( arr.cp, arrx.cp, 8 ); - if (f.coud) { apply_permutation( arr.cp, arrx.coud, 8 ); - sum_arrays_mod( arr.coud, arrx.coud, 8, 3 ); } - if (f.corl) { apply_permutation( arr.cp, arrx.corl, 8 ); - sum_arrays_mod( arr.corl, arrx.corl, 8, 3 ); } - if (f.cofb) { apply_permutation( arr.cp, arrx.cofb, 8 ); - sum_arrays_mod( arr.cofb, arrx.cofb, 8, 3 ); } - if (f.cpos) apply_permutation( arr.cpos, arrx.cpos, 6 ); - - return arrays_to_cube(arrx, f); -} - -Cube compose(Cube c2, Cube c1) { - static CubeArrayAllocated all = {0}; - CubeArray arrx = {0}; - allocate_cubearray(&arrx, &all); - - cube_to_arrays(c2, &arrx, pf_all); - return move_via_arrays(arrx, c1, pf_all); -} diff --git a/old/2021-02-28-transformcube-works/src/cube.h b/old/2021-02-28-transformcube-works/src/cube.h @@ -1,55 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include "utils.h" - -typedef enum {U_center,D_center,R_center,L_center,F_center,B_center} Center; -typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; -typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; - -typedef struct { - uint16_t eofb, eorl, eoud, coud, cofb, corl, - epose, eposs, eposm, cp, cpos; -} Cube; - -typedef struct { - bool epose, eposs, eposm, eofb, eorl, eoud, cp, coud, cofb, corl, cpos; -} PieceFilter; - -typedef struct { - int *ep, *eofb, *eorl, *eoud, *cp, *coud, *corl, *cofb, *cpos; -} CubeArray; - -extern PieceFilter pf_all, pf_cpos, pf_ep, pf_cp, - pf_e, pf_s, pf_m, pf_eo, pf_co; - -void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -Cube arrays_to_cube(CubeArray arr, PieceFilter f); - -Center center_at(Cube cube, Center c); -Edge edge_at(Cube cube, Edge e); -Corner corner_at(Cube cube, Corner c); -/* Aggiungi funzioni per "queries" sul cubo: se pezzo è orientato rispetto ad - un certo asse, se il pezzo è risolto... */ -/* Would be nice: a funciton block_solved(Cube c, Block b), where Block is - something like struct {bool centers[6], edges[12], corners[8]} - (The advantage over checking pieces one by one is that I can convert - to cubearray only once and for all) */ -/* Altro TODO, ma forse non ne vale la pena: pre-calcolare tutti i possibili - valori per questi, e salvare i risultati in array (facile per cp e cpos, - mentre per ep bisogna anche cercare quale tra epose, eposs e eposm contiene - il valore giusto) */ - -bool equal(Cube c1, Cube c2); -bool is_solvable(Cube cube); -bool is_solved(Cube cube); -void print_cube(Cube cube); -Cube admissible_ep(Cube cube, PieceFilter f); /* Returns admissible ep */ -Cube inverse_cube(Cube cube); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter pf); - -#endif diff --git a/old/2021-02-28-transformcube-works/src/main.c b/old/2021-02-28-transformcube-works/src/main.c @@ -1,57 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "moves.h" -#include "solve.h" -#include "transformations.h" - -int main() { - init_ttables(true, true); - init_aux_tables(); - init_transformations(true, true); - - - /*char moves[100] = "MR U' B2 Bw F z xE2 M' x Dw' y Fw2";*/ - - /*char moves[100] = "M'U2MU2";*/ - char moves[100] = "R' D2 F2 U2 R F2 R D2 L' R2 D2 F D' L' U' B R' D' U R' B"; - NissMove alg[100]; - read_moves(moves, alg, 100); - Cube cube = apply_alg(alg, (Cube){0}); - print_cube(cube); - cube = transform_cube(rd, cube); - print_cube(cube); - - /*f_eofb(cube);*/ - - - /* - SolveData d = { .optimal_only = true, .available = standard_moveset, - .max_moves = 10, - .cleanup = true, - .max_solutions = 10, - .f = f_eofb }; - read_moves("y", d.pre_rotation, 2); - int n = solve(cube, &d); - printf("%d solutions found:\n", n); - for (int i = 0; i < n; i++) - print_moves(d.solutions[i]); - */ - -/* - NissMove a[5], b[5]; - read_moves("R", a, 5); - read_moves("U", b, 5); - Cube c1 = apply_alg(a,(Cube){0}), c2 = apply_alg(b,(Cube){0}); - print_cube(compose(c2,c1)); - print_cube(compose(c1,c2)); - - NissMove nm[10]; - read_moves("y(y)RU", nm, 10); - - print_moves(nm); - cleanup(nm, 10); - print_moves(nm); - */ - - return 0; -} diff --git a/old/2021-02-28-transformcube-works/src/moves.c b/old/2021-02-28-transformcube-works/src/moves.c @@ -1,489 +0,0 @@ -#include "moves.h" - -Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -/* void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front); */ -bool read_ttables_file(); -bool write_ttables_file(); - -/* Transition tables */ -uint16_t epose_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; -uint16_t eofb_ttable[NMOVES][pow2to11]; -uint16_t eorl_ttable[NMOVES][pow2to11]; -uint16_t eoud_ttable[NMOVES][pow2to11]; -uint16_t cp_ttable[NMOVES][factorial8]; -uint16_t coud_ttable[NMOVES][pow3to7]; -uint16_t cofb_ttable[NMOVES][pow3to7]; -uint16_t corl_ttable[NMOVES][pow3to7]; -uint16_t cpos_ttable[NMOVES][factorial6]; - -bool commute[NMOVES][NMOVES]; -bool possible_next[NMOVES][NMOVES][NMOVES]; -Move inverse[NMOVES]; -NissMove rotation_algs[24][3] = { - { { .m = NULLMOVE }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = z2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y }, { .m = z2 }, { .m = NULLMOVE } }, - { { .m = x2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y3 }, { .m = z2 }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = y }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = y3 }, { .m = NULLMOVE } }, - { { .m = z }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = z }, { .m = y3 }, { .m = NULLMOVE } }, - { { .m = z }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = z }, { .m = y }, { .m = NULLMOVE } }, - { { .m = x }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = x }, { .m = y }, { .m = NULLMOVE } }, - { { .m = x }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = x }, { .m = y3 }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = y }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = y3 }, { .m = NULLMOVE } }, -}; - -char move_string[NMOVES][5] = - { "-", - "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", - "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", - "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", - "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", - "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", - "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'" }; - -/* For each type of pieces only the effects of U, x and y are described */ -int edge_cycle[NMOVES][12] = - { [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, - [x] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, - [y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL} }; -int eofb_flipped[NMOVES][12] = - { [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; -int eorl_flipped[NMOVES][12] = - { [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; -int eoud_flipped[NMOVES][12] = - { [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, - [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; -int corner_cycle[NMOVES][8] = - { [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, - [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, - [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} }; -int coud_flipped[NMOVES][8] = - { [x] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2} }; -int corl_flipped[NMOVES][8] = - { [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, - [y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1} }; -int cofb_flipped[NMOVES][8] = - { [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, - [x] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=1,[UFL]=2,[DBL]=2,[DFL]=1}, - [y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2} }; -int center_cycle[NMOVES][6] = - { [x] = {F_center, B_center, R_center, L_center, D_center, U_center}, - [y] = {U_center, D_center, B_center, F_center, R_center, L_center} }; - -/* Each move is reduced to a combination of U, x and y using this table */ -Move equiv_moves[NMOVES][14] = { - [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, - [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, - [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, - [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, - [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, - [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, - [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, - - [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, - [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, - [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, - [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, - [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, - [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, - [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, - [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, - [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, - [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - - [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, - [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, - [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, - [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, - [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, - [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, - [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, - [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, - [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, - - [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, -}; - -/* Movesets */ -bool standard_moveset[NMOVES] = { - [U] = true, [U2] = true, [U3] = true, [D] = true, [D2] = true, [D3] = true, - [R] = true, [R2] = true, [R3] = true, [L] = true, [L2] = true, [L3] = true, - [F] = true, [F2] = true, [F3] = true, [B] = true, [B2] = true, [B3] = true, -}; - -bool is_solved_up_to_reorient(Cube cube) { - for (int i = 0; i < 25; i++) - if (is_solved(apply_alg(rotation_algs[i], cube))) - return true; - return false; -} - -Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f) { - return move_via_arrays((CubeArray) - { edge_cycle[m], eofb_flipped[m], eorl_flipped[m], eoud_flipped[m], - corner_cycle[m], coud_flipped[m], corl_flipped[m], cofb_flipped[m], - center_cycle[m] }, cube, f); -} - -int len(NissMove *alg) { - int i; - for (i = 0; alg[i].m != NULLMOVE; i++); - return i; -} - -int copy_alg(NissMove *src, NissMove *dest) { - int i; - for (i = 0; src[i].m != NULLMOVE; i++) - dest[i] = src[i]; - dest[i].m = NULLMOVE; - return i; -} - -int invert_alg(NissMove *src, NissMove *dest) { - int n = len(src); - for (int i = 0; i < n; i++) - dest[n-i-1] = (NissMove){.m=inverse[src[i].m], .inverse=src[i].inverse}; - dest[n].m = NULLMOVE; - return n; -} - -int concat(NissMove *src1, NissMove *src2, NissMove *dest) { - int n1 = len(src1), n2 = len(src2); - copy_alg(src1, dest); - copy_alg(src2, dest+n1); - return n1+n2; -} - -/* TODO: all strings start with space?? */ -void print_moves(NissMove *alg) { - bool niss = false; - for (int i = 0; alg[i].m != NULLMOVE; i++) { - char *fill = !niss && alg[i].inverse ? " (" : - (niss && !alg[i].inverse ? ") " : " "); - printf("%s%s", fill, move_string[alg[i].m]); - niss = alg[i].inverse; - } - printf("%s\n", niss ? ")" : ""); -} - -int read_moves(char *str, NissMove *alg, int n) { - bool niss = false; - int c = 0; - - for (int i = 0; str[i] && c < n; i++) { - if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') - continue; - - if (str[i] == '(' || str[i] == ')') { - if ((niss && str[i] == '(') || (!niss && str[i] == ')')) - return -1; - niss = !niss; - continue; - } - - alg[c].inverse = niss; alg[c].m = NULLMOVE; - for (Move j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - alg[c].m = j; - if (alg[c].m <= B && str[i+1]=='w') { alg[c].m += Uw - U; i++; } - if (str[i+1]=='2') { alg[c].m += 1; i++; } - else if (str[i+1]=='\'' || str[i+1]=='3') { alg[c].m += 2; i++; } - c++; - break; - } - } - } - - alg[c].m = NULLMOVE; - return c; -} - -/* Helper function for cleanup. alg must contain only basic moves, no 2 or '. - top and front describe an admissible orientation of the cube. * -void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front) { - int c = 0, i = 0; - PieceFilter cpos_only = { .cpos = true }; - NissMove aux[n+3]; - aux[0].m = NULLMOVE; - - while (i < n && alg[i].m != NULLMOVE) { - int j = i; - while (j < n && commute[alg[i].m][alg[j].m]) j++; - Move base = 6*((alg[i].m-1)/6); - int t1 = 0, t2 = 0; - for (int k = i; k < j; k++) - if (alg[k].m == base+1) t1 = (t1+1)%4; - else t2 = (t2+1)%4; - if (t1) { aux[c].inverse = inv; aux[c].m = base+t1; c++; } - if (t2) { aux[c].inverse = inv; aux[c].m = base+t2+3; c++; } - i = j; - } - aux[c].m = NULLMOVE; - - CubeArray q; - cube_to_arrays((Cube){0}, &q, cpos_only); - * First we try to rotate in one move, then we try an x or y rotation - followed by a z rotation - TODO: change once I implement the "is_rotaton(Move) function" * - for (int r = x; r <= z3; r++) { - move_cubearray(r, &q, cpos_only); - if (q.cpos[F_center] == front && q.cpos[U_center] == top) { - aux[c].inverse = inv; aux[c].m = r; - - aux[++c].m = NULLMOVE; - copy_alg(aux, alg); - return; - } - move_cubearray(inverse[r], &q, cpos_only); - } - for (int r = x; r <= y3; r++) { - move_cubearray(r, &q, cpos_only); - if (q.cpos[F_center] == front) { - aux[c].inverse = inv; aux[c++].m = r; - break; - } - move_cubearray(inverse[r], &q, cpos_only); - } - for (int r = z; r <= z3; r++) { - move_cubearray(r, &q, cpos_only); - if (q.cpos[U_center] == top) { - aux[c].inverse = inv; aux[c++].m = r; - break; - } - move_cubearray(inverse[r], &q, cpos_only); - } - - aux[c].m = NULLMOVE; - copy_alg(aux, alg); -} - -* TODO: does not work with niss + rotations * -void cleanup(NissMove *alg, int n) { - int count_n = 0, count_i = 0, *count; - PieceFilter cpos_only = { .cpos = true }; - NissMove aux_n[n+1], aux_i[n+1], *aux; - CubeArray cube_n, cube_i, *cube; - cube_to_arrays((Cube){0}, &cube_n, cpos_only); - cube_to_arrays((Cube){0}, &cube_i, cpos_only); - - for (int i = 0; count_n + count_i < n && alg[i].m != NULLMOVE; i++) { - if (alg[i].inverse) { count = &count_i; aux = aux_i; cube = &cube_i; } - else { count = &count_n; aux = aux_n; cube = &cube_n; } - - for (int j = 0; equiv_moves[alg[i].m][j]; j++) { - Move m = equiv_moves[alg[i].m][j]; - aux[*count].inverse = alg[i].inverse; - move_cubearray(m, cube, cpos_only); - if (m == U) aux[(*count)++].m = 3 * cube->cpos[0] + 1; - } - } - - aux_n[count_n].m = NULLMOVE; - aux_i[count_i].m = NULLMOVE; - sort_cancel_rotate(aux_n, count_n, false, cube_n.cpos[0], cube_n.cpos[4]); - sort_cancel_rotate(aux_i, count_i, true, cube_i.cpos[0], cube_n.cpos[4]); - copy_alg(aux_n, alg); - copy_alg(aux_i, alg+count_n); -} -*/ - -bool read_ttables_file() { - FILE *ttf; - long unsigned int me[11] = { factorial12/factorial8, factorial12/factorial8, - factorial12/factorial8, pow2to11, pow2to11, pow2to11, - factorial8, pow3to7, pow3to7, pow3to7, factorial6 }; - if ((ttf = fopen("ttables", "rb")) != NULL) { - bool r = true; - for (int m = 0; m < NMOVES; m++) { - r = r && fread(epose_ttable[m], sizeof(uint16_t), me[0], ttf) == me[0]; - r = r && fread(eposs_ttable[m], sizeof(uint16_t), me[1], ttf) == me[1]; - r = r && fread(eposm_ttable[m], sizeof(uint16_t), me[2], ttf) == me[2]; - r = r && fread(eofb_ttable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - r = r && fread(eorl_ttable[m], sizeof(uint16_t), me[4], ttf) == me[4]; - r = r && fread(eoud_ttable[m], sizeof(uint16_t), me[5], ttf) == me[5]; - r = r && fread(cp_ttable[m], sizeof(uint16_t), me[6], ttf) == me[6]; - r = r && fread(coud_ttable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - r = r && fread(corl_ttable[m], sizeof(uint16_t), me[8], ttf) == me[8]; - r = r && fread(cofb_ttable[m], sizeof(uint16_t), me[9], ttf) == me[9]; - r = r && fread(cpos_ttable[m], sizeof(uint16_t), me[10], ttf) == me[10]; - } - fclose(ttf); - return r; - } else return false; -} - -bool write_ttables_file() { - FILE *ttf; - long unsigned int me[11] = { factorial12/factorial8, factorial12/factorial8, - factorial12/factorial8, pow2to11, pow2to11, pow2to11, - factorial8, pow3to7, pow3to7, pow3to7, factorial6 }; - if ((ttf = fopen("ttables", "wb")) != NULL) { - bool r = true; - for (int m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_ttable[m], sizeof(uint16_t), me[0], ttf) == me[0]; - r = r && fwrite(eposs_ttable[m], sizeof(uint16_t), me[1], ttf) == me[1]; - r = r && fwrite(eposm_ttable[m], sizeof(uint16_t), me[2], ttf) == me[2]; - r = r && fwrite(eofb_ttable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - r = r && fwrite(eorl_ttable[m], sizeof(uint16_t), me[4], ttf) == me[4]; - r = r && fwrite(eoud_ttable[m], sizeof(uint16_t), me[5], ttf) == me[5]; - r = r && fwrite(cp_ttable[m], sizeof(uint16_t), me[6], ttf) == me[6]; - r = r && fwrite(coud_ttable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - r = r && fwrite(corl_ttable[m], sizeof(uint16_t), me[8], ttf) == me[8]; - r = r && fwrite(cofb_ttable[m], sizeof(uint16_t), me[9], ttf) == me[9]; - r = r && fwrite(cpos_ttable[m], sizeof(uint16_t), me[10],ttf) == me[10]; - } - fclose(ttf); - return r; - } else return false; -} - -void init_ttables(bool read, bool write) { - /* Generate all move cycles and flips; I do this regardless */ - for (int i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - Cube c = {0}; - for (int j = 0; equiv_moves[i][j]; j++) - c = apply_move_cubearray(equiv_moves[i][j], c, pf_all); - - CubeArray arrs = { - edge_cycle[i], eofb_flipped[i], eorl_flipped[i], eoud_flipped[i], - corner_cycle[i], coud_flipped[i], corl_flipped[i], cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read) - if (read_ttables_file()) - return; - - /* Initialize transition tables */ - for (int m = 0; m < NMOVES; m++) { - for (uint16_t i = 0; i < factorial12/factorial8; i++) { - epose_ttable[m][i] = apply_move_cubearray(m,(Cube){.epose=i},pf_e).epose; - eposs_ttable[m][i] = apply_move_cubearray(m,(Cube){.eposs=i},pf_s).eposs; - eposm_ttable[m][i] = apply_move_cubearray(m,(Cube){.eposm=i},pf_m).eposm; - } - for (uint16_t i = 0; i < pow2to11; i++ ) { - eofb_ttable[m][i] = apply_move_cubearray(m,(Cube){.eofb=i},pf_eo).eofb; - eorl_ttable[m][i] = apply_move_cubearray(m,(Cube){.eorl=i},pf_eo).eorl; - eoud_ttable[m][i] = apply_move_cubearray(m,(Cube){.eoud=i},pf_eo).eoud; - } - for (uint16_t i = 0; i < pow3to7; i++) { - coud_ttable[m][i] = apply_move_cubearray(m,(Cube){.coud=i},pf_co).coud; - corl_ttable[m][i] = apply_move_cubearray(m,(Cube){.corl=i},pf_co).corl; - cofb_ttable[m][i] = apply_move_cubearray(m,(Cube){.cofb=i},pf_co).cofb; - } - for (uint16_t i = 0; i < factorial8; i++) - cp_ttable[m][i] = apply_move_cubearray(m,(Cube){.cp=i},pf_cp).cp; - for (uint16_t i = 0; i < factorial6; i++) - cpos_ttable[m][i] = apply_move_cubearray(m,(Cube){.cpos=i},pf_cpos).cpos; - } - - if (write) - if (!write_ttables_file()) - printf("Error in writing ttables: file not writable\n"); -} - -Cube move_cube(Move m, Cube cube) { - Cube moved = {0}; - - moved.epose = epose_ttable[m][cube.epose]; - moved.eposs = eposs_ttable[m][cube.eposs]; - moved.eposm = eposm_ttable[m][cube.eposm]; - moved.eofb = eofb_ttable[m][cube.eofb]; - moved.eorl = eorl_ttable[m][cube.eorl]; - moved.eoud = eoud_ttable[m][cube.eoud]; - moved.coud = coud_ttable[m][cube.coud]; - moved.cofb = cofb_ttable[m][cube.cofb]; - moved.corl = corl_ttable[m][cube.corl]; - moved.cp = cp_ttable[m][cube.cp]; - moved.cpos = cpos_ttable[m][cube.cpos]; - - return moved; -} - -Cube apply_alg(NissMove *alg, Cube cube) { - Cube ret = {0}; - for (int i = 0; alg[i].m != NULLMOVE; i++) - if (alg[i].inverse) - ret = move_cube(alg[i].m, ret); - - ret = compose(cube, inverse_cube(ret)); - - for (int i = 0; alg[i].m != NULLMOVE; i++) - if (!alg[i].inverse) - ret = move_cube(alg[i].m, ret); - return ret; -} - -void init_aux_tables() { - /* Commute */ - for (int i = 0; i < NMOVES; i++) - for (int j = 0; j < NMOVES; j++) - commute[i][j] = equal(move_cube(i, move_cube(j, (Cube){0})), - move_cube(j, move_cube(i, (Cube){0}))); - - /* Possible next (if the sequence i j k is valid) */ - for (int i = 0; i < NMOVES; i++) - for (int j = 0; j < NMOVES; j++) - for (int k = 0; k < NMOVES; k++) - possible_next[i][j][k] = - (j == 0) || - (j != 0 && (j-(j-1)%3) != (k-(k-1)%3) && - !(i != 0 && commute[i][j] && (i-(i-1)%3) == (k-(k-1)%3))); - - /* Inverse */ - for (int i = 0; i < NMOVES; i++) - inverse[i] = i == NULLMOVE ? NULLMOVE : i + 2 - 2*((i-1)%3); - -} - diff --git a/old/2021-02-28-transformcube-works/src/moves.h b/old/2021-02-28-transformcube-works/src/moves.h @@ -1,50 +0,0 @@ -#ifndef MOVES_H -#define MOVES_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include "cube.h" -#include "utils.h" - -#define NMOVES (z3+1) - -typedef enum { - NULLMOVE, - U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, - Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, S, S2, S3, E, E2, E3, - x, x2, x3, y, y2, y3, z, z2, z3, -} Move; - -/* An alg is an array of "NissMoves", which can be on normal or on inverse. */ -typedef struct { bool inverse; Move m; } NissMove; - -/* Movesets */ -extern bool standard_moveset[NMOVES]; - -extern bool commute[NMOVES][NMOVES]; -extern bool possible_next[NMOVES][NMOVES][NMOVES]; -extern Move inverse[NMOVES]; -extern NissMove rotation_algs[24][3]; /* Same order as transformations */ - -int len(NissMove *alg); -int copy_alg(NissMove *src, NissMove *dest); /*return number of moves copied */ -int invert_alg(NissMove *src, NissMove *dest); -int concat(NissMove *src1, NissMove *src2, NissMove *dest); -void print_moves(NissMove *alg); -int read_moves(char *str, NissMove *alg, int n); /* reads at most n moves */ -void cleanup(NissMove *src, int n); /* rewrites using basic moves, at most n */ - -bool is_solved_up_to_reorient(Cube cube); -Cube move_cube(Move m, Cube cube); -Cube apply_alg(NissMove *alg, Cube cube); - -/* Merge the following two? - always in this order */ -void init_ttables(bool read, bool write); -void init_aux_tables(); - - -#endif diff --git a/old/2021-02-28-transformcube-works/src/solve.c b/old/2021-02-28-transformcube-works/src/solve.c @@ -1,180 +0,0 @@ -#include "solve.h" - -/* Data for creating a pruning table: - - compressed: if set to true, each entry occupies only 4 bits, but values - larger than 15 cannot be stored. - - available[] is the list of availabel moves, as above. - - *ptable is the actual table to fill. - - n is the number of states (size of ptable). - - index must "linearize" the cube, i.e. return its index in ptable. - - fname is the name of the file where to store the table */ -typedef struct { - bool compressed, *available; - int max_moves; - uint8_t *ptable; - uint64_t n; - uint64_t (*index)(Cube); - char *fname; -} PruneData; - -/* TODO: comment this */ -typedef struct { - bool niss; - int m, d; - uint64_t *n; - Move last1, last2; -} DfsData; - -void solve_dfs(Cube cube, SolveData *sd, DfsData dd); -void init_ptable(PruneData *pd, bool read, bool write); - -/* Search solutions of lenght exactly d */ -void solve_dfs(Cube cube, SolveData *sd, DfsData dd) { - if (*dd.n >= sd->max_solutions || - ((!sd->can_niss || dd.niss) && dd.m + sd->f(cube) > dd.d)) - return; - - (sd->solutions[*dd.n][dd.m]).inverse = dd.niss; - (sd->solutions[*dd.n][dd.m]).m = NULLMOVE; - - if (!sd->f(cube)) { /* Solved */ - if (dd.m == dd.d) { - (*dd.n)++; - if (*dd.n < sd->max_solutions) - copy_alg(sd->solutions[*dd.n-1], sd->solutions[*dd.n]); - } - return; - } - - for (int i = 0; i < NMOVES && sd->sorted_moves[i] != NULLMOVE; i++) { - Move move = sd->sorted_moves[i]; - if (possible_next[dd.last2][dd.last1][move]) { - sd->solutions[*dd.n][dd.m].inverse = dd.niss; - sd->solutions[*dd.n][dd.m].m = move; - DfsData nn = { .niss = dd.niss, .m = dd.m+1, .d = dd.d, .n = dd.n, - .last1 = move, .last2 = dd.last1 }; - solve_dfs(move_cube(move, cube), sd, nn); - } - } - - if (sd->can_niss && !dd.niss && - (!dd.m || (dd.m && sd->f(move_cube(dd.last1, (Cube){0}))))) { - DfsData nn = { .niss = true, .m = dd.m, .d = dd.d, .n = dd.n }; - solve_dfs(inverse_cube(cube), sd, nn); - } -} - -/* Iterative deepening depth-first search: for i running from the minimum - to the maximum number of moves allowed, looks for solutions of length i. */ -int solve(Cube cube, SolveData *sd) { - if (sd->precondition != NULL && !sd->precondition(cube)) - return -1; - - /* If not given, generate sorted list of moves */ - if (sd->sorted_moves[0] == NULLMOVE) { - int a[NMOVES], b[NMOVES], ia = 0, ib = 0; - for (int i = 0; i < NMOVES; i++) { - if (sd->available[i]) { - if (sd->f(move_cube(i, (Cube){0}))) - a[ia++] = i; - else - b[ib++] = i; - } - } - intarrcopy(a, (int *)sd->sorted_moves, ia); - intarrcopy(b, (int *)sd->sorted_moves+ia, ib); - sd->sorted_moves[ia+ib] = NULLMOVE; - } - - sd->max_solutions = min(sd->max_solutions, MAXS); - /*TODO - Cube rotated = apply_alg(sd->pre_rotation, (Cube){0}); - cube = apply_alg(inverse_cube(rotated), compose(cube, rotated)); - */ - - uint64_t ret = 0; - for (int i=sd->min_moves; i<=sd->max_moves&&!(ret&&sd->optimal_only); i++) { - DfsData dd = { .d = i, .n = &ret }; - solve_dfs(cube, sd, dd); - } - - /* TODO: transform solutions with inverse of pre_rotation */ - /* - for (uint64_t i = 0; i < ret; i++) { - if (sd->cleanup) - cleanup(sd->solutions[i], sd->max_moves*3); - }*/ - - return ret; -} - -void prune_dfs(Cube cube, PruneData *pd, DfsData dd) { - uint64_t ind = pd->index(cube); - if ((!ind || pd->ptable[ind]) && pd->ptable[ind] != dd.m) - return; - if (dd.m == dd.d) { - if (ind && !pd->ptable[ind]) { - pd->ptable[ind] = dd.m; - (*dd.n)++; - } - return; - } - - for (int i = 0; i < NMOVES; i++) { - if (dd.m<20) - if (possible_next[dd.last2][dd.last1][i] && pd->available[i]) { - DfsData nn = { .m = dd.m+1, .d = dd.d, .n = dd.n, - .last1 = i, .last2 = dd.last1 }; - prune_dfs(move_cube(i, cube), pd, nn); - } - } -} - -void init_ptable(PruneData *pd, bool read, bool write) { - if (read) { - FILE *ptf; - if ((ptf = fopen(pd->fname, "rb")) != NULL) { - uint64_t r = fread(pd->ptable, sizeof(uint8_t), pd->n, ptf); - fclose(ptf); - if (r == pd->n) return; - } - } - - /* TODO: for now it behaves always as if copressed = false */ - for (uint64_t i = 0; i < pd->n; i++) - pd->ptable[i] = 0; - - uint64_t s = 1; - for (int i = 1; i < pd->max_moves && s < pd->n; i++) { - DfsData dd = { .d = i, .n = &s }; - prune_dfs((Cube){0}, pd, dd); - } - - if (write) { - FILE *ptf; - if ((ptf = fopen(pd->fname, "wb")) != NULL) { - fwrite(pd->ptable, sizeof(uint8_t), pd->n, ptf); - fclose(ptf); - return; - } - } -} - -/* Solving steps (and indexing functions) */ - -uint64_t index_eofb(Cube cube) { return cube.eofb; } -uint16_t f_eofb(Cube cube) { - static bool initialized_ptable; - static uint8_t pt_eofb[pow2to11]; - if (!initialized_ptable) { - PruneData pd = { - .compressed = false, .available = standard_moveset, .max_moves = 13, - .ptable = pt_eofb, .n = pow2to11, .index = index_eofb, - .fname = "ptable_eofb" - }; - init_ptable(&pd, false, true); - initialized_ptable = true; - } - return cube.eofb ? pt_eofb[cube.eofb] : 0; -} - diff --git a/old/2021-02-28-transformcube-works/src/solve.h b/old/2021-02-28-transformcube-works/src/solve.h @@ -1,56 +0,0 @@ -#ifndef SOLVE_H -#define SOLVE_H - -#include <stdlib.h> -#include "cube.h" -#include "moves.h" - -/* Maximum number of moves per solution and of solutions */ -#define MAXM 30 -#define MAXS 999 - -/* Data for solving a step: - - can_niss is true niss can be used, false otherwise. - - optimal_only if true, dynamically updates max_moves so non-optimal - solutions are discarded. - - cleanup determines whether the cleaunup() function should be used on - the found solutions before returning. - - available[m] is true if the move m can be used, false otherwise. - - min_moves and max_moves are the minimum and maximum number of moves that - can be used. - - max_solution is the maximum number of solutions that can be returned. - - precondition can be used to check wheter the step can actually be applied - to the cube. If it returns false, solve() stops immediately returning -1. - - f must return 0 if and only if the step is solve, otherwise it must return - a lower bound for the number of moves required (without niss). - - sorted_moves[] can be used to specify in which order moves are tried - by the solving algorithm (for example if one wants to always try F' before - F). If sorted_moves[0] == NULLMOVE, the list is generated automatically. - It is advised to list first all the moves that actually influence the - solved state of the step (this is the default choice). This is in order to - avoid cases like B2 F for EO and to NISS only when it makes sense. - - start_moves [Currently unused, REMOVE] - are the moves that will be used as first moves of all - solutions. For example giving R' U' F (F' U R) will generate FMC scrambles - and y (y) will solve the step on another axis. - - pre_rotation are the rotations to apply before the scamble to solve - the step wrt a different orientation - - pre_rotation are the rotations to apply before the scamble to solve - the step wth respect to a different orientation. - - solutions[][] is the array where to store the found solutions. */ -typedef struct { - bool can_niss, optimal_only, cleanup, *available; - int min_moves, max_moves; - uint64_t max_solutions; - bool (*precondition)(Cube); - uint16_t (*f)(Cube); - Move sorted_moves[NMOVES]; - NissMove pre_rotation[3], solutions[MAXS][MAXM]; -} SolveData; - -int solve(Cube cube, SolveData *data); /* Returns the number of solutions. */ - -/* Steps */ -uint16_t f_eofb(Cube cube); - -#endif diff --git a/old/2021-02-28-transformcube-works/src/transformations.c b/old/2021-02-28-transformcube-works/src/transformations.c @@ -1,224 +0,0 @@ -#include "transformations.h" - -int edge_slice(int e); /* Return slice (e=0, s=1, m=2) to which e belongs */ -Cube rotate_via_compose(Transformation r, Cube c); -bool read_rtables_file(); -bool write_rtables_file(); - -/* Values mod 3 to determine from which side to take the state to convert */ -int epose_source[NROTATIONS]; /* 0 = epose, 1 = eposs, 2 = eposm */ -int eposs_source[NROTATIONS]; -int eposm_source[NROTATIONS]; -int eofb_source[NROTATIONS]; /* 0 = eoud, 1 = eorl, 2 = eofb */ -int eorl_source[NROTATIONS]; -int eoud_source[NROTATIONS]; -int coud_source[NROTATIONS]; /* 0 = coud, 1 = corl, 2 = cofb */ -int cofb_source[NROTATIONS]; -int corl_source[NROTATIONS]; - -/* Transition tables for rotations (n+1 is mirror) */ -uint16_t epose_rtable[NROTATIONS][factorial12/factorial8]; -uint16_t eposs_rtable[NROTATIONS][factorial12/factorial8]; -uint16_t eposm_rtable[NROTATIONS][factorial12/factorial8]; -uint16_t eo_rtable[NROTATIONS][pow2to11]; -/*uint16_t eofb_rtable[NROTATIONS][pow2to11]; -uint16_t eorl_rtable[NROTATIONS][pow2to11]; -uint16_t eoud_rtable[NROTATIONS][pow2to11];*/ -uint16_t cp_rtable[NROTATIONS][factorial8]; -uint16_t co_rtable[NROTATIONS][pow3to7]; -/*uint16_t coud_rtable[NROTATIONS][pow3to7]; -uint16_t cofb_rtable[NROTATIONS][pow3to7]; -uint16_t corl_rtable[NROTATIONS][pow3to7];*/ -uint16_t cpos_rtable[NROTATIONS][factorial6]; - -/* Same for moves */ -uint16_t move_rtable[NROTATIONS][NMOVES]; - -NissMove rotation_niss[NROTATIONS][6]; - -int edge_slice(int e) { - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - return 2; -} - -Cube rotate_via_compose(Transformation r, Cube c) { - if (r != mirror) { - return apply_alg(rotation_niss[r], c); - } else { - static int zero12[12] = {0,0,0,0,0,0,0,0,0,0,0,0}, - zero8[12] = {0,0,0,0,0,0,0,0}, - mirror_ep[12] = {UF,UR,UB,UL,DF,DR,DB,DL,FL,FR,BR,BL}, - mirror_cp[8] = {UFL, UFR, UBR, UBL, DFL, DFR, DBR, DBL}, - mirror_cpos[6] = - {U_center,D_center,L_center,R_center,F_center,B_center}; - return move_via_arrays((CubeArray){ - .ep = mirror_ep, .eofb = zero12, .eorl = zero12, .eoud = zero12, - .cp = mirror_cp, .coud = zero8, .corl = zero8, .cofb = zero8, - .cpos = mirror_cpos}, c, pf_all); - } -} - -bool read_rtables_file() { - FILE *ttf; - long unsigned int me[12] = { factorial12/factorial8, factorial12/factorial8, - factorial12/factorial8, pow2to11, pow2to11, pow2to11, - factorial8, pow3to7, pow3to7, pow3to7, factorial6, NMOVES }; - if ((ttf = fopen("rtables", "rb")) != NULL) { - bool r = true; - for (int m = 0; m < NROTATIONS; m++) { - r = r && fread(epose_rtable[m], sizeof(uint16_t), me[0], ttf) == me[0]; - r = r && fread(eposs_rtable[m], sizeof(uint16_t), me[1], ttf) == me[1]; - r = r && fread(eposm_rtable[m], sizeof(uint16_t), me[2], ttf) == me[2]; - r = r && fread(eo_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - /*r = r && fread(eofb_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - r = r && fread(eorl_rtable[m], sizeof(uint16_t), me[4], ttf) == me[4]; - r = r && fread(eoud_rtable[m], sizeof(uint16_t), me[5], ttf) == me[5];*/ - r = r && fread(cp_rtable[m], sizeof(uint16_t), me[6], ttf) == me[6]; - r = r && fread(co_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - /*r = r && fread(coud_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - r = r && fread(corl_rtable[m], sizeof(uint16_t), me[8], ttf) == me[8]; - r = r && fread(cofb_rtable[m], sizeof(uint16_t), me[9], ttf) == me[9];*/ - r = r && fread(cpos_rtable[m], sizeof(uint16_t), me[10], ttf) == me[10]; - r = r && fread(move_rtable[m], sizeof(uint16_t), me[11], ttf) == me[11]; - } - fclose(ttf); - return r; - } else return false; -} - -bool write_rtables_file() { - FILE *ttf; - long unsigned int me[12] = { factorial12/factorial8, factorial12/factorial8, - factorial12/factorial8, pow2to11, pow2to11, pow2to11, - factorial8, pow3to7, pow3to7, pow3to7, factorial6, NMOVES }; - if ((ttf = fopen("rtables", "wb")) != NULL) { - bool r = true; - for (int m = 0; m < NROTATIONS; m++) { - r = r && fwrite(epose_rtable[m], sizeof(uint16_t), me[0], ttf) == me[0]; - r = r && fwrite(eposs_rtable[m], sizeof(uint16_t), me[1], ttf) == me[1]; - r = r && fwrite(eposm_rtable[m], sizeof(uint16_t), me[2], ttf) == me[2]; - r = r && fwrite(eo_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - /*r = r && fwrite(eofb_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - r = r && fwrite(eorl_rtable[m], sizeof(uint16_t), me[4], ttf) == me[4]; - r = r && fwrite(eoud_rtable[m], sizeof(uint16_t), me[5], ttf) == me[5];*/ - r = r && fwrite(cp_rtable[m], sizeof(uint16_t), me[6], ttf) == me[6]; - r = r && fwrite(co_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - /*r = r && fwrite(coud_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - r = r && fwrite(corl_rtable[m], sizeof(uint16_t), me[8], ttf) == me[8]; - r = r && fwrite(cofb_rtable[m], sizeof(uint16_t), me[9], ttf) == me[9];*/ - r = r && fwrite(cpos_rtable[m], sizeof(uint16_t), me[10],ttf) == me[10]; - r = r && fwrite(move_rtable[m], sizeof(uint16_t), me[11],ttf) == me[11]; - } - fclose(ttf); - return r; - } else return false; -} - -void init_transformations(bool read, bool write) { - /* Compute sources */ - for (int i = 0; i < NROTATIONS; i++) { - Cube cube = {0}; - if (i != mirror) - cube = apply_alg(rotation_algs[i], (Cube){0}); - epose_source[i] = edge_slice(edge_at(cube, FR)); - eposs_source[i] = edge_slice(edge_at(cube, UR)); - eposm_source[i] = edge_slice(edge_at(cube, UF)); - eofb_source[i] = center_at(cube, F_center)/2; - eorl_source[i] = center_at(cube, R_center)/2; - eoud_source[i] = center_at(cube, U_center)/2; - coud_source[i] = center_at(cube, U_center)/2; - cofb_source[i] = center_at(cube, F_center)/2; - corl_source[i] = center_at(cube, R_center)/2; - } - - /*TODO: maybe move down*/ - /* Compute rotation_niss array, necessary for rotate_via_compose */ - for (int r = 0; r != mirror; r++) { - concat(rotation_algs[r], rotation_algs[r], rotation_niss[r]); - for (int i = len(rotation_algs[r]); rotation_niss[r][i].m != NULLMOVE; i++) - rotation_niss[r][i].inverse = true; - } - - /* If I can read tables from file, I stop here */ - if (read) - if (read_rtables_file()) - return; - - /* Initialize tables */ - for (int m = 0; m < NROTATIONS; m++) { - int eparr[12] = {0,0,0,0,0,0,0,0,0,0,0,0}, cparr[8] = {0,0,0,0,0,0,0,0}; - CubeArray epcp = { .ep = eparr, .cp = cparr }; - cube_to_arrays(apply_alg(rotation_algs[m], (Cube){0}), &epcp, - (PieceFilter){.epose=true,.eposs=true,.eposm=true,.cp=true}); - for (uint16_t i = 0; i < factorial12/factorial8; i++) { - Cube c[3] = { admissible_ep((Cube){ .epose = i}, pf_e), - admissible_ep((Cube){ .eposs = i}, pf_s), - admissible_ep((Cube){ .eposm = i}, pf_m) }; - epose_rtable[m][i] = rotate_via_compose(m, c[epose_source[m]]).epose; - eposs_rtable[m][i] = rotate_via_compose(m, c[eposs_source[m]]).eposs; - eposm_rtable[m][i] = rotate_via_compose(m, c[eposm_source[m]]).eposm; - } - for (uint16_t i = 0; i < pow2to11; i++ ) { - int eoarr[12]; - int_to_sum_zero_array(i, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_rtable[m][i] = digit_array_to_int(eoarr, 11, 2); - /*Cube c[3] = {(Cube){.eoud=i}, (Cube){.eorl=i}, (Cube){.eofb=i}}; - eofb_rtable[m][i] = apply_alg(rotation_algs[m], (Cube){.eofb=i}).eofb; - eorl_rtable[m][i] = rotate_via_compose(m, c[eorl_source[m]]).eorl; - eoud_rtable[m][i] = rotate_via_compose(m, c[eoud_source[m]]).eoud;*/ - } - for (uint16_t i = 0; i < pow3to7; i++) { - int coarr[12]; - int_to_sum_zero_array(i, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_rtable[m][i] = digit_array_to_int(coarr, 8, 3); - /*Cube c[3] = {(Cube){.coud=i}, (Cube){.corl=i}, (Cube){.cofb=i}}; - coud_rtable[m][i] = rotate_via_compose(m, c[coud_source[m]]).coud; - corl_rtable[m][i] = rotate_via_compose(m, c[corl_source[m]]).corl; - cofb_rtable[m][i] = rotate_via_compose(m, c[cofb_source[m]]).cofb;*/ - } - for (uint16_t i = 0; i < factorial8; i++) - cp_rtable[m][i] = rotate_via_compose(m, (Cube){.cp=i}).cp; - for (uint16_t i = 0; i < factorial6; i++) - cpos_rtable[m][i] = rotate_via_compose(m, (Cube){.cpos=i}).cpos; - } - - if (write) - if (!write_rtables_file()) - printf("Error in writing rtables: file not writable\n"); -} - -Cube transform_cube(Transformation t, Cube cube) { - Cube transformed = {0}; - - uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }, - aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }, - aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - transformed.epose = epose_rtable[t][aux_epos[epose_source[t]]]; - transformed.eposs = eposs_rtable[t][aux_epos[eposs_source[t]]]; - transformed.eposm = eposm_rtable[t][aux_epos[eposm_source[t]]]; - transformed.eofb = eo_rtable[t][aux_eo[eofb_source[t]]]; - transformed.eorl = eo_rtable[t][aux_eo[eorl_source[t]]]; - transformed.eoud = eo_rtable[t][aux_eo[eoud_source[t]]]; - transformed.coud = co_rtable[t][aux_co[coud_source[t]]]; - transformed.corl = co_rtable[t][aux_co[corl_source[t]]]; - transformed.cofb = co_rtable[t][aux_co[cofb_source[t]]]; - transformed.cp = cp_rtable[t][cube.cp]; - transformed.cpos = cpos_rtable[t][cube.cpos]; - -/* - printf("%d\n", coud_source[t]); - int ccc[8]; - int_to_sum_zero_array(cube.cofb, 3, 8, ccc); - for (int i = 0; i < 8; i++) - printf("%d ", ccc[i]); - printf("\n"); - */ - - return transformed; -} diff --git a/old/2021-02-28-transformcube-works/src/transformations.h b/old/2021-02-28-transformcube-works/src/transformations.h @@ -1,34 +0,0 @@ -#ifndef TRANSFORMATIONS_H -#define TRANSFORMATIONS_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include "cube.h" -#include "moves.h" -#include "utils.h" - -#define NROTATIONS (mirror+1) - -/* Letters indicate top and front centers - * Mirror is wrt rl - * Lowercase letter to distinguish from pieces */ - -typedef enum { - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - mirror, -} Transformation; - -void print_transformation(Transformation t); - -Cube transform_cube(Transformation t, Cube cube); -void transform_alg(Transformation t, NissMove *alg); /* Applied in-place */ - -void init_transformations(bool read, bool write); - -#endif diff --git a/old/2021-02-28-transformcube-works/src/utils.c b/old/2021-02-28-transformcube-works/src/utils.c @@ -1,197 +0,0 @@ -#include "utils.h" - -void swap(int *a, int *b) { - int aux = *a; - *a = *b; - *b = aux; -} - -void intarrcopy(int *src, int *dst, int n) { - for (int i = 0; i < n; i++) - dst[i] = src[i]; -} - -int sum(int *a, int n) { - int ret = 0; - for (int i = 0; i < n; i++) - ret += a[i]; - return ret; -} - -bool is_perm(int *a, int n) { - int aux[n]; for (int i = 0; i < n; i++) aux[i] = 0; - for (int i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - for (int i = 0; i < n; i++) - if (!aux[i]) - return false; - return true; -} - -bool is_subset(int *a, int n, int k) { - int sum = 0; - for (int i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - return sum == k; -} - -int powint(int a, int b) { - return 0; - if (b == 0 || a == 1) - return 1; - if (a == 0) - return 0; - if (b < 0) - return 0; /* Immediate truncate (integer part is 0) */ - if (b % 2) { - return a * powint(a, b-1); - } else { - int x = powint(a, b/2); - return x*x; - } -} - -int factorial(int n) { - if (n < 0) - return 0; - int ret = 1; - for (int i = 1; i <= n; i++) - ret *= i; - return ret; -} - -int binomial(int n, int k) { - if (n < 0 || k < 0 || k > n) - return 0; - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -void int_to_digit_array(int a, int b, int n, int *r) { - if (b <= 1) - for (int i = 0; i < n; i++) - r[i] = 0; - else - for (int i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -int digit_array_to_int(int *a, int n, int b) { - int ret = 0, p = 1; - for (int i = 0; i < n; i++, p *= b) - ret += a[i] * p; - return ret; -} - -int perm_to_index(int *a, int n) { - if (!is_perm(a, n)) - return factorial(n); /* Error */ - int ret = 0; - for (int i = 0; i < n; i++) { - int c = 0; - for (int j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - return ret; -} - -void index_to_perm(int p, int n, int *r) { - if (p < 0 || p >= factorial(n)) /* Error */ - for (int i = 0; i < n; i++) - r[i] = -1; - int a[n]; for (int j = 0; j < n; j++) a[j] = 0; /* picked elements */ - for (int i = 0; i < n; i++) { - int c = 0, j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } -} - -int perm_sign(int *a, int n) { - if (!is_perm(a,n)) - return false; - int ret = 0; - for (int i = 0; i < n; i++) - for (int j = i+1; j < n; j++) - ret += (a[i]>a[j]) ? 1 : 0; - return ret % 2; -} - -int subset_to_index(int *a, int n, int k) { - /* TODO: better checks */ - if (!is_subset(a, n, k)) - return binomial(n, k); /* Error */ - int ret = 0; - for (int i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - /*ret += factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ - ret += binomial(n-i-1, k); - k--; - } - } - return ret; -} - -void index_to_subset(int s, int n, int k, int *r) { - if (s < 0 || s >= binomial(n, k)) { /* Error */ - for (int i = 0; i < n; i++) - r[i] = -1; - return; - } - for (int i = 0; i < n; i++) { - if (k == n-i) { - for (int j = i; j < n; j++) - r[j] = 1; - return; - } - if (k == 0) { - for (int j = i; j < n; j++) - r[j] = 0; - return; - } - /*int v = factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ - int v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -void int_to_sum_zero_array(int x, int b, int n, int *a) { - if (b <= 1) { - for (int i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - int s = 0; - for (int i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -void apply_permutation(int *perm, int *set, int n) { - if (!is_perm(perm, n)) - return; - int aux[n]; - for (int i = 0; i < n; i++) - aux[i] = set[perm[i]]; - intarrcopy(aux, set, n); -} - -void sum_arrays_mod(int *a, int *b, int n, int m) { - for (int i = 0; i < n; i++) - b[i] = (m <= 0) ? 0 : (a[i] + b[i]) % m; -} diff --git a/old/2021-02-28-transformcube-works/src/utils.h b/old/2021-02-28-transformcube-works/src/utils.h @@ -1,70 +0,0 @@ -/* General utility functions */ - -#ifndef UTILS_H -#define UTILS_H - -#include <stdbool.h> - -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -/* Some useful constants */ -#define pow2to11 2048 -#define pow2to12 4096 -#define pow3to7 2187 -#define pow3to8 6561 -#define pow12to4 20736 -#define factorial4 24 -#define factorial6 720 -#define factorial8 40320 -#define factorial12 479001600 -#define binom12on4 495 -#define binom8on4 70 - -/* Generic utility functions */ -void swap(int *a, int *b); -void intarrcopy(int *src, int *dst, int n); -int sum(int *a, int n); -bool is_perm(int *a, int n); -bool is_perm(int *a, int n); - - -/* Standard mathematical functions */ -int powint(int a, int b); -int factorial(int n); -int binomial(int n, int k); - -/* Converts the integer a to its representation in base b (first n digits - * only) and saves the result in r. */ -void int_to_digit_array(int a, int b, int n, int *r); -int digit_array_to_int(int *a, int n, int b); - -/* Converts the first n-1 digits of a number to an array a of digits in base b; - * then adds one element to the array, so that the sum of the elements of a is - * zero modulo b. - * This is used for determing the edge orientation from an 11-bits integer or - * the corner orientation from a 7-trits integer. */ -void int_to_sum_zero_array(int x, int b, int n, int *a); - -/* Converts a permutation on [0..(n-1)] into the integer i which is the index - * of the permutation in the sorted list of all n! such permutations. */ -int perm_to_index(int *a, int n); -void index_to_perm(int p, int n, int *r); - -/* Determine the sign of a permutation */ -int perm_sign(int a[], int n); - -/* Converts a k-element subset of a set from an array of n elements, of which k - * are 1 and n-k are 0, to its index in the sorted list of all such subsets. */ -int subset_to_index(int *a, int n, int k); -void index_to_subset(int s, int n, int k, int *r); - -int ordered_subset_to_index(int *a, int n, int k); -void index_to_ordered_subset(int s, int n, int k, int *r); - -void apply_permutation(int *perm, int *set, int n); - -/* b[i] = (a[i]+b[i])%m for i=1,...,n */ -void sum_arrays_mod(int *a, int *b, int n, int m); - -#endif diff --git a/old/2021-05-26-before-restyle/cube.c b/old/2021-05-26-before-restyle/cube.c @@ -1,293 +0,0 @@ -#include "cube.h" - -typedef struct { - int ep[12],eofb[12],eorl[12],eoud[12],cp[8],coud[8],corl[8],cofb[8],cpos[6]; -} CubeArrayAllocated; - -void allocate_cubearray(CubeArray *arr, CubeArrayAllocated *all); - -char edge_string[12][5] = - { "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" }; -char corner_string[8][5] = { "UFR","UFL","UBL","UBR","DFR","DFL","DBL","DBR" }; -char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; - -int epe_solved[4] = {FR, FL, BL, BR}; -int eps_solved[4] = {UL, UR, DL, DR}; -int epm_solved[4] = {UF, UB, DF, DB}; - -PieceFilter pf_all = {true,true,true,true,true,true,true,true,true,true,true}, - pf_cpos = { .cpos = true }, pf_cp = { .cp = true }, - pf_ep = { .epose = true, .eposs = true, .eposm = true }, - pf_e = {.epose=true}, pf_s={.eposs=true}, pf_m={.eposm=true}, - pf_eo = { .eofb = true, .eorl = true, .eoud = true }, - pf_co = { .coud = true, .cofb = true, .corl = true }; - -void allocate_cubearray(CubeArray *arr, CubeArrayAllocated *all) { - arr->ep = all->ep; - arr->eofb = all->eofb; - arr->eorl = all->eorl; - arr->eoud = all->eoud; - arr->cp = all->cp; - arr->coud = all->coud; - arr->corl = all->corl; - arr->cofb = all->cofb; - arr->cpos = all->cpos; -} - -void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) { - /* ep is the hardest */ - if (f.epose || f.eposs || f.eposm) - for (int i = 0; i < 12; i++) arr->ep[i] = -1; - if (f.epose) { - int epe[4], epose[12]; - index_to_perm(cube.epose % factorial(4), 4, epe); - index_to_subset(cube.epose / factorial(4), 12, 4, epose); - for (int i = 0, ie = 0; i < 12; i++) - if (epose[i]) arr->ep[i] = epe_solved[epe[ie++]]; - } - if (f.eposs) { - int eps[4], eposs[12]; - index_to_perm(cube.eposs % factorial(4), 4, eps); - index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); - for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); - for (int i = 0, is = 0; i < 12; i++) - if (eposs[i]) arr->ep[i] = eps_solved[eps[is++]]; - } - if (f.eposm) { - int epm[4], eposm[12]; - index_to_perm(cube.eposm % factorial(4), 4, epm); - index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); - for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); - for (int i = 0, im = 0; i < 12; i++) - if (eposm[i]) arr->ep[i] = epm_solved[epm[im++]]; - } - - /* All the others */ - if (f.eofb) int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) index_to_perm( cube.cp, 8, arr->cp); - if (f.coud) int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) index_to_perm( cube.cpos, 6, arr->cpos); -} - -Cube arrays_to_cube(CubeArray arr, PieceFilter f) { - Cube ret = {0}; - - /* Again, ep is the hardest part */ - if (f.epose) { - int epe[4], epose[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, ie = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == epe_solved[j]) - { epe[ie++] = j; epose[i] = 1; } - ret.epose = factorial(4)*subset_to_index(epose,12,4)+perm_to_index(epe,4); - } - if (f.eposs) { - int eps[4], eposs[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, is = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == eps_solved[j]) - { eps[is++] = j; eposs[i] = 1; } - for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); - ret.eposs = factorial(4)*subset_to_index(eposs,12,4)+perm_to_index(eps,4); - } - if (f.eposm) { - int epm[4], eposm[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; - for (int i = 0, im = 0; i < 12; i++) - for (int j = 0; j < 4; j++) - if (arr.ep[i] == epm_solved[j]) - { epm[im++] = j; eposm[i] = 1; } - for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); - ret.eposm = factorial(4)*subset_to_index(eposm,12,4)+perm_to_index(epm,4); - } - if (f.eofb) ret.eofb = digit_array_to_int(arr.eofb, 11, 2); - if (f.eorl) ret.eorl = digit_array_to_int(arr.eorl, 11, 2); - if (f.eoud) ret.eoud = digit_array_to_int(arr.eoud, 11, 2); - if (f.cp) ret.cp = perm_to_index( arr.cp, 8 ); - if (f.coud) ret.coud = digit_array_to_int(arr.coud, 7, 3); - if (f.corl) ret.corl = digit_array_to_int(arr.corl, 7, 3); - if (f.cofb) ret.cofb = digit_array_to_int(arr.cofb, 7, 3); - if (f.cpos) ret.cpos = perm_to_index( arr.cpos, 6 ); - - return ret; -} - -int piece_orientation(Cube cube, int piece, char *orientation) { - int arr[12], n, b; - uint16_t x; - if (!strcmp(orientation, "eofb")) { x = cube.eofb; n = 12; b = 2; } else - if (!strcmp(orientation, "eorl")) { x = cube.eorl; n = 12; b = 2; } else - if (!strcmp(orientation, "eoud")) { x = cube.eoud; n = 12; b = 2; } else - if (!strcmp(orientation, "coud")) { x = cube.coud; n = 8; b = 3; } else - if (!strcmp(orientation, "corl")) { x = cube.corl; n = 8; b = 3; } else - if (!strcmp(orientation, "cofb")) { x = cube.cofb; n = 8; b = 3; } - else return -1; - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - return -1; -} - -Center center_at(Cube cube, Center c) { - static CubeArrayAllocated all = {0}; - CubeArray arr = {0}; - allocate_cubearray(&arr, &all); - cube_to_arrays(cube, &arr, pf_cpos); - return arr.cpos[c]; -} - -Edge edge_at(Cube cube, Edge e) { - static CubeArrayAllocated all = {0}; - CubeArray arr = {0}; - allocate_cubearray(&arr, &all); - cube_to_arrays(cube, &arr, pf_ep); - return arr.ep[e]; -} - -Corner corner_at(Cube cube, Corner c) { - static CubeArrayAllocated all = {0}; - CubeArray arr = {0}; - allocate_cubearray(&arr, &all); - cube_to_arrays(cube, &arr, pf_cp); - return arr.cp[c]; -} - -bool block_solved(Cube cube, Block block) { - static CubeArrayAllocated all = {0}; - CubeArray arr = {0}; - allocate_cubearray(&arr, &all); - cube_to_arrays(cube, &arr, pf_all); - - bool ret = true; - - for (int i = 0; i < 12; i++) - ret = ret && !(block.edge[i] && (arr.ep[i] != i || arr.eofb[i])); - for (int i = 0; i < 8; i++) - ret = ret && !(block.corner[i] && (arr.cp[i] != i || arr.coud[i])); - for (int i = 0; i < 6; i++) - ret = ret && !(block.center[i] && arr.cpos[i] != i); - - return ret; -} - -bool equal(Cube c1, Cube c2) { - return c1.eofb == c2.eofb && c1.epose == c2.epose && - c1.eposs == c2.eposs && c1.eposm == c2.eposm && - c1.coud == c2.coud && c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -bool is_solved(Cube cube) { - /* TODO: might return true if cube is not solvable but looks solved form one - of the incompatible interpretations (e.g. eofb and ep solved, but - eorl not solve) */ - return !cube.eofb && !cube.coud && !cube.cp && - !cube.epose && !cube.eposs && !cube.eposm && !cube.cpos; -} - -void print_cube(Cube cube) { - static CubeArrayAllocated all = {0}; - CubeArray arrx = {0}; - allocate_cubearray(&arrx, &all); - cube_to_arrays(cube, &arrx, pf_all); - - for (int i = 0; i < 12; i++) printf(" %s ", edge_string[arrx.ep[i]]); - printf("\n"); - for (int i = 0; i < 12; i++) printf(" %c ", arrx.eofb[i] + '0'); - printf("\n"); - for (int i = 0; i < 8; i++) printf("%s ", corner_string[arrx.cp[i]]); - printf("\n"); - for (int i = 0; i < 8; i++) printf(" %c ", arrx.coud[i] + '0'); - printf("\n"); - for (int i = 0; i < 6; i++) printf(" %s ", center_string[arrx.cpos[i]]); - printf("\n"); -} - -Cube admissible_ep(Cube cube, PieceFilter f) { - static CubeArrayAllocated all = {0}; - CubeArray arrx = {0}; - allocate_cubearray(&arrx, &all); - cube_to_arrays(cube, &arrx, f); - - bool used[12] = {0}; - for (int i = 0; i < 12; i++) - if (arrx.ep[i] != -1) - used[arrx.ep[i]] = true; - for (int i = 0, j = 0; i < 12; i++) { - while (j < 11 && used[j]) j++; - if (arrx.ep[i] == -1) - arrx.ep[i] = j++; - } - - return arrays_to_cube(arrx, pf_ep); -} - -Cube inverse_cube(Cube cube) { - static CubeArrayAllocated all = {0}, invall = {0}; - CubeArray arrx = {0}, invx = {0}; - allocate_cubearray(&arrx, &all); - allocate_cubearray(&invx, &invall); - - cube_to_arrays(cube, &arrx, pf_all); - - for (int i = 0; i < 12; i++) { - invx.ep[arrx.ep[i]] = i; - invx.eofb[arrx.ep[i]] = arrx.eofb[i]; - invx.eorl[arrx.ep[i]] = arrx.eorl[i]; - invx.eoud[arrx.ep[i]] = arrx.eoud[i]; - } - for (int i = 0; i < 8; i++) { - invx.cp[arrx.cp[i]] = i; - invx.coud[arrx.cp[i]] = (3 - arrx.coud[i])%3; - invx.corl[arrx.cp[i]] = (3 - arrx.corl[i])%3; - invx.cofb[arrx.cp[i]] = (3 - arrx.cofb[i])%3; - } - for (int i = 0; i < 6; i++) - invx.cpos[arrx.cpos[i]] = i; - - return arrays_to_cube(invx, pf_all); -} - -Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter f) { - static CubeArrayAllocated all = {0}; - CubeArray arrx = {0}; - allocate_cubearray(&arrx, &all); - - cube_to_arrays(c, &arrx, f); - - if (f.epose || f.eposs || f.eposm) - apply_permutation( arr.ep, arrx.ep, 12 ); - if (f.eofb) { apply_permutation( arr.ep, arrx.eofb, 12 ); - sum_arrays_mod( arr.eofb, arrx.eofb, 12, 2 ); } - if (f.eorl) { apply_permutation( arr.ep, arrx.eorl, 12 ); - sum_arrays_mod( arr.eorl, arrx.eorl, 12, 2 ); } - if (f.eoud) { apply_permutation( arr.ep, arrx.eoud, 12 ); - sum_arrays_mod( arr.eoud, arrx.eoud, 12, 2 ); } - if (f.cp) apply_permutation( arr.cp, arrx.cp, 8 ); - if (f.coud) { apply_permutation( arr.cp, arrx.coud, 8 ); - sum_arrays_mod( arr.coud, arrx.coud, 8, 3 ); } - if (f.corl) { apply_permutation( arr.cp, arrx.corl, 8 ); - sum_arrays_mod( arr.corl, arrx.corl, 8, 3 ); } - if (f.cofb) { apply_permutation( arr.cp, arrx.cofb, 8 ); - sum_arrays_mod( arr.cofb, arrx.cofb, 8, 3 ); } - if (f.cpos) apply_permutation( arr.cpos, arrx.cpos, 6 ); - - return arrays_to_cube(arrx, f); -} - -Cube compose_filtered(Cube c2, Cube c1, PieceFilter f) { - static CubeArrayAllocated all = {0}; - CubeArray arrx = {0}; - allocate_cubearray(&arrx, &all); - - cube_to_arrays(c2, &arrx, f); - return move_via_arrays(arrx, c1, f); -} - -Cube compose(Cube c2, Cube c1) { - return compose_filtered(c2, c1, pf_all); -} diff --git a/old/2021-05-26-before-restyle/cube.h b/old/2021-05-26-before-restyle/cube.h @@ -1,65 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <string.h> -#include "utils.h" - -typedef enum {U_center,D_center,R_center,L_center,F_center,B_center} Center; -typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; -typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; - -typedef struct { - uint16_t eofb, eorl, eoud, coud, cofb, corl, - epose, eposs, eposm, cp, cpos; -} Cube; - -typedef struct { - bool edge[12], corner[8], center[6]; -} Block; - -typedef struct { - bool epose, eposs, eposm, eofb, eorl, eoud, cp, coud, cofb, corl, cpos; -} PieceFilter; - -typedef struct { - int *ep, *eofb, *eorl, *eoud, *cp, *coud, *corl, *cofb, *cpos; -} CubeArray; - -extern PieceFilter pf_all, pf_cpos, pf_ep, pf_cp, - pf_e, pf_s, pf_m, pf_eo, pf_co; - -void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -Cube arrays_to_cube(CubeArray arr, PieceFilter f); - -/* piece can be edge or corner and orientation is any of the following: - "eofb", "eorl", "eoud", "coud", "corl", "cofb" - Return either 0 (oriented) or 1 for edges and 0, 1 or 2 for corners */ -int piece_orientation(Cube cube, int piece, char *orientation); -Center center_at(Cube cube, Center c); -Edge edge_at(Cube cube, Edge e); -Corner corner_at(Cube cube, Corner c); -bool block_solved(Cube cube, Block); -/* Aggiungi funzioni per "queries" sul cubo: se pezzo è orientato rispetto ad - un certo asse, se il pezzo è risolto... */ -/* Would be nice: a funciton block_solved(Cube c, Block b), where Block is - something like struct {bool centers[6], edges[12], corners[8]} - (The advantage over checking pieces one by one is that I can convert - to cubearray only once and for all) */ -/* Altro TODO, ma forse non ne vale la pena: pre-calcolare tutti i possibili - valori per questi, e salvare i risultati in array (facile per cp e cpos, - mentre per ep bisogna anche cercare quale tra epose, eposs e eposm contiene - il valore giusto) */ - -bool equal(Cube c1, Cube c2); -bool is_solved(Cube cube); -void print_cube(Cube cube); -Cube admissible_ep(Cube cube, PieceFilter f); /* Returns admissible ep */ -Cube inverse_cube(Cube cube); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter pf); - -#endif diff --git a/old/2021-05-26-before-restyle/main.c b/old/2021-05-26-before-restyle/main.c @@ -1,24 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "moves.h" -#include "solve.h" -#include "transformations.h" - -int main() { - init_ttables(true, true); - init_aux_tables(); - init_transformations(true, true); - - - char moves[100] = "R' D2 F2 U2 R F2 R D2 L' R2 D2 F D' L' U' B R' D' U R' B"; - NissMove alg[100]; - read_moves(moves, alg, 100); - Cube cube = apply_alg(alg, (Cube){0}); - print_cube(transform_cube(rd, cube)); - - transform_alg(rd, alg); - print_alg(alg); - - - return 0; -} diff --git a/old/2021-05-26-before-restyle/moves.c b/old/2021-05-26-before-restyle/moves.c @@ -1,412 +0,0 @@ -#include "moves.h" - -Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -/* void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front); */ -bool read_ttables_file(); -bool write_ttables_file(); - -/* Transition tables */ -uint16_t epose_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; -uint16_t eofb_ttable[NMOVES][pow2to11]; -uint16_t eorl_ttable[NMOVES][pow2to11]; -uint16_t eoud_ttable[NMOVES][pow2to11]; -uint16_t cp_ttable[NMOVES][factorial8]; -uint16_t coud_ttable[NMOVES][pow3to7]; -uint16_t cofb_ttable[NMOVES][pow3to7]; -uint16_t corl_ttable[NMOVES][pow3to7]; -uint16_t cpos_ttable[NMOVES][factorial6]; - -bool commute[NMOVES][NMOVES]; -bool possible_next[NMOVES][NMOVES][NMOVES]; -Move inverse[NMOVES]; -NissMove rotation_algs[24][3] = { - { { .m = NULLMOVE }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = z2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y }, { .m = z2 }, { .m = NULLMOVE } }, - { { .m = x2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y3 }, { .m = z2 }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = y }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = y3 }, { .m = NULLMOVE } }, - { { .m = z }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = z }, { .m = y3 }, { .m = NULLMOVE } }, - { { .m = z }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = z }, { .m = y }, { .m = NULLMOVE } }, - { { .m = x }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = x }, { .m = y }, { .m = NULLMOVE } }, - { { .m = x }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = x }, { .m = y3 }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = y }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = y3 }, { .m = NULLMOVE } }, -}; - -char move_string[NMOVES][5] = - { "-", - "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", - "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", - "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", - "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", - "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", - "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'" }; - -/* For each type of pieces only the effects of U, x and y are described */ -int edge_cycle[NMOVES][12] = - { [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, - [x] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, - [y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL} }; -int eofb_flipped[NMOVES][12] = - { [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; -int eorl_flipped[NMOVES][12] = - { [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; -int eoud_flipped[NMOVES][12] = - { [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, - [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; -int corner_cycle[NMOVES][8] = - { [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, - [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, - [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} }; -int coud_flipped[NMOVES][8] = - { [x] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2} }; -int corl_flipped[NMOVES][8] = - { [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, - [y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1} }; -int cofb_flipped[NMOVES][8] = - { [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, - [x] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=1,[UFL]=2,[DBL]=2,[DFL]=1}, - [y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2} }; -int center_cycle[NMOVES][6] = - { [x] = {F_center, B_center, R_center, L_center, D_center, U_center}, - [y] = {U_center, D_center, B_center, F_center, R_center, L_center} }; - -/* Each move is reduced to a combination of U, x and y using this table */ -Move equiv_moves[NMOVES][14] = { - [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, - [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, - [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, - [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, - [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, - [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, - [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, - - [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, - [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, - [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, - [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, - [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, - [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, - [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, - [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, - [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, - [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - - [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, - [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, - [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, - [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, - [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, - [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, - [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, - [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, - [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, - - [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, -}; - -/* Movesets */ -bool standard_moveset[NMOVES] = { - [U] = true, [U2] = true, [U3] = true, [D] = true, [D2] = true, [D3] = true, - [R] = true, [R2] = true, [R3] = true, [L] = true, [L2] = true, [L3] = true, - [F] = true, [F2] = true, [F3] = true, [B] = true, [B2] = true, [B3] = true, -}; - -bool is_solved_up_to_reorient(Cube cube) { - for (int i = 0; i < 25; i++) - if (is_solved(apply_alg(rotation_algs[i], cube))) - return true; - return false; -} - -Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f) { - return move_via_arrays((CubeArray) - { edge_cycle[m], eofb_flipped[m], eorl_flipped[m], eoud_flipped[m], - corner_cycle[m], coud_flipped[m], corl_flipped[m], cofb_flipped[m], - center_cycle[m] }, cube, f); -} - -int len(NissMove *alg) { - int i; - for (i = 0; alg[i].m != NULLMOVE; i++); - return i; -} - -int copy_alg(NissMove *src, NissMove *dest) { - int i; - for (i = 0; src[i].m != NULLMOVE; i++) - dest[i] = src[i]; - dest[i].m = NULLMOVE; - return i; -} - -int invert_alg(NissMove *src, NissMove *dest) { - int n = len(src); - for (int i = 0; i < n; i++) - dest[n-i-1] = (NissMove){.m=inverse[src[i].m], .inverse=src[i].inverse}; - dest[n].m = NULLMOVE; - return n; -} - -int concat(NissMove *src1, NissMove *src2, NissMove *dest) { - int n1 = len(src1), n2 = len(src2); - copy_alg(src1, dest); - copy_alg(src2, dest+n1); - return n1+n2; -} - -/* TODO: all strings start with space?? */ -void print_alg(NissMove *alg) { - bool niss = false; - for (int i = 0; alg[i].m != NULLMOVE; i++) { - char *fill = !niss && alg[i].inverse ? " (" : - (niss && !alg[i].inverse ? ") " : " "); - printf("%s%s", fill, move_string[alg[i].m]); - niss = alg[i].inverse; - } - printf("%s\n", niss ? ")" : ""); -} - -int read_moves(char *str, NissMove *alg, int n) { - bool niss = false; - int c = 0; - - for (int i = 0; str[i] && c < n; i++) { - if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') - continue; - - if (str[i] == '(' || str[i] == ')') { - if ((niss && str[i] == '(') || (!niss && str[i] == ')')) - return -1; - niss = !niss; - continue; - } - - alg[c].inverse = niss; alg[c].m = NULLMOVE; - for (Move j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - alg[c].m = j; - if (alg[c].m <= B && str[i+1]=='w') { alg[c].m += Uw - U; i++; } - if (str[i+1]=='2') { alg[c].m += 1; i++; } - else if (str[i+1]=='\'' || str[i+1]=='3') { alg[c].m += 2; i++; } - c++; - break; - } - } - } - - alg[c].m = NULLMOVE; - return c; -} - -/* TODO: rewrite cleanup(). Idea: - 1. split alg in normal + inverse part, rewriting each with equiv_moves - 2. shift rotations to the end while transforming all moves in between - ARGH! this uses transformation! One more reason to merge everything in - one file. - 3. cancellations -*/ - -bool read_ttables_file() { - FILE *ttf; - long unsigned int me[11] = { factorial12/factorial8, factorial12/factorial8, - factorial12/factorial8, pow2to11, pow2to11, pow2to11, - factorial8, pow3to7, pow3to7, pow3to7, factorial6 }; - if ((ttf = fopen("ttables", "rb")) != NULL) { - bool r = true; - for (int m = 0; m < NMOVES; m++) { - r = r && fread(epose_ttable[m], sizeof(uint16_t), me[0], ttf) == me[0]; - r = r && fread(eposs_ttable[m], sizeof(uint16_t), me[1], ttf) == me[1]; - r = r && fread(eposm_ttable[m], sizeof(uint16_t), me[2], ttf) == me[2]; - r = r && fread(eofb_ttable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - r = r && fread(eorl_ttable[m], sizeof(uint16_t), me[4], ttf) == me[4]; - r = r && fread(eoud_ttable[m], sizeof(uint16_t), me[5], ttf) == me[5]; - r = r && fread(cp_ttable[m], sizeof(uint16_t), me[6], ttf) == me[6]; - r = r && fread(coud_ttable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - r = r && fread(corl_ttable[m], sizeof(uint16_t), me[8], ttf) == me[8]; - r = r && fread(cofb_ttable[m], sizeof(uint16_t), me[9], ttf) == me[9]; - r = r && fread(cpos_ttable[m], sizeof(uint16_t), me[10], ttf) == me[10]; - } - fclose(ttf); - return r; - } else return false; -} - -bool write_ttables_file() { - FILE *ttf; - long unsigned int me[11] = { factorial12/factorial8, factorial12/factorial8, - factorial12/factorial8, pow2to11, pow2to11, pow2to11, - factorial8, pow3to7, pow3to7, pow3to7, factorial6 }; - if ((ttf = fopen("ttables", "wb")) != NULL) { - bool r = true; - for (int m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_ttable[m], sizeof(uint16_t), me[0], ttf) == me[0]; - r = r && fwrite(eposs_ttable[m], sizeof(uint16_t), me[1], ttf) == me[1]; - r = r && fwrite(eposm_ttable[m], sizeof(uint16_t), me[2], ttf) == me[2]; - r = r && fwrite(eofb_ttable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - r = r && fwrite(eorl_ttable[m], sizeof(uint16_t), me[4], ttf) == me[4]; - r = r && fwrite(eoud_ttable[m], sizeof(uint16_t), me[5], ttf) == me[5]; - r = r && fwrite(cp_ttable[m], sizeof(uint16_t), me[6], ttf) == me[6]; - r = r && fwrite(coud_ttable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - r = r && fwrite(corl_ttable[m], sizeof(uint16_t), me[8], ttf) == me[8]; - r = r && fwrite(cofb_ttable[m], sizeof(uint16_t), me[9], ttf) == me[9]; - r = r && fwrite(cpos_ttable[m], sizeof(uint16_t), me[10],ttf) == me[10]; - } - fclose(ttf); - return r; - } else return false; -} - -void init_ttables(bool read, bool write) { - /* Generate all move cycles and flips; I do this regardless */ - for (int i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - Cube c = {0}; - for (int j = 0; equiv_moves[i][j]; j++) - c = apply_move_cubearray(equiv_moves[i][j], c, pf_all); - - CubeArray arrs = { - edge_cycle[i], eofb_flipped[i], eorl_flipped[i], eoud_flipped[i], - corner_cycle[i], coud_flipped[i], corl_flipped[i], cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read) - if (read_ttables_file()) - return; - - /* Initialize transition tables */ - for (int m = 0; m < NMOVES; m++) { - for (uint16_t i = 0; i < factorial12/factorial8; i++) { - epose_ttable[m][i] = apply_move_cubearray(m,(Cube){.epose=i},pf_e).epose; - eposs_ttable[m][i] = apply_move_cubearray(m,(Cube){.eposs=i},pf_s).eposs; - eposm_ttable[m][i] = apply_move_cubearray(m,(Cube){.eposm=i},pf_m).eposm; - } - for (uint16_t i = 0; i < pow2to11; i++ ) { - eofb_ttable[m][i] = apply_move_cubearray(m,(Cube){.eofb=i},pf_eo).eofb; - eorl_ttable[m][i] = apply_move_cubearray(m,(Cube){.eorl=i},pf_eo).eorl; - eoud_ttable[m][i] = apply_move_cubearray(m,(Cube){.eoud=i},pf_eo).eoud; - } - for (uint16_t i = 0; i < pow3to7; i++) { - coud_ttable[m][i] = apply_move_cubearray(m,(Cube){.coud=i},pf_co).coud; - corl_ttable[m][i] = apply_move_cubearray(m,(Cube){.corl=i},pf_co).corl; - cofb_ttable[m][i] = apply_move_cubearray(m,(Cube){.cofb=i},pf_co).cofb; - } - for (uint16_t i = 0; i < factorial8; i++) - cp_ttable[m][i] = apply_move_cubearray(m,(Cube){.cp=i},pf_cp).cp; - for (uint16_t i = 0; i < factorial6; i++) - cpos_ttable[m][i] = apply_move_cubearray(m,(Cube){.cpos=i},pf_cpos).cpos; - } - - if (write) - if (!write_ttables_file()) - printf("Error in writing ttables: file not writable\n"); -} - -Cube move_cube(Move m, Cube cube) { - Cube moved = {0}; - - moved.epose = epose_ttable[m][cube.epose]; - moved.eposs = eposs_ttable[m][cube.eposs]; - moved.eposm = eposm_ttable[m][cube.eposm]; - moved.eofb = eofb_ttable[m][cube.eofb]; - moved.eorl = eorl_ttable[m][cube.eorl]; - moved.eoud = eoud_ttable[m][cube.eoud]; - moved.coud = coud_ttable[m][cube.coud]; - moved.cofb = cofb_ttable[m][cube.cofb]; - moved.corl = corl_ttable[m][cube.corl]; - moved.cp = cp_ttable[m][cube.cp]; - moved.cpos = cpos_ttable[m][cube.cpos]; - - return moved; -} - -Cube apply_alg_filtered(NissMove *alg, Cube cube, PieceFilter f) { - Cube ret = {0}; - for (int i = 0; alg[i].m != NULLMOVE; i++) - if (alg[i].inverse) - ret = move_cube(alg[i].m, ret); - - ret = compose_filtered(cube, inverse_cube(ret), f); - - for (int i = 0; alg[i].m != NULLMOVE; i++) - if (!alg[i].inverse) - ret = move_cube(alg[i].m, ret); - return ret; -} - -Cube apply_alg(NissMove *alg, Cube cube) { - return apply_alg_filtered(alg, cube, pf_all); -} - -void init_aux_tables() { - /* Commute */ - for (int i = 0; i < NMOVES; i++) - for (int j = 0; j < NMOVES; j++) - commute[i][j] = equal(move_cube(i, move_cube(j, (Cube){0})), - move_cube(j, move_cube(i, (Cube){0}))); - - /* Possible next (if the sequence i j k is valid) */ - for (int i = 0; i < NMOVES; i++) - for (int j = 0; j < NMOVES; j++) - for (int k = 0; k < NMOVES; k++) - possible_next[i][j][k] = - (j == 0) || - (j != 0 && (j-(j-1)%3) != (k-(k-1)%3) && - !(i != 0 && commute[i][j] && (i-(i-1)%3) == (k-(k-1)%3))); - - /* Inverse */ - for (int i = 0; i < NMOVES; i++) - inverse[i] = i == NULLMOVE ? NULLMOVE : i + 2 - 2*((i-1)%3); - -} - diff --git a/old/2021-05-26-before-restyle/moves.h b/old/2021-05-26-before-restyle/moves.h @@ -1,51 +0,0 @@ -#ifndef MOVES_H -#define MOVES_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include "cube.h" -#include "utils.h" - -#define NMOVES (z3+1) - -typedef enum { - NULLMOVE, - U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, - Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, S, S2, S3, E, E2, E3, - x, x2, x3, y, y2, y3, z, z2, z3, -} Move; - -/* An alg is an array of "NissMoves", which can be on normal or on inverse. */ -typedef struct { bool inverse; Move m; } NissMove; - -/* Movesets */ -extern bool standard_moveset[NMOVES]; - -extern bool commute[NMOVES][NMOVES]; -extern bool possible_next[NMOVES][NMOVES][NMOVES]; -extern Move inverse[NMOVES]; -extern NissMove rotation_algs[24][3]; /* Same order as transformations */ - -int len(NissMove *alg); -int copy_alg(NissMove *src, NissMove *dest); /*return number of moves copied */ -int invert_alg(NissMove *src, NissMove *dest); -int concat(NissMove *src1, NissMove *src2, NissMove *dest); -void print_alg(NissMove *alg); -int read_moves(char *str, NissMove *alg, int n); /* reads at most n moves */ -void cleanup(NissMove *src, int n); /* rewrites using basic moves, at most n */ - -bool is_solved_up_to_reorient(Cube cube); -Cube move_cube(Move m, Cube cube); -Cube apply_alg(NissMove *alg, Cube cube); -Cube apply_alg_filtered(NissMove *alg, Cube cube, PieceFilter f); - -/* Merge the following two? - always in this order */ -void init_ttables(bool read, bool write); -void init_aux_tables(); - - -#endif diff --git a/old/2021-05-26-before-restyle/solve.c b/old/2021-05-26-before-restyle/solve.c @@ -1,180 +0,0 @@ -#include "solve.h" - -/* Data for creating a pruning table: - - compressed: if set to true, each entry occupies only 4 bits, but values - larger than 15 cannot be stored. - - available[] is the list of availabel moves, as above. - - *ptable is the actual table to fill. - - n is the number of states (size of ptable). - - index must "linearize" the cube, i.e. return its index in ptable. - - fname is the name of the file where to store the table */ -typedef struct { - bool compressed, *available; - int max_moves; - uint8_t *ptable; - uint64_t n; - uint64_t (*index)(Cube); - char *fname; -} PruneData; - -/* TODO: comment this */ -typedef struct { - bool niss; - int m, d; - uint64_t *n; - Move last1, last2; -} DfsData; - -void solve_dfs(Cube cube, SolveData *sd, DfsData dd); -void init_ptable(PruneData *pd, bool read, bool write); - -/* Search solutions of lenght exactly d */ -void solve_dfs(Cube cube, SolveData *sd, DfsData dd) { - if (*dd.n >= sd->max_solutions || - ((!sd->can_niss || dd.niss) && dd.m + sd->f(cube) > dd.d)) - return; - - (sd->solutions[*dd.n][dd.m]).inverse = dd.niss; - (sd->solutions[*dd.n][dd.m]).m = NULLMOVE; - - if (!sd->f(cube)) { /* Solved */ - if (dd.m == dd.d) { - (*dd.n)++; - if (*dd.n < sd->max_solutions) - copy_alg(sd->solutions[*dd.n-1], sd->solutions[*dd.n]); - } - return; - } - - for (int i = 0; i < NMOVES && sd->sorted_moves[i] != NULLMOVE; i++) { - Move move = sd->sorted_moves[i]; - if (possible_next[dd.last2][dd.last1][move]) { - sd->solutions[*dd.n][dd.m].inverse = dd.niss; - sd->solutions[*dd.n][dd.m].m = move; - DfsData nn = { .niss = dd.niss, .m = dd.m+1, .d = dd.d, .n = dd.n, - .last1 = move, .last2 = dd.last1 }; - solve_dfs(move_cube(move, cube), sd, nn); - } - } - - if (sd->can_niss && !dd.niss && - (!dd.m || (dd.m && sd->f(move_cube(dd.last1, (Cube){0}))))) { - DfsData nn = { .niss = true, .m = dd.m, .d = dd.d, .n = dd.n }; - solve_dfs(inverse_cube(cube), sd, nn); - } -} - -/* Iterative deepening depth-first search: for i running from the minimum - to the maximum number of moves allowed, looks for solutions of length i. */ -int solve(Cube cube, SolveData *sd) { - if (sd->precondition != NULL && !sd->precondition(cube)) - return -1; - - /* If not given, generate sorted list of moves */ - if (sd->sorted_moves[0] == NULLMOVE) { - int a[NMOVES], b[NMOVES], ia = 0, ib = 0; - for (int i = 0; i < NMOVES; i++) { - if (sd->available[i]) { - if (sd->f(move_cube(i, (Cube){0}))) - a[ia++] = i; - else - b[ib++] = i; - } - } - intarrcopy(a, (int *)sd->sorted_moves, ia); - intarrcopy(b, (int *)sd->sorted_moves+ia, ib); - sd->sorted_moves[ia+ib] = NULLMOVE; - } - - sd->max_solutions = min(sd->max_solutions, MAXS); - /*TODO - Cube rotated = apply_alg(sd->pre_rotation, (Cube){0}); - cube = apply_alg(inverse_cube(rotated), compose(cube, rotated)); - */ - - uint64_t ret = 0; - for (int i=sd->min_moves; i<=sd->max_moves&&!(ret&&sd->optimal_only); i++) { - DfsData dd = { .d = i, .n = &ret }; - solve_dfs(cube, sd, dd); - } - - /* TODO: transform solutions with inverse of pre_rotation */ - /* - for (uint64_t i = 0; i < ret; i++) { - if (sd->cleanup) - cleanup(sd->solutions[i], sd->max_moves*3); - }*/ - - return ret; -} - -void prune_dfs(Cube cube, PruneData *pd, DfsData dd) { - uint64_t ind = pd->index(cube); - if ((!ind || pd->ptable[ind]) && pd->ptable[ind] != dd.m) - return; - if (dd.m == dd.d) { - if (ind && !pd->ptable[ind]) { - pd->ptable[ind] = dd.m; - (*dd.n)++; - } - return; - } - - for (int i = 0; i < NMOVES; i++) { - if (dd.m<20) - if (possible_next[dd.last2][dd.last1][i] && pd->available[i]) { - DfsData nn = { .m = dd.m+1, .d = dd.d, .n = dd.n, - .last1 = i, .last2 = dd.last1 }; - prune_dfs(move_cube(i, cube), pd, nn); - } - } -} - -void init_ptable(PruneData *pd, bool read, bool write) { - if (read) { - FILE *ptf; - if ((ptf = fopen(pd->fname, "rb")) != NULL) { - uint64_t r = fread(pd->ptable, sizeof(uint8_t), pd->n, ptf); - fclose(ptf); - if (r == pd->n) return; - } - } - - /* TODO: for now it behaves always as if copressed = false */ - for (uint64_t i = 0; i < pd->n; i++) - pd->ptable[i] = 0; - - uint64_t s = 1; - for (int i = 1; i < pd->max_moves && s < pd->n; i++) { - DfsData dd = { .d = i, .n = &s }; - prune_dfs((Cube){0}, pd, dd); - } - - if (write) { - FILE *ptf; - if ((ptf = fopen(pd->fname, "wb")) != NULL) { - fwrite(pd->ptable, sizeof(uint8_t), pd->n, ptf); - fclose(ptf); - return; - } - } -} - -/* Solving steps (and indexing functions) */ - -uint64_t index_eofb(Cube cube) { return cube.eofb; } -int f_eofb(Cube cube) { - static bool initialized_ptable; - static uint8_t pt_eofb[pow2to11]; - if (!initialized_ptable) { - PruneData pd = { - .compressed = false, .available = standard_moveset, .max_moves = 13, - .ptable = pt_eofb, .n = pow2to11, .index = index_eofb, - .fname = "ptable_eofb" - }; - init_ptable(&pd, false, true); - initialized_ptable = true; - } - return cube.eofb ? pt_eofb[cube.eofb] : 0; -} - diff --git a/old/2021-05-26-before-restyle/solve.h b/old/2021-05-26-before-restyle/solve.h @@ -1,59 +0,0 @@ -#ifndef SOLVE_H -#define SOLVE_H - -#include <stdlib.h> -#include "cube.h" -#include "moves.h" -#include "transformations.h" - -/* Maximum number of moves per solution and of solutions */ -#define MAXM 30 -#define MAXS 999 - -/* Data for solving a step: - - can_niss is true niss can be used, false otherwise. - - optimal_only if true, dynamically updates max_moves so non-optimal - solutions are discarded. - - cleanup determines whether the cleaunup() function should be used on - the found solutions before returning. - - available[m] is true if the move m can be used, false otherwise. - (Rename to moveset[]?) - - min_moves and max_moves are the minimum and maximum number of moves that - can be used. - - max_solution is the maximum number of solutions that can be returned. - - precondition can be used to check wheter the step can actually be applied - to the cube. If it returns false, solve() stops immediately returning -1. - - f must return 0 if and only if the step is solve, otherwise it must return - a lower bound for the number of moves required (without niss). - - sorted_moves[] can be used to specify in which order moves are tried - by the solving algorithm (for example if one wants to always try F' before - F). If sorted_moves[0] == NULLMOVE, the list is generated automatically. - It is advised to list first all the moves that actually influence the - solved state of the step (this is the default choice). This is in order to - avoid cases like B2 F for EO and to NISS only when it makes sense. - - start_moves [Currently unused, REMOVE] - are the moves that will be used as first moves of all - solutions. For example giving R' U' F (F' U R) will generate FMC scrambles - and y (y) will solve the step on another axis. - - pre_rotation are the rotations to apply before the scamble to solve - the step wrt a different orientation - - pre_rotation are the rotations to apply before the scamble to solve - the step wth respect to a different orientation. - TODO: cange name - - solutions[][] is the array where to store the found solutions. */ -typedef struct { - bool can_niss, optimal_only, cleanup, *available; - int min_moves, max_moves, max_solutions; - int (*f)(Cube); - bool (*precondition)(Cube); - Move sorted_moves[NMOVES]; - Transformation pre_rotation; - NissMove solutions[MAXS][MAXM]; -} SolveData; - -int solve(Cube cube, SolveData *data); /* Returns the number of solutions. */ - -/* Steps */ -int f_eofb(Cube cube); - -#endif diff --git a/old/2021-05-26-before-restyle/transformations.c b/old/2021-05-26-before-restyle/transformations.c @@ -1,200 +0,0 @@ -#include "transformations.h" - -int edge_slice(int e); /* Return slice (e=0, s=1, m=2) to which e belongs */ -Cube rotate_via_compose(Transformation r, Cube c, PieceFilter f); -bool read_rtables_file(); -bool write_rtables_file(); - -/* Values mod 3 to determine from which side to take the state to convert */ -int epose_source[NTRANS]; /* 0 = epose, 1 = eposs, 2 = eposm */ -int eposs_source[NTRANS]; -int eposm_source[NTRANS]; -int eofb_source[NTRANS]; /* 0 = eoud, 1 = eorl, 2 = eofb */ -int eorl_source[NTRANS]; -int eoud_source[NTRANS]; -int coud_source[NTRANS]; /* 0 = coud, 1 = corl, 2 = cofb */ -int cofb_source[NTRANS]; -int corl_source[NTRANS]; - -/* Transition tables for rotations (n+1 is mirror) */ -uint16_t epose_rtable[NTRANS][factorial12/factorial8]; -uint16_t eposs_rtable[NTRANS][factorial12/factorial8]; -uint16_t eposm_rtable[NTRANS][factorial12/factorial8]; -uint16_t eo_rtable[NTRANS][pow2to11]; -uint16_t cp_rtable[NTRANS][factorial8]; -uint16_t co_rtable[NTRANS][pow3to7]; -uint16_t cpos_rtable[NTRANS][factorial6]; - -/* Same for moves */ -uint16_t moves_rtable[NTRANS][NMOVES]; - -NissMove rotation_niss[NTRANS][6]; - -int edge_slice(int e) { - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - return 2; -} - -Cube rotate_via_compose(Transformation r, Cube c, PieceFilter f) { - if (r != mirror) { - return apply_alg_filtered(rotation_niss[r], c, f); - } else { - static int zero12[12] = {0,0,0,0,0,0,0,0,0,0,0,0}, - zero8[12] = {0,0,0,0,0,0,0,0}, - mirror_ep[12] = {UF,UR,UB,UL,DF,DR,DB,DL,FL,FR,BR,BL}, - mirror_cp[8] = {UFL, UFR, UBR, UBL, DFL, DFR, DBR, DBL}, - mirror_cpos[6] = - {U_center,D_center,L_center,R_center,F_center,B_center}; - return move_via_arrays((CubeArray){ - .ep = mirror_ep, .eofb = zero12, .eorl = zero12, .eoud = zero12, - .cp = mirror_cp, .coud = zero8, .corl = zero8, .cofb = zero8, - .cpos = mirror_cpos}, c, f); - } -} - -bool read_rtables_file() { - FILE *ttf; - long unsigned int me[12] = { factorial12/factorial8, factorial12/factorial8, - factorial12/factorial8, pow2to11, pow2to11, pow2to11, - factorial8, pow3to7, pow3to7, pow3to7, factorial6, NMOVES }; - if ((ttf = fopen("rtables", "rb")) != NULL) { - bool r = true; - for (int m = 0; m < NTRANS; m++) { - r = r && fread(epose_rtable[m], sizeof(uint16_t), me[0], ttf) == me[0]; - r = r && fread(eposs_rtable[m], sizeof(uint16_t), me[1], ttf) == me[1]; - r = r && fread(eposm_rtable[m], sizeof(uint16_t), me[2], ttf) == me[2]; - r = r && fread(eo_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - r = r && fread(cp_rtable[m], sizeof(uint16_t), me[6], ttf) == me[6]; - r = r && fread(co_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - r = r && fread(cpos_rtable[m], sizeof(uint16_t), me[10], ttf) == me[10]; - r = r && fread(moves_rtable[m], sizeof(uint16_t), me[11], ttf) == me[11]; - } - fclose(ttf); - return r; - } else return false; -} - -bool write_rtables_file() { - FILE *ttf; - long unsigned int me[12] = { factorial12/factorial8, factorial12/factorial8, - factorial12/factorial8, pow2to11, pow2to11, pow2to11, - factorial8, pow3to7, pow3to7, pow3to7, factorial6, NMOVES }; - if ((ttf = fopen("rtables", "wb")) != NULL) { - bool r = true; - for (int m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_rtable[m], sizeof(uint16_t), me[0], ttf) == me[0]; - r = r && fwrite(eposs_rtable[m], sizeof(uint16_t), me[1], ttf) == me[1]; - r = r && fwrite(eposm_rtable[m], sizeof(uint16_t), me[2], ttf) == me[2]; - r = r && fwrite(eo_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; - r = r && fwrite(cp_rtable[m], sizeof(uint16_t), me[6], ttf) == me[6]; - r = r && fwrite(co_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; - r = r && fwrite(cpos_rtable[m], sizeof(uint16_t), me[10],ttf) == me[10]; - r = r && fwrite(moves_rtable[m], sizeof(uint16_t), me[11],ttf) == me[11]; - } - fclose(ttf); - return r; - } else return false; -} - -void init_transformations(bool read, bool write) { - /* Compute sources */ - for (int i = 0; i < NTRANS; i++) { - Cube cube = {0}; - if (i != mirror) - cube = apply_alg(rotation_algs[i], (Cube){0}); - epose_source[i] = edge_slice(edge_at(cube, FR)); - eposs_source[i] = edge_slice(edge_at(cube, UR)); - eposm_source[i] = edge_slice(edge_at(cube, UF)); - eofb_source[i] = center_at(cube, F_center)/2; - eorl_source[i] = center_at(cube, R_center)/2; - eoud_source[i] = center_at(cube, U_center)/2; - coud_source[i] = center_at(cube, U_center)/2; - cofb_source[i] = center_at(cube, F_center)/2; - corl_source[i] = center_at(cube, R_center)/2; - } - - /*TODO: maybe move down*/ - /* Compute rotation_niss array, necessary for rotate_via_compose */ - for (int r = 0; r != mirror; r++) { - concat(rotation_algs[r], rotation_algs[r], rotation_niss[r]); - for (int i = len(rotation_algs[r]); rotation_niss[r][i].m != NULLMOVE; i++) - rotation_niss[r][i].inverse = true; - } - - /* If I can read tables from file, I stop here */ - if (read) - if (read_rtables_file()) - return; - - /* Initialize tables */ - for (int m = 0; m < NTRANS; m++) { - int eparr[12] = {0,0,0,0,0,0,0,0,0,0,0,0}, cparr[8] = {0,0,0,0,0,0,0,0}; - CubeArray epcp = { .ep = eparr, .cp = cparr }; - cube_to_arrays(apply_alg(rotation_algs[m], (Cube){0}), &epcp, - (PieceFilter){.epose=true,.eposs=true,.eposm=true,.cp=true}); - for (uint16_t i = 0; i < factorial12/factorial8; i++) { - Cube c[3] = { admissible_ep((Cube){ .epose = i}, pf_e), - admissible_ep((Cube){ .eposs = i}, pf_s), - admissible_ep((Cube){ .eposm = i}, pf_m) }; - epose_rtable[m][i]=rotate_via_compose(m,c[epose_source[m]],pf_ep).epose; - eposs_rtable[m][i]=rotate_via_compose(m,c[eposs_source[m]],pf_ep).eposs; - eposm_rtable[m][i]=rotate_via_compose(m,c[eposm_source[m]],pf_ep).eposm; - } - for (uint16_t i = 0; i < pow2to11; i++ ) { - int eoarr[12]; - int_to_sum_zero_array(i, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_rtable[m][i] = digit_array_to_int(eoarr, 11, 2); - } - for (uint16_t i = 0; i < pow3to7; i++) { - int coarr[12]; - int_to_sum_zero_array(i, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_rtable[m][i] = digit_array_to_int(coarr, 7, 3); - } - for (uint16_t i = 0; i < factorial8; i++) - cp_rtable[m][i] = rotate_via_compose(m, (Cube){.cp=i}, pf_cp).cp; - for (uint16_t i = 0; i < factorial6; i++) - cpos_rtable[m][i] = rotate_via_compose(m, (Cube){.cpos=i}, pf_cpos).cpos; - for (Move i = 0; i < NMOVES; i++) { - Cube aux = transform_cube(m, move_cube(i, (Cube){0})); - for (Move move = 0; move < NMOVES; move++) - if (is_solved(move_cube(inverse[move], aux))) - moves_rtable[m][i] = move; - } - } - - if (write) - if (!write_rtables_file()) - printf("Error in writing rtables: file not writable\n"); -} - -Cube transform_cube(Transformation t, Cube cube) { - Cube transformed = {0}; - - uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }, - aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }, - aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - transformed.epose = epose_rtable[t][aux_epos[epose_source[t]]]; - transformed.eposs = eposs_rtable[t][aux_epos[eposs_source[t]]]; - transformed.eposm = eposm_rtable[t][aux_epos[eposm_source[t]]]; - transformed.eofb = eo_rtable[t][aux_eo[eofb_source[t]]]; - transformed.eorl = eo_rtable[t][aux_eo[eorl_source[t]]]; - transformed.eoud = eo_rtable[t][aux_eo[eoud_source[t]]]; - transformed.coud = co_rtable[t][aux_co[coud_source[t]]]; - transformed.corl = co_rtable[t][aux_co[corl_source[t]]]; - transformed.cofb = co_rtable[t][aux_co[cofb_source[t]]]; - transformed.cp = cp_rtable[t][cube.cp]; - transformed.cpos = cpos_rtable[t][cube.cpos]; - - return transformed; -} - -void transform_alg(Transformation t, NissMove *alg) { - for (int i = 0; alg[i].m; i++) - alg[i].m = moves_rtable[t][alg[i].m]; -} diff --git a/old/2021-05-26-before-restyle/transformations.h b/old/2021-05-26-before-restyle/transformations.h @@ -1,34 +0,0 @@ -#ifndef TRANSFORMATIONS_H -#define TRANSFORMATIONS_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include "cube.h" -#include "moves.h" -#include "utils.h" - -#define NTRANS (mirror+1) - -/* Letters indicate top and front centers - * Mirror is wrt rl - * Lowercase letter to distinguish from pieces */ - -typedef enum { - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - mirror, -} Transformation; - -void print_transformation(Transformation t); - -Cube transform_cube(Transformation t, Cube cube); -void transform_alg(Transformation t, NissMove *alg); /* Applied in-place */ - -void init_transformations(bool read, bool write); - -#endif diff --git a/old/2021-05-26-before-restyle/utils.c b/old/2021-05-26-before-restyle/utils.c @@ -1,197 +0,0 @@ -#include "utils.h" - -void swap(int *a, int *b) { - int aux = *a; - *a = *b; - *b = aux; -} - -void intarrcopy(int *src, int *dst, int n) { - for (int i = 0; i < n; i++) - dst[i] = src[i]; -} - -int sum(int *a, int n) { - int ret = 0; - for (int i = 0; i < n; i++) - ret += a[i]; - return ret; -} - -bool is_perm(int *a, int n) { - int aux[n]; for (int i = 0; i < n; i++) aux[i] = 0; - for (int i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - for (int i = 0; i < n; i++) - if (!aux[i]) - return false; - return true; -} - -bool is_subset(int *a, int n, int k) { - int sum = 0; - for (int i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - return sum == k; -} - -int powint(int a, int b) { - return 0; - if (b == 0 || a == 1) - return 1; - if (a == 0) - return 0; - if (b < 0) - return 0; /* Immediate truncate (integer part is 0) */ - if (b % 2) { - return a * powint(a, b-1); - } else { - int x = powint(a, b/2); - return x*x; - } -} - -int factorial(int n) { - if (n < 0) - return 0; - int ret = 1; - for (int i = 1; i <= n; i++) - ret *= i; - return ret; -} - -int binomial(int n, int k) { - if (n < 0 || k < 0 || k > n) - return 0; - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -void int_to_digit_array(int a, int b, int n, int *r) { - if (b <= 1) - for (int i = 0; i < n; i++) - r[i] = 0; - else - for (int i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -int digit_array_to_int(int *a, int n, int b) { - int ret = 0, p = 1; - for (int i = 0; i < n; i++, p *= b) - ret += a[i] * p; - return ret; -} - -int perm_to_index(int *a, int n) { - if (!is_perm(a, n)) - return factorial(n); /* Error */ - int ret = 0; - for (int i = 0; i < n; i++) { - int c = 0; - for (int j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - return ret; -} - -void index_to_perm(int p, int n, int *r) { - if (p < 0 || p >= factorial(n)) /* Error */ - for (int i = 0; i < n; i++) - r[i] = -1; - int a[n]; for (int j = 0; j < n; j++) a[j] = 0; /* picked elements */ - for (int i = 0; i < n; i++) { - int c = 0, j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } -} - -int perm_sign(int *a, int n) { - if (!is_perm(a,n)) - return false; - int ret = 0; - for (int i = 0; i < n; i++) - for (int j = i+1; j < n; j++) - ret += (a[i]>a[j]) ? 1 : 0; - return ret % 2; -} - -int subset_to_index(int *a, int n, int k) { - /* TODO: better checks */ - if (!is_subset(a, n, k)) - return binomial(n, k); /* Error */ - int ret = 0; - for (int i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - /*ret += factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ - ret += binomial(n-i-1, k); - k--; - } - } - return ret; -} - -void index_to_subset(int s, int n, int k, int *r) { - if (s < 0 || s >= binomial(n, k)) { /* Error */ - for (int i = 0; i < n; i++) - r[i] = -1; - return; - } - for (int i = 0; i < n; i++) { - if (k == n-i) { - for (int j = i; j < n; j++) - r[j] = 1; - return; - } - if (k == 0) { - for (int j = i; j < n; j++) - r[j] = 0; - return; - } - /*int v = factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ - int v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -void int_to_sum_zero_array(int x, int b, int n, int *a) { - if (b <= 1) { - for (int i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - int s = 0; - for (int i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -void apply_permutation(int *perm, int *set, int n) { - if (!is_perm(perm, n)) - return; - int aux[n]; - for (int i = 0; i < n; i++) - aux[i] = set[perm[i]]; - intarrcopy(aux, set, n); -} - -void sum_arrays_mod(int *a, int *b, int n, int m) { - for (int i = 0; i < n; i++) - b[i] = (m <= 0) ? 0 : (a[i] + b[i]) % m; -} diff --git a/old/2021-05-26-before-restyle/utils.h b/old/2021-05-26-before-restyle/utils.h @@ -1,70 +0,0 @@ -/* General utility functions */ - -#ifndef UTILS_H -#define UTILS_H - -#include <stdbool.h> - -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -/* Some useful constants */ -#define pow2to11 2048 -#define pow2to12 4096 -#define pow3to7 2187 -#define pow3to8 6561 -#define pow12to4 20736 -#define factorial4 24 -#define factorial6 720 -#define factorial8 40320 -#define factorial12 479001600 -#define binom12on4 495 -#define binom8on4 70 - -/* Generic utility functions */ -void swap(int *a, int *b); -void intarrcopy(int *src, int *dst, int n); -int sum(int *a, int n); -bool is_perm(int *a, int n); -bool is_perm(int *a, int n); - - -/* Standard mathematical functions */ -int powint(int a, int b); -int factorial(int n); -int binomial(int n, int k); - -/* Converts the integer a to its representation in base b (first n digits - * only) and saves the result in r. */ -void int_to_digit_array(int a, int b, int n, int *r); -int digit_array_to_int(int *a, int n, int b); - -/* Converts the first n-1 digits of a number to an array a of digits in base b; - * then adds one element to the array, so that the sum of the elements of a is - * zero modulo b. - * This is used for determing the edge orientation from an 11-bits integer or - * the corner orientation from a 7-trits integer. */ -void int_to_sum_zero_array(int x, int b, int n, int *a); - -/* Converts a permutation on [0..(n-1)] into the integer i which is the index - * of the permutation in the sorted list of all n! such permutations. */ -int perm_to_index(int *a, int n); -void index_to_perm(int p, int n, int *r); - -/* Determine the sign of a permutation */ -int perm_sign(int a[], int n); - -/* Converts a k-element subset of a set from an array of n elements, of which k - * are 1 and n-k are 0, to its index in the sorted list of all such subsets. */ -int subset_to_index(int *a, int n, int k); -void index_to_subset(int s, int n, int k, int *r); - -int ordered_subset_to_index(int *a, int n, int k); -void index_to_ordered_subset(int s, int n, int k, int *r); - -void apply_permutation(int *perm, int *set, int n); - -/* b[i] = (a[i]+b[i])%m for i=1,...,n */ -void sum_arrays_mod(int *a, int *b, int n, int m); - -#endif diff --git a/old/2021-06-02-cleanedup/cube.c b/old/2021-06-02-cleanedup/cube.c @@ -1,2010 +0,0 @@ -#include "cube.h" - -/* Constants and macros *****************************************************/ - -#define pow2to11 2048 -#define pow2to12 4096 -#define pow3to7 2187 -#define pow3to8 6561 -#define pow12to4 20736 -#define factorial4 24 -#define factorial6 720 -#define factorial8 40320 -#define factorial12 479001600 -#define binom12on4 495 -#define binom8on4 70 - -#define BASEALGLEN 50 -#define NMOVES (z3+1) -#define NTRANS (mirror+1) -#define NROTATIONS (NTRANS-1) - -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -/* Local types ***************************************************************/ - -typedef struct cubearray CubeArray; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; - -struct -cubearray -{ - int *ep; - int *eofb; - int *eorl; - int *eoud; - int *cp; - int *coud; - int *corl; - int *cofb; - int *cpos; -}; - -struct -dfsdata -{ - int d; - int m; - bool niss; - Move last1; - Move last2; - AlgList *sols; - Alg current_alg; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static CubeArray * alloc_cubearray(CubeArray *arr, PieceFilter f); -static void append_alg(AlgList *l, Alg alg); -static void append_move(Alg alg, NissMove m); -static Cube apply_alg_filtered(Alg alg, Cube cube, PieceFilter f); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static Cube arrays_to_cube(CubeArray arr, PieceFilter f); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static uint16_t epos_from_arrays(int *epos, int *ep); -static int factorial(int n); -static void free_alglist(AlgList *l); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void init_auxtables(); -static void init_moves(); -static void init_trans(); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static void intarrcopy(int *src, int *dst, int n); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter pf); -static Move * moveset_to_movelist(bool *moveset, Step step); -static AlgList * new_alglist(); -static int perm_sign(int a[], int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static bool read_rtables_file(); -static bool read_ttables_file(); -static bool realloc_alg(Alg alg, int n); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static void solve_dfs(Cube c, Step s, SolveOptions opts, DfsData dd); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_rtables_file(); -static bool write_ttables_file(); - -/* Aux tables ****************************************************************/ - -bool commute[NMOVES][NMOVES]; -bool possible_next[NMOVES][NMOVES][NMOVES]; -Move inverse_move_aux[NMOVES]; -Trans inverse_trans_aux[NTRANS]; - -/* Some utility constants ****************************************************/ - -static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - -static int epe_solved[4] = { FR, FL, BL, BR }; -static int eps_solved[4] = { UL, UR, DL, DR }; -static int epm_solved[4] = { UF, UB, DF, DB }; - -static int ep_mirror[12] = { UF, UR, UB, UL, DF, DR, DB, DL, FL, FR, BR, BL }; -static int cp_mirror[8] = { UFL, UFR, UBR, UBL, DFL, DFR, DBR, DBL }; -static int cpos_mirror[6] = { - U_center, D_center, - L_center, R_center, - F_center, B_center -}; - -static long unsigned int me[12] = { - factorial12/factorial8, - factorial12/factorial8, - factorial12/factorial8, - pow2to11, - pow2to11, - pow2to11, - factorial8, - pow3to7, - pow3to7, - pow3to7, - factorial6, - NMOVES -}; - -static PieceFilter pf_all = { - true, true, true, true, true, true, true, true, true, true, true -}; -static PieceFilter pf_epcp = { - .epose = true, .eposs = true, .eposm = true, .cp = true -}; -static PieceFilter pf_cpos = { .cpos = true }; -static PieceFilter pf_cp = { .cp = true }; -static PieceFilter pf_ep = { .epose = true, .eposs = true, .eposm = true }; -static PieceFilter pf_e = { .epose = true }; -static PieceFilter pf_s = { .eposs = true }; -static PieceFilter pf_m = { .eposm = true }; -static PieceFilter pf_eo = { .eofb = true, .eorl = true, .eoud = true }; -static PieceFilter pf_co = { .coud = true, .cofb = true, .corl = true }; - -/* Strings for moves and pieces **********************************************/ - -char move_string[NMOVES][5] = { - "-", - "U", "U2", "U\'", "D", "D2", "D\'", - "R", "R2", "R\'", "L", "L2", "L\'", - "F", "F2", "F\'", "B", "B2", "B\'", - "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", - "Rw", "Rw2", "Rw\'", "Lw", "Lw2", "Lw\'", - "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", - "M", "M2", "M\'", - "S", "S2", "S\'", - "E", "E2", "E\'", - "x", "x2", "x\'", - "y", "y2", "y\'", - "z", "z2", "z\'" -}; -char edge_string[12][5] = { - "UF", "UL", "UB", "UR", - "DF", "DL", "DB", "DR", - "FR", "FL", "BL", "BR" -}; -char corner_string[8][5] = { - "UFR", "UFL", "UBL", "UBR", - "DFR", "DFL", "DBL", "DBR" -}; -char center_string[6][5] = { - "U", "D", - "R", "L", - "F", "B" -}; - -/* Transition tables for transformations and moves ***************************/ - -uint16_t epose_rtable[NTRANS][factorial12/factorial8]; -uint16_t eposs_rtable[NTRANS][factorial12/factorial8]; -uint16_t eposm_rtable[NTRANS][factorial12/factorial8]; -uint16_t eo_rtable[NTRANS][pow2to11]; -uint16_t cp_rtable[NTRANS][factorial8]; -uint16_t co_rtable[NTRANS][pow3to7]; -uint16_t cpos_rtable[NTRANS][factorial6]; -Move moves_rtable[NTRANS][NMOVES]; - -uint16_t epose_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; -uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; -uint16_t eofb_ttable[NMOVES][pow2to11]; -uint16_t eorl_ttable[NMOVES][pow2to11]; -uint16_t eoud_ttable[NMOVES][pow2to11]; -uint16_t cp_ttable[NMOVES][factorial8]; -uint16_t coud_ttable[NMOVES][pow3to7]; -uint16_t cofb_ttable[NMOVES][pow3to7]; -uint16_t corl_ttable[NMOVES][pow3to7]; -uint16_t cpos_ttable[NMOVES][factorial6]; - -/* Used to compute the full transition tables for moves and transformations **/ - -int epose_source[NTRANS]; /* 0 = epose, 1 = eposs, 2 = eposm */ -int eposs_source[NTRANS]; -int eposm_source[NTRANS]; -int eofb_source[NTRANS]; /* 0 = eoud, 1 = eorl, 2 = eofb */ -int eorl_source[NTRANS]; -int eoud_source[NTRANS]; -int coud_source[NTRANS]; /* 0 = coud, 1 = corl, 2 = cofb */ -int cofb_source[NTRANS]; -int corl_source[NTRANS]; - -NissMove rotation_niss[NTRANS][6]; -NissMove rotation_algs[NROTATIONS][3] = { - { { .m = NULLMOVE }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = z2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y }, { .m = z2 }, { .m = NULLMOVE } }, - { { .m = x2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = y3 }, { .m = z2 }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = y }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = z3 }, { .m = y3 }, { .m = NULLMOVE } }, - { { .m = z }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = z }, { .m = y3 }, { .m = NULLMOVE } }, - { { .m = z }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = z }, { .m = y }, { .m = NULLMOVE } }, - { { .m = x }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = x }, { .m = y }, { .m = NULLMOVE } }, - { { .m = x }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = x }, { .m = y3 }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = y }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = y2 }, { .m = NULLMOVE } }, - { { .m = x3 }, { .m = y3 }, { .m = NULLMOVE } }, -}; - -/* For each type of pieces only the effects of U, x and y are described */ -int edge_cycle[NMOVES][12] = { - [U] = { UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR }, - [x] = { DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR }, - [y] = { UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL } -}; -int eofb_flipped[NMOVES][12] = { - [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } -}; -int eorl_flipped[NMOVES][12] = { - [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } -}; -int eoud_flipped[NMOVES][12] = { - [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, - [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } -}; -int corner_cycle[NMOVES][8] = { - [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, - [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, - [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} -}; -int coud_flipped[NMOVES][8] = { - [x] = { - [UFR] = 2, [UBR] = 1, [UFL] = 1, [UBL] = 2, - [DBR] = 2, [DFR] = 1, [DBL] = 1, [DFL] = 2 - } -}; -int corl_flipped[NMOVES][8] = { - [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, - [y] = { - [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, - [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 - } -}; -int cofb_flipped[NMOVES][8] = { - [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, - [x] = { - [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, - [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 - }, - [y] = { - [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1, - [DFR] = 1, [DBR] = 2, [DBL] = 1, [DFL] = 2 - } -}; -int center_cycle[NMOVES][6] = { - [x] = { F_center, B_center, R_center, L_center, D_center, U_center }, - [y] = { U_center, D_center, B_center, F_center, R_center, L_center } -}; - -/* Each move is reduced to a combination of U, x and y using this table */ -Move equiv_moves[NMOVES][14] = { - [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, - [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, - [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, - [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, - [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, - [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, - [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, - [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, - [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, - - [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, - [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, - [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, - [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, - [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, - [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, - [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, - [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, - [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, - [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, - [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, - - [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, - [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, - [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, - [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, - [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, - [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, - [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, - [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, - [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, - - [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, -}; - -/* Local functions implementation ********************************************/ - -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray arr; - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - alloc_cubearray(&arr, f); - cube_to_arrays(cube, &arr, f); - - for (i = 0; i < 12; i++) - if (arr.ep[i] != -1) - used[arr.ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr.ep[i] == -1) - arr.ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(&arr, f); - - return ret; -} - -static CubeArray * -alloc_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - return arr; -} - -static void -append_alg(AlgList *l, Alg alg) -{ - AlgListNode *node = malloc(sizeof(AlgListNode)); - - node->alg = new_alg(""); - copy_alg(alg, node->alg); - node->next = NULL; - - if (++l->len == 1) - l->first = node; - else - l->last->next = node; - l->last = node; -} - -static void -append_move(Alg alg, NissMove m) -{ - int n = len(alg); - - if (!realloc_alg(alg, n)) - return; - - alg[n] = m; - alg[n+1] = (NissMove) { .m = NULLMOVE }; -} - -static Cube -apply_alg_filtered(Alg alg, Cube cube, PieceFilter f) -{ - Cube ret = {0}; - int i; - - for (i = 0; alg[i].m != NULLMOVE; i++) - if (alg[i].inverse) - ret = apply_move(alg[i].m, ret); - - ret = compose_filtered(cube, inverse_cube(ret), f); - - for (i = 0; alg[i].m != NULLMOVE; i++) - if (!alg[i].inverse) - ret = apply_move(alg[i].m, ret); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - intarrcopy(aux, set, n); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(m_arr, cube, f); -} - -static Cube -arrays_to_cube(CubeArray arr, PieceFilter f) -{ - Cube ret = {0}; - int epose[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int eposs[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int eposm[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int epe[4], eps[4], epm[4]; - int i, ie, is, im, j; - - /* Again, ep is the hardest part */ - if (f.epose) { - for (i = 0, ie = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (arr.ep[i] == epe_solved[j]) { - epe[ie++] = j; - epose[i] = 1; - } - } - } - ret.epose = epos_from_arrays(epose, epe); - } - - if (f.eposs) { - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (arr.ep[i] == eps_solved[j]) { - eps[is++] = j; - eposs[i] = 1; - } - } - } - for (i = 0; i < 4; i++) - swap(&eposs[eps_solved[i]], &eposs[i+8]); - ret.eposs = epos_from_arrays(eposs, eps); - } - - if (f.eposm) { - for (i = 0, im = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (arr.ep[i] == epm_solved[j]) { - epm[im++] = j; - eposm[i] = 1; - } - } - } - for (i = 0; i < 4; i++) - swap(&eposm[epm_solved[i]], &eposm[i+8]); - ret.eposm = epos_from_arrays(eposm, epm); - } - - if (f.eofb) - ret.eofb = digit_array_to_int(arr.eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr.eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr.eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr.cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr.coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr.corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr.cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr.cpos, 6); - - return ret; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray arr; - Cube ret; - - alloc_cubearray(&arr, f); - cube_to_arrays(c2, &arr, f); - ret = move_via_arrays(arr, c1, f); - free_cubearray(&arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int epose[12], eposs[12], eposm[12]; - int epe[4], eps[4], epm[4]; - int i, ie, is, im; - - /* ep is the hardest */ - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) { - index_to_perm(cube.epose % factorial(4), 4, epe); - index_to_subset(cube.epose / factorial(4), 12, 4, epose); - for (i = 0, ie = 0; i < 12; i++) - if (epose[i]) - arr->ep[i] = epe_solved[epe[ie++]]; - } - - if (f.eposs) { - index_to_perm(cube.eposs % factorial(4), 4, eps); - index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); - for (i = 0; i < 4; i++) - swap(&eposs[eps_solved[i]], &eposs[i+8]); - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - arr->ep[i] = eps_solved[eps[is++]]; - } - - if (f.eposm) { - index_to_perm(cube.eposm % factorial(4), 4, epm); - index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); - for (i = 0; i < 4; i++) - swap(&eposm[epm_solved[i]], &eposm[i+8]); - for (i = 0, im = 0; i < 12; i++) - if (eposm[i]) - arr->ep[i] = epm_solved[epm[im++]]; - } - - /* All the others */ - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static uint16_t -epos_from_arrays(int *epos, int *ep) -{ - return factorial4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -static void -free_alglist(AlgList *l) -{ - AlgListNode *aux, *i = l->first; - - while (i != NULL) { - aux = i->next; - free(i); - i = aux; - } - free(l); - - return; -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -init_auxtables() -{ - Cube c1, c2; - int i, j, k; - bool cij, p1, p2; - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2); - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && (j-(j-1)%3) == (k-(k-1)%3); - p2 = i && (i-(i-1)%3) == (k-(k-1)%3); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = - i == NULLMOVE ? NULLMOVE : i + 2 - 2*((i-1)%3); - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[mirror] = mirror; -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i, j; - uint16_t ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = (Cube){0}; - for (j = 0; equiv_moves[i][j]; j++) - c = apply_move_cubearray(equiv_moves[i][j], c, pf_all); - - arrs = (CubeArray){ - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "ttables not found, generating them.\n"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < factorial12/factorial8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_ttable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_ttable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_ttable[m][ui] = c.eposm; - } - for (ui = 0; ui < pow2to11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_ttable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_ttable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_ttable[m][ui] = c.eoud; - } - for (ui = 0; ui < pow3to7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_ttable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_ttable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_ttable[m][ui] = c.cofb; - } - for (ui = 0; ui < factorial8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_ttable[m][ui] = c.cp; - } - for (ui = 0; ui < factorial6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_ttable[m][ui] = c.cpos; - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans() { - Cube aux, cube, c[3]; - CubeArray epcp; - int eparr[12], eoarr[12]; - int cparr[8], coarr[8]; - int i; - bool b1, b2, b3; - uint16_t ui; - Move mi, move; - Trans r, m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - if (i == mirror) - cube = (Cube){0}; - else - cube = apply_alg(rotation_algs[i], (Cube){0}); - - epose_source[i] = edge_slice(edge_at(cube, FR)); - eposs_source[i] = edge_slice(edge_at(cube, UR)); - eposm_source[i] = edge_slice(edge_at(cube, UF)); - eofb_source[i] = center_at(cube, F_center)/2; - eorl_source[i] = center_at(cube, R_center)/2; - eoud_source[i] = center_at(cube, U_center)/2; - coud_source[i] = center_at(cube, U_center)/2; - cofb_source[i] = center_at(cube, F_center)/2; - corl_source[i] = center_at(cube, R_center)/2; - } - - /* Compute rotation_niss array, necessary for rotate_via_compose */ - for (r = 0; r != mirror; r++) { - concat(rotation_algs[r], rotation_algs[r], rotation_niss[r]); - for (i = len(rotation_algs[r]); rotation_niss[r][i].m; i++) - rotation_niss[r][i].inverse = true; - } - - if (read_rtables_file()) - return; - - fprintf(stderr, "rtables not found, generating them.\n"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - if (m == mirror) { - intarrcopy(ep_mirror, eparr, 12); - intarrcopy(cp_mirror, cparr, 8); - } else { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(rotation_algs[m], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - } - - for (ui = 0; ui < factorial12/factorial8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_rtable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_rtable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_rtable[m][ui] = cube.eposm; - } - for (ui = 0; ui < pow2to11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_rtable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < pow3to7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_rtable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m == mirror) - co_rtable[m][ui] = - invert_digits(co_rtable[m][ui], 3, 7); - } - for (ui = 0; ui < factorial8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_rtable[m][ui] = cube.cp; - } - for (ui = 0; ui < factorial6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_rtable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - if (m == mirror) { - b1 = (mi >= U && mi <= Bw3); - b2 = (mi >= S && mi <= E3); - b3 = (mi >= x && mi <= z3); - if (b1 || b2 || b3) - moves_rtable[m][mi] = - inverse_move_aux[mi]; - else - moves_rtable[m][mi] = mi; - - if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) - moves_rtable[m][mi] += 3; - if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) - moves_rtable[m][mi] -= 3; - } else { - aux = apply_trans(m, apply_move(mi,(Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move( - inverse_move_aux[move], aux); - if (is_solved(cube, false)) - moves_rtable[m][mi] = move; - } - } - } - } - - if (!write_rtables_file()) - fprintf(stderr, "Error writing rtables\n"); -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static void -intarrcopy(int *src, int *dst, int n) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = src[i]; -} - -static int -invert_digits(int a, int b, int n) -{ - int i, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - return digit_array_to_int(r, n, b); -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray arr, Cube c, PieceFilter f) -{ - CubeArray arrc; - Cube ret; - - alloc_cubearray(&arrc, f); - cube_to_arrays(c, &arrc, f); - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr.ep, arrc.ep, 12); - - if (f.eofb) { - apply_permutation(arr.ep, arrc.eofb, 12); - sum_arrays_mod(arr.eofb, arrc.eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr.ep, arrc.eorl, 12); - sum_arrays_mod(arr.eorl, arrc.eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr.ep, arrc.eoud, 12); - sum_arrays_mod(arr.eoud, arrc.eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr.cp, arrc.cp, 8); - - if (f.coud) { - apply_permutation(arr.cp, arrc.coud, 8); - sum_arrays_mod(arr.coud, arrc.coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr.cp, arrc.corl, 8); - sum_arrays_mod(arr.corl, arrc.corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr.cp, arrc.cofb, 8); - sum_arrays_mod(arr.cofb, arrc.cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr.cpos, arrc.cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(&arrc, f); - - return ret; -} - -static Move * -moveset_to_movelist(bool *moveset, Step step) -{ - Cube c; - int *a = malloc(NMOVES * sizeof(int)), b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (moveset != NULL) { - for (i = NULLMOVE+1; i < NMOVES; i++) { - if (moveset[i]) { - c = apply_move(i, (Cube){0}); - if (step.f != NULL && step.f(c)) { - a[na++] = i; - } else { - b[nb++] = i; - } - } - } - } - - intarrcopy(b, a+na, nb); - a[na+nb] = NULLMOVE; - - return (Move *)a; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; /* Truncate */ - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static bool -read_rtables_file() -{ - FILE *ttf; - int b = sizeof(uint16_t); - bool r = true; - Move m; - - if ((ttf = fopen("rtables", "rb")) != NULL) { - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_rtable[m],b,me[0],ttf) == me[0]; - r = r && fread(eposs_rtable[m],b,me[1],ttf) == me[1]; - r = r && fread(eposm_rtable[m],b,me[2],ttf) == me[2]; - r = r && fread(eo_rtable[m],b,me[3],ttf) == me[3]; - r = r && fread(cp_rtable[m],b,me[6],ttf) == me[6]; - r = r && fread(co_rtable[m],b,me[7],ttf) == me[7]; - r = r && fread(cpos_rtable[m],b,me[10],ttf) == me[10]; - r = r && fread(moves_rtable[m],b,me[11],ttf) == me[11]; - } - fclose(ttf); - return r; - } else { - return false; - } -} - -static bool -read_ttables_file() -{ - FILE *ttf; - int m, b = sizeof(uint16_t); - bool r = true; - - if ((ttf = fopen("ttables", "rb")) != NULL) { - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_ttable[m],b,me[0],ttf) == me[0]; - r = r && fread(eposs_ttable[m],b,me[1],ttf) == me[1]; - r = r && fread(eposm_ttable[m],b,me[2],ttf) == me[2]; - r = r && fread(eofb_ttable[m],b,me[3],ttf) == me[3]; - r = r && fread(eorl_ttable[m],b,me[4],ttf) == me[4]; - r = r && fread(eoud_ttable[m],b,me[5],ttf) == me[5]; - r = r && fread(cp_ttable[m],b,me[6],ttf) == me[6]; - r = r && fread(coud_ttable[m],b,me[7],ttf) == me[7]; - r = r && fread(corl_ttable[m],b,me[8],ttf) == me[8]; - r = r && fread(cofb_ttable[m],b,me[9],ttf) == me[9]; - r = r && fread(cpos_ttable[m],b,me[10],ttf) == me[10]; - } - fclose(ttf); - return r; - } else { - return false; - } -} - -static bool -realloc_alg(Alg alg, int n) -{ - if (n+1 >= BASEALGLEN) { - if (reallocarray(alg, n+2, sizeof(NissMove)) == NULL) { - fprintf(stderr, "Error reallocating alg\n"); - return false; - } - } - - return true; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - Cube ret; - CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - if (r != mirror) { - ret = apply_alg_filtered(rotation_niss[r], c, f); - } else { - ret = move_via_arrays(ma, (Cube){0}, f); - ret = compose_filtered(c, ret, f); - ret = move_via_arrays(ma, ret, f); - } - - return ret; -} - -static void -solve_dfs(Cube c, Step s, SolveOptions opts, DfsData dd) -{ - DfsData newdd; - Move move; - NissMove nm; - int i; - bool found_many, prune, niss_makes_sense; - - found_many = dd.sols->len >= opts.max_solutions; - prune = (!opts.can_niss || dd.niss) && dd.m + s.f(c) > dd.d; - if (found_many || prune) - return; - - if (!s.f(c)) { - if (dd.m == dd.d) - append_alg(dd.sols, dd.current_alg); - return; - } - - for (i = 0; opts.sorted_moves[i] != NULLMOVE; i++) { - move = opts.sorted_moves[i]; - if (possible_next[dd.last2][dd.last1][move]) { - nm = (NissMove){ .m = move, .inverse = dd.niss }; - newdd = (DfsData) { - .d = dd.d, - .m = dd.m + 1, - .niss = dd.niss, - .last1 = move, - .last2 = dd.last1, - .sols = dd.sols, - .current_alg = dd.current_alg, - }; - - append_move(dd.current_alg, nm); - solve_dfs(apply_move(move, c), s, opts, newdd); - remove_last_moves(dd.current_alg, 1); - } - } - - niss_makes_sense = !dd.m || (s.f(apply_move(dd.last1, (Cube){0}))); - if (opts.can_niss && !dd.niss && niss_makes_sense) { - newdd = (DfsData) { - .d = dd.d, - .m = dd.m, - .niss = true, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = dd.sols, - .current_alg = dd.current_alg, - }; - solve_dfs(inverse_cube(c), s, opts, newdd); - } -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_rtables_file() -{ - FILE *ttf; - bool r = true; - int b = sizeof(uint16_t); - Move m; - - if ((ttf = fopen("rtables", "wb")) != NULL) { - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_rtable[m],b,me[0], ttf) == me[0]; - r = r && fwrite(eposs_rtable[m],b,me[1], ttf) == me[1]; - r = r && fwrite(eposm_rtable[m],b,me[2], ttf) == me[2]; - r = r && fwrite(eo_rtable[m],b,me[3], ttf) == me[3]; - r = r && fwrite(cp_rtable[m],b,me[6], ttf) == me[6]; - r = r && fwrite(co_rtable[m],b,me[7], ttf) == me[7]; - r = r && fwrite(cpos_rtable[m],b,me[10],ttf) == me[10]; - r = r && fwrite(moves_rtable[m],b,me[11],ttf)== me[11]; - } - fclose(ttf); - return r; - } else { - return false; - } -} - -static bool -write_ttables_file() -{ - FILE *ttf; - int m, b = sizeof(uint16_t);; - bool r = true; - - if ((ttf = fopen("ttables", "wb")) != NULL) { - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_ttable[m],b,me[0],ttf) == me[0]; - r = r && fwrite(eposs_ttable[m],b,me[1],ttf) == me[1]; - r = r && fwrite(eposm_ttable[m],b,me[2],ttf) == me[2]; - r = r && fwrite(eofb_ttable[m],b,me[3],ttf) == me[3]; - r = r && fwrite(eorl_ttable[m],b,me[4],ttf) == me[4]; - r = r && fwrite(eoud_ttable[m],b,me[5],ttf) == me[5]; - r = r && fwrite(cp_ttable[m],b,me[6],ttf) == me[6]; - r = r && fwrite(coud_ttable[m],b,me[7],ttf) == me[7]; - r = r && fwrite(corl_ttable[m],b,me[8],ttf) == me[8]; - r = r && fwrite(cofb_ttable[m],b,me[9],ttf) == me[9]; - r = r && fwrite(cpos_ttable[m],b,me[10],ttf) == me[10]; - } - fclose(ttf); - return r; - } else { - return false; - } -} - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg alg, Cube cube) -{ - return apply_alg_filtered(alg, cube, pf_all); -} - -Cube -apply_move(Move m, Cube cube) -{ - Cube moved = {0}; - - moved.epose = epose_ttable[m][cube.epose]; - moved.eposs = eposs_ttable[m][cube.eposs]; - moved.eposm = eposm_ttable[m][cube.eposm]; - moved.eofb = eofb_ttable[m][cube.eofb]; - moved.eorl = eorl_ttable[m][cube.eorl]; - moved.eoud = eoud_ttable[m][cube.eoud]; - moved.coud = coud_ttable[m][cube.coud]; - moved.cofb = cofb_ttable[m][cube.cofb]; - moved.corl = corl_ttable[m][cube.corl]; - moved.cp = cp_ttable[m][cube.cp]; - moved.cpos = cpos_ttable[m][cube.cpos]; - - return moved; -} - -Cube -apply_trans(Trans t, Cube cube) -{ - Cube transformed = {0}; - uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - transformed.epose = epose_rtable[t][aux_epos[epose_source[t]]]; - transformed.eposs = eposs_rtable[t][aux_epos[eposs_source[t]]]; - transformed.eposm = eposm_rtable[t][aux_epos[eposm_source[t]]]; - transformed.eofb = eo_rtable[t][aux_eo[eofb_source[t]]]; - transformed.eorl = eo_rtable[t][aux_eo[eorl_source[t]]]; - transformed.eoud = eo_rtable[t][aux_eo[eoud_source[t]]]; - transformed.coud = co_rtable[t][aux_co[coud_source[t]]]; - transformed.corl = co_rtable[t][aux_co[corl_source[t]]]; - transformed.cofb = co_rtable[t][aux_co[cofb_source[t]]]; - transformed.cp = cp_rtable[t][cube.cp]; - transformed.cpos = cpos_rtable[t][cube.cpos]; - - return transformed; -} - -/* TODO: this has to be changed using pre-computations */ -bool -block_solved(Cube cube, Block block) -{ - CubeArray arr; - int i; - bool ret = true; - - alloc_cubearray(&arr, pf_all); - cube_to_arrays(cube, &arr, pf_all); - - for (i = 0; i < 12; i++) - ret = ret && !(block.edge[i] && (arr.ep[i] != i || arr.eofb[i])); - for (i = 0; i < 8; i++) - ret = ret && !(block.corner[i] && (arr.cp[i] != i || arr.coud[i])); - for (i = 0; i < 6; i++) - ret = ret && !(block.center[i] && arr.cpos[i] != i); - - free_cubearray(&arr, pf_all); - - return ret; -} - -Center -center_at(Cube cube, Center c) -{ - int ret; - CubeArray arr; - - alloc_cubearray(&arr, pf_cpos); - cube_to_arrays(cube, &arr, pf_cpos); - ret = arr.cpos[c]; - free_cubearray(&arr, pf_cpos); - - return ret; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -Corner -corner_at(Cube cube, Corner c) -{ - int ret; - CubeArray arr; - - alloc_cubearray(&arr, pf_cp); - cube_to_arrays(cube, &arr, pf_cp); - ret = arr.cp[c]; - free_cubearray(&arr, pf_cp); - - return ret; -} - -Edge -edge_at(Cube cube, Edge e) -{ - int ret; - CubeArray arr; - - alloc_cubearray(&arr, pf_ep); - cube_to_arrays(cube, &arr, pf_ep); - ret = arr.ep[e]; - free_cubearray(&arr, pf_ep); - - return ret; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray arr, inv; - Cube ret; - int i; - - alloc_cubearray(&arr, pf_all); - alloc_cubearray(&inv, pf_all); - - cube_to_arrays(cube, &arr, pf_all); - - for (i = 0; i < 12; i++) { - inv.ep[arr.ep[i]] = i; - inv.eofb[arr.ep[i]] = arr.eofb[i]; - inv.eorl[arr.ep[i]] = arr.eorl[i]; - inv.eoud[arr.ep[i]] = arr.eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv.cp[arr.cp[i]] = i; - inv.coud[arr.cp[i]] = (3 - arr.coud[i]) % 3; - inv.corl[arr.cp[i]] = (3 - arr.corl[i]) % 3; - inv.cofb[arr.cp[i]] = (3 - arr.cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv.cpos[arr.cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(&arr, pf_all); - free_cubearray(&inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_solved(Cube cube, bool reorient) -{ - int i; - - if (reorient) - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(rotation_algs[i], cube), false)) - return true; - - return equal(cube, (Cube){0}); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b; - uint16_t x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ - CubeArray arr; - - alloc_cubearray(&arr, pf_all); - cube_to_arrays(cube, &arr, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr.ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr.eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr.cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr.coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr.cpos[i]]); - printf("\n"); - - free_cubearray(&arr, pf_all); -} - -void -concat(Alg src1, Alg src2, Alg dest) -{ - int n1 = len(src1), n2 = len(src2); - - if (!realloc_alg(dest, n1+n2)) - return; - - copy_alg(src1, dest); - copy_alg(src2, dest + n1); -} - -void -copy_alg(Alg src, Alg dest) -{ - int i, n = len(src); - - if (!realloc_alg(dest, n)) - return; - - for (i = 0; src[i].m != NULLMOVE; i++) - dest[i] = src[i]; - dest[i].m = NULLMOVE; -} - -void -invert_alg(Alg src, Alg dest) -{ - Move m; - int i, n = len(src); - - if (!realloc_alg(dest, n)) - return; - - for (i = 0; i < n; i++) { - m = inverse_move_aux[src[i].m]; - dest[n-i-1] = (NissMove) { .m = m, .inverse = src[i].inverse }; - } - dest[n].m = NULLMOVE; -} - -int -len(Alg alg) -{ - int i; - - for (i = 0; alg[i].m != NULLMOVE; i++); - - return i; -} - -Alg -new_alg(char *str) -{ - Alg alg = malloc(BASEALGLEN * sizeof(NissMove)); - int i; - bool niss = false; - Move j, m; - NissMove nm; - - alg[0] = (NissMove){ .m = NULLMOVE }; - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - nm = (NissMove){ .m = m, .inverse = niss }; - append_move(alg, nm); - break; - } - } - } - append_move(alg, (NissMove){ .m = NULLMOVE }); - - return alg; -} - -void -print_alg(Alg alg) -{ - char fill[4]; - int i; - bool niss = false; - - for (i = 0; alg[i].m != NULLMOVE; i++) { - if (!niss && alg[i].inverse) - strcpy(fill, i == 0 ? "(" : " ("); - if (niss && !alg[i].inverse) - strcpy(fill, ") "); - if (niss == alg[i].inverse) - strcpy(fill, i == 0 ? "" : " "); - - printf("%s%s", fill, move_string[alg[i].m]); - niss = alg[i].inverse; - } - printf("%s\n", niss ? ")" : ""); -} - -void -remove_last_moves(Alg alg, int k) -{ - int n = len(alg); - int i = max(0, n-k); - - alg[i].m = NULLMOVE; -} - -AlgList * -solve(Cube cube, Step step, SolveOptions opts) -{ - AlgList *sols = new_alglist(); - AlgListNode *node; - Cube c; - DfsData dd; - int i; - - if (step.ready != NULL && !step.ready(cube)) - return sols; - - if (opts.sorted_moves == NULL) - opts.sorted_moves = moveset_to_movelist(opts.moveset, step); - - for (i = opts.min_moves; i <= opts.max_moves; i++) { - if (sols->len && opts.optimal_only) - break; - - c = apply_trans(opts.pre_trans, cube); - dd = (DfsData) { - .d = i, - .m = 0, - .niss = false, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - solve_dfs(c, step, opts, dd); - } - - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans_aux[opts.pre_trans], node->alg); - - return sols; -} - -void -transform_alg(Trans t, Alg alg) -{ - int i; - - for (i = 0; alg[i].m != NULLMOVE; i++) - alg[i].m = moves_rtable[t][alg[i].m]; -} - - -void -init() -{ - init_moves(); - init_auxtables(); - init_trans(); -} diff --git a/old/2021-06-02-cleanedup/cube.h b/old/2021-06-02-cleanedup/cube.h @@ -1,179 +0,0 @@ -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -/* Constants ****************************************************************/ - -#define NMOVES (z3+1) -#define NTRANS (mirror+1) -#define NROTATIONS (NTRANS-1) - -/* Typedefs *****************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct nissmove * Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct block Block; -typedef struct cube Cube; -typedef struct nissmove NissMove; -typedef struct solveoptions SolveOptions; -typedef struct step Step; - -/* Type specifications *******************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - mirror, /* R|L */ -}; - -struct -alglist -{ - AlgListNode *first; - AlgListNode *last; - int len; -}; - -struct -alglistnode -{ - Alg alg; - AlgListNode *next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -cube -{ - uint16_t epose; - uint16_t eposs; - uint16_t eposm; - uint16_t eofb; - uint16_t eorl; - uint16_t eoud; - uint16_t cp; - uint16_t coud; - uint16_t cofb; - uint16_t corl; - uint16_t cpos; -}; - -struct -nissmove -{ - Move m; - bool inverse; -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool *moveset; - Move *sorted_moves; - Trans pre_trans; -}; - -struct -step -{ - int (*f)(Cube); - bool (*ready)(Cube); -}; - -/* Public functions **********************************************************/ - -Cube apply_alg(Alg alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Center center_at(Cube cube, Center c); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -Corner corner_at(Cube cube, Corner c); -Edge edge_at(Cube cube, Edge e); -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_solved(Cube cube, bool reorient); -int piece_orientation(Cube cube, int piece, char *orientation); -void print_cube(Cube cube); -AlgList * solve(Cube cube, Step step, SolveOptions opts); - -void concat(Alg src1, Alg src2, Alg dest); -void copy_alg(Alg src, Alg dest); -void invert_alg(Alg src, Alg dest); -int len(Alg alg); -Alg new_alg(char *str); -void print_alg(Alg alg); -void remove_last_moves(Alg alg, int k); -void transform_alg(Trans t, Alg alg); - -void init(); diff --git a/old/2021-06-02-cleanedup/main.c b/old/2021-06-02-cleanedup/main.c @@ -1,35 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "steps.h" - -int main() { - Alg algo; - AlgList *sols; - Cube cube; - SolveOptions opts; - - init(); - - algo = new_alg("R U R' F"); - cube = apply_alg(algo, (Cube){0}); - - print_cube(apply_trans(rd, cube)); - - opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 5, - .optimal_only = true, - .max_solutions = 3, - .can_niss = false, - .moveset = standard_moveset, - .pre_trans = fu - }; - sols = solve(cube, step_eofb, opts); - if (sols->len == 0) - fprintf(stderr, "No solution found\n"); - else - print_alg(sols->first->alg); - - - return 0; -} diff --git a/old/2021-06-02-cleanedup/steps.h b/old/2021-06-02-cleanedup/steps.h @@ -1,22 +0,0 @@ -/* Pre-conditions, i.e. "ready(cube)" functions ******************************/ - -bool always_ready(Cube cube) { return true; } - -/* Main functions, i.e. "f(cube)" ********************************************/ - -int f_eofb(Cube cube) { return (cube.eofb != 0) ? 1 : 0; } - -/* Steps *********************************************************************/ - -Step step_eofb = { .f = f_eofb, .ready = always_ready }; - -/* Movesets ******************************************************************/ - -bool standard_moveset[NMOVES] = { - [U] = true, [U2] = true, [U3] = true, - [D] = true, [D2] = true, [D3] = true, - [R] = true, [R2] = true, [R3] = true, - [L] = true, [L2] = true, [L3] = true, - [F] = true, [F2] = true, [F3] = true, - [B] = true, [B2] = true, [B3] = true, -}; diff --git a/old/2021-06-14-oldalg/cube.c b/old/2021-06-14-oldalg/cube.c @@ -1,2849 +0,0 @@ -#include "cube.h" - -/* Constants and macros *****************************************************/ - -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define BASEALGLEN 50 -#define NMOVES (z3+1) -#define NTRANS (mirror+1) -#define NROTATIONS (NTRANS-1) -#define PTABLESIZE(n) ((n+1) / 2) -#define PTABLEVAL(tab,ind) (((ind)%2) ? (tab[(ind)/2] / 16) : \ - (tab[(ind)/2] % 16)) - - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static uint16_t array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static Move base_move(Move m); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent(int pos1, int pos2); -static uint16_t epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(uint16_t epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void generate_ptable(PruneData *pd); -static void generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void moveset_to_list(bool (*ms)(Move), int (*f)(Cube), Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static void ptable_set_reached(PruneData *pd, uint64_t ind); -static void ptable_update(PruneData *pd, uint64_t ind, int m); -static bool read_ptable_file(PruneData *pd); -static bool read_ttables_file(); -static bool read_mtables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static void solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_ptable_file(PruneData *pd); -static bool write_ttables_file(); -static bool write_mtables_file(); - -static void init_auxtables(); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_steps(); -static void init_strings(); -static void init_trans(); -static void init_trans_aux(); - -static bool moveset_HTM(Move m); -static bool moveset_URF(Move m); - -/* Steps and related functions and data **************************************/ - -Step eofb_HTM; -Step eorl_HTM; -Step eoud_HTM; -Step coud_HTM; -Step corl_HTM; -Step cofb_HTM; -Step coud_URF; -Step corl_URF; -Step cofb_URF; -Step corners_HTM; -Step corners_URF; -Step edges_HTM; -Step drud_HTM; -Step optimal_HTM; - -PruneData pd_eofb_HTM; -PruneData pd_coud_HTM; -PruneData pd_corners_HTM; -PruneData pd_ep_HTM; -PruneData pd_drud_HTM; - -static uint64_t index_eofb(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_ep(Cube cube); -static uint64_t index_drud(Cube cube); - -static int check_nothing(Cube cube); -static int check_eofb_HTM(Cube cube); -static int check_coud_HTM(Cube cube); -static int check_coud_URF(Cube cube); -static int check_corners_HTM(Cube cube); -static int check_corners_URF(Cube cube); -static int check_edges_HTM(Cube cube); -static int check_drud_HTM(Cube cube); -static int check_optimal_HTM(Cube cube); - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; - -static uint16_t epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eo_ttable[NTRANS][POW2TO11]; -static uint16_t cp_ttable[NTRANS][FACTORIAL8]; -static uint16_t co_ttable[NTRANS][POW3TO7]; -static uint16_t cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static uint16_t epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eofb_mtable[NMOVES][POW2TO11]; -static uint16_t eorl_mtable[NMOVES][POW2TO11]; -static uint16_t eoud_mtable[NMOVES][POW2TO11]; -static uint16_t cp_mtable[NMOVES][FACTORIAL8]; -static uint16_t coud_mtable[NMOVES][POW3TO7]; -static uint16_t cofb_mtable[NMOVES][POW3TO7]; -static uint16_t corl_mtable[NMOVES][POW3TO7]; -static uint16_t cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * trans_algs[NROTATIONS]; - - -/* Local functions implementation ********************************************/ - -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static void -append_alg(AlgList *l, Alg *alg) -{ - AlgListNode *node = malloc(sizeof(AlgListNode)); - AlgNode *i; - - node->alg = new_alg(""); - for (i = alg->first; i != NULL; i = i->next) - append_move(node->alg, i->m, i->inverse); - node->next = NULL; - - if (++l->len == 1) - l->first = node; - else - l->last->next = node; - l->last = node; -} - -static void -append_move(Alg *alg, Move m, bool inverse) -{ - AlgNode *node = malloc(sizeof(AlgNode)); - - node->m = m; - node->inverse = inverse; - node->next = NULL; - node->prev = alg->last; - - if (++alg->len == 1) - alg->first = node; - else - alg->last->next = node; - alg->last = node; -} - -static Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - AlgNode *i; - - for (i = alg->first; i != NULL; i = i->next) - if (i->inverse) - ret = a ? apply_move(i->m, ret) : - apply_move_cubearray(i->m, ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = alg->first; i != NULL; i = i->next) - if (!i->inverse) - ret = a ? apply_move(i->m, ret) : - apply_move_cubearray(i->m, ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static uint16_t -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 1) - ep8[j++] = (edge_slice(ep[i]) == 0) ? 1 : 0; - - return subset_to_index(ep8, 8, 4); -} - -static uint16_t -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(uint16_t epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -void -free_alg(Alg *alg) -{ - AlgNode *aux, *i = alg->first; - - while (i != NULL) { - aux = i->next; - free(i); - i = aux; - } - 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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -generate_ptable(PruneData *pd) -{ - uint64_t j; - DfsData dd; - - if (pd->generated) - return; - - pd->ptable = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - dd.m = 0; - dd.last1 = NULLMOVE; - dd.last2 = NULLMOVE; - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->size; j++) - ptable_update(pd, j, 15); - - moveset_to_list(pd->moveset, NULL, dd.sorted_moves); - - pd->reached = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); - for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { - memset(pd->reached, 0, PTABLESIZE(pd->size)*sizeof(uint8_t)); - generate_ptable_dfs((Cube){0}, pd, &dd); - fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", - dd.d, pd->n, pd->size); - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; - free(pd->reached); -} - -static void -generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd) -{ - uint64_t ind = pd->index(c); - int oldval = PTABLEVAL(pd->ptable, ind); - Move i, move, l1 = dd->last1, l2 = dd->last2; - - if (oldval < dd->m || PTABLEVAL(pd->reached, ind) || pd->n == pd->size) - return; - - ptable_set_reached(pd, ind); - - if (dd->m == dd->d) { - if (dd->m < oldval) - ptable_update(pd, ind, dd->m); - return; - } - - dd->m++; - dd->last2 = dd->last1; - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (possible_next[l2][l1][move]) { - dd->last1 = move; - generate_ptable_dfs(apply_move(move, c), pd, dd); - } - } - - dd->m--; - dd->last1 = l1; - dd->last2 = l2; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -moveset_to_list(bool (*ms)(Move m), int (*f)(Cube), Move *r) -{ - Cube c; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - c = apply_move(i, (Cube){0}); - if (f != NULL && f(c)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; /* Truncate */ - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static void -ptable_set_reached(PruneData *pd, uint64_t ind) -{ - uint8_t oldval2 = pd->reached[ind/2]; - int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; - - pd->reached[ind/2] = ind % 2 ? 16 + other : 16*other + 1; -} - -static void -ptable_update(PruneData *pd, uint64_t ind, int n) -{ - uint8_t oldval2 = pd->ptable[ind/2]; - int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = ind % 2 ? 16*n + other : 16*other + n; - pd->n++; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(uint16_t); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); - fclose(f); - - return r == PTABLESIZE(pd->size); -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(uint16_t); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - Alg *inv; - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Cube ret; - - if (r != mirror) { - ret = apply_alg_generic(trans_algs[r], c, f, true); - inv = on_inverse(trans_algs[r]); - ret = apply_alg_generic(inv, ret, f, true); - free_alg(inv); - } else { - ret = move_via_arrays(&ma, (Cube){0}, f); - ret = compose_filtered(c, ret, f); - ret = move_via_arrays(&ma, ret, f); - } - - return ret; -} - -static void -solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move move, l1 = dd->last1, l2 = dd->last2; - int i, lower_bound = s.check(c); - bool found_many, prune, niss_make_sense, nissbackup = dd->niss; - - if (opts->can_niss && !dd->niss) - lower_bound = MIN(1, lower_bound); - - found_many = dd->sols->len >= opts->max_solutions; - prune = dd->current_alg->len + lower_bound > dd->d; - if (found_many || prune) - return; - - if (!lower_bound) { /* solved */ - if (dd->current_alg->len == dd->d) - append_alg(dd->sols, dd->current_alg); - return; - } - - dd->last2 = dd->last1; - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (possible_next[l2][l1][move]) { - dd->last1 = move; - append_move(dd->current_alg, move, dd->niss); - solve_dfs(apply_move(move, c), s, opts, dd); - remove_last_move(dd->current_alg); - } - } - - niss_make_sense = !dd->current_alg->len || - (s.check(apply_move(l1,(Cube){0}))); - if (opts->can_niss && !dd->niss && niss_make_sense) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - solve_dfs(inverse_cube(c), s, opts, dd); - } - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = nissbackup; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(uint16_t); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); - fclose(f); - - return written == PTABLESIZE(pd->size); -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(uint16_t); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - uint64_t ui, uj; - int i, j, k; - bool cij, p1, p2; - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj] = epos_dependent(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2); - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[mirror] = mirror; -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - uint16_t ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray){ - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_steps() -{ - /* PruneData */ - pd_eofb_HTM.filename = "ptable_eofb_HTM"; - pd_eofb_HTM.size = POW2TO11; - pd_eofb_HTM.index = index_eofb; - pd_eofb_HTM.moveset = moveset_HTM; - - pd_coud_HTM.filename = "ptable_coud_HTM"; - pd_coud_HTM.size = POW3TO7; - pd_coud_HTM.index = index_coud; - pd_coud_HTM.moveset = moveset_HTM; - - pd_corners_HTM.filename = "ptable_corners_HTM"; - pd_corners_HTM.size = POW3TO7 * FACTORIAL8; - pd_corners_HTM.index = index_corners; - pd_corners_HTM.moveset = moveset_HTM; - - pd_ep_HTM.filename = "ptable_ep_HTM"; - pd_ep_HTM.size = FACTORIAL12; - pd_ep_HTM.index = index_ep; - pd_ep_HTM.moveset = moveset_HTM; - - pd_drud_HTM.filename = "ptable_drud_HTM"; - pd_drud_HTM.size = POW2TO11 * POW3TO7 * BINOM12ON4; - pd_drud_HTM.index = index_drud; - pd_drud_HTM.moveset = moveset_HTM; - - - /* Actual steps */ - eofb_HTM.check = check_eofb_HTM; - eofb_HTM.ready = check_nothing; - eofb_HTM.pre_trans = uf; - eofb_HTM.moveset = moveset_HTM; - - eorl_HTM.check = check_eofb_HTM; - eorl_HTM.ready = check_nothing; - eorl_HTM.pre_trans = ur; - eorl_HTM.moveset = moveset_HTM; - - eoud_HTM.check = check_eofb_HTM; - eoud_HTM.ready = check_nothing; - eoud_HTM.pre_trans = bu; - eoud_HTM.moveset = moveset_HTM; - - - coud_HTM.check = check_coud_HTM; - coud_HTM.ready = check_nothing; - coud_HTM.pre_trans = uf; - coud_HTM.moveset = moveset_HTM; - - corl_HTM.check = check_coud_HTM; - corl_HTM.ready = check_nothing; - corl_HTM.pre_trans = rf; - corl_HTM.moveset = moveset_HTM; - - cofb_HTM.check = check_coud_HTM; - cofb_HTM.ready = check_nothing; - cofb_HTM.pre_trans = fd; - cofb_HTM.moveset = moveset_HTM; - - coud_URF.check = check_coud_URF; - coud_URF.ready = check_nothing; - coud_URF.pre_trans = uf; - coud_URF.moveset = moveset_URF; - - corl_URF.check = check_coud_URF; - corl_URF.ready = check_nothing; - corl_URF.pre_trans = rf; - corl_URF.moveset = moveset_URF; - - cofb_URF.check = check_coud_URF; - cofb_URF.ready = check_nothing; - cofb_URF.pre_trans = fd; - cofb_URF.moveset = moveset_URF; - - corners_HTM.check = check_corners_HTM; - corners_HTM.ready = check_nothing; - corners_HTM.pre_trans = uf; - corners_HTM.moveset = moveset_HTM; - - corners_URF.check = check_corners_URF; - corners_URF.ready = check_nothing; - corners_URF.pre_trans = uf; - corners_URF.moveset = moveset_URF; - - edges_HTM.check = check_edges_HTM; - edges_HTM.ready = check_nothing; - edges_HTM.pre_trans = uf; - edges_HTM.moveset = moveset_HTM; - - drud_HTM.check = check_drud_HTM; - drud_HTM.ready = check_nothing; - drud_HTM.pre_trans = uf; - drud_HTM.moveset = moveset_HTM; - - optimal_HTM.check = check_optimal_HTM; - optimal_HTM.ready = check_nothing; - optimal_HTM.pre_trans = uf; - optimal_HTM.moveset = moveset_HTM; -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_trans() { - Cube aux, cube, c[3]; - CubeArray epcp; - int eparr[12], eoarr[12]; - int cparr[8], coarr[8]; - int i; - bool b1, b2, b3; - uint16_t ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - if (i == mirror) - cube = (Cube){0}; - else - cube = apply_alg(trans_algs[i], (Cube){0}); - - epose_source[i] = edge_slice(edge_at(cube, FR)); - eposs_source[i] = edge_slice(edge_at(cube, UR)); - eposm_source[i] = edge_slice(edge_at(cube, UF)); - eofb_source[i] = center_at(cube, F_center)/2; - eorl_source[i] = center_at(cube, R_center)/2; - eoud_source[i] = center_at(cube, U_center)/2; - coud_source[i] = center_at(cube, U_center)/2; - cofb_source[i] = center_at(cube, F_center)/2; - corl_source[i] = center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - if (m == mirror) { - memcpy(eparr, ep_mirror, 12 * sizeof(int)); - memcpy(cparr, cp_mirror, 8 * sizeof(int)); - } else { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(trans_algs[m], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m == mirror) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - if (m == mirror) { - b1 = (mi >= U && mi <= Bw3); - b2 = (mi >= S && mi <= E3); - b3 = (mi >= x && mi <= z3); - if (b1 || b2 || b3) - moves_ttable[m][mi] = - inverse_move_aux[mi]; - else - moves_ttable[m][mi] = mi; - - if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) - moves_ttable[m][mi] += 3; - if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) - moves_ttable[m][mi] -= 3; - } else { - aux = apply_trans(m, apply_move(mi,(Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move( - inverse_move_aux[move], aux); - if (is_solved(cube, false)) - moves_ttable[m][mi] = move; - } - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - trans_algs[uf] = new_alg(""); - trans_algs[ur] = new_alg("y"); - trans_algs[ub] = new_alg("y2"); - trans_algs[ul] = new_alg("y3"); - - trans_algs[df] = new_alg("z2"); - trans_algs[dr] = new_alg("y z2"); - trans_algs[db] = new_alg("x2"); - trans_algs[dl] = new_alg("y3 z2"); - - trans_algs[rf] = new_alg("z3"); - trans_algs[rd] = new_alg("z3 y"); - trans_algs[rb] = new_alg("z3 y2"); - trans_algs[ru] = new_alg("z3 y3"); - - trans_algs[lf] = new_alg("z"); - trans_algs[ld] = new_alg("z y3"); - trans_algs[lb] = new_alg("z y2"); - trans_algs[lu] = new_alg("z y"); - - trans_algs[fu] = new_alg("x y2"); - trans_algs[fr] = new_alg("x y"); - trans_algs[fd] = new_alg("x"); - trans_algs[fl] = new_alg("x y3"); - - trans_algs[bu] = new_alg("x3"); - trans_algs[br] = new_alg("x3 y"); - trans_algs[bd] = new_alg("x3 y2"); - trans_algs[bl] = new_alg("x3 y3"); -} - -/* Linearization functions implementation ************************************/ - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_ep(Cube cube) -{ - uint64_t a, b, c; - - /* TODO: remove this check */ - if (epos_dependent_aux[cube.eposs/FACTORIAL4][cube.epose/FACTORIAL4] ==BINOM8ON4) - fprintf(stderr, "Impossible\n"); - - a = cube.eposs; - b = (cube.epose % FACTORIAL4) + - epos_dependent_aux[cube.eposs/FACTORIAL4][cube.epose/FACTORIAL4] * - FACTORIAL4; - c = cube.eposm % FACTORIAL4; - - b *= FACTORIAL4 * BINOM12ON4; - c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; - - return a + b + c; -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -/* Step checking functions implementation ************************************/ - -static int -check_nothing(Cube cube) -{ - return true; -} - -static int -check_eofb_HTM(Cube cube) -{ - if (!pd_eofb_HTM.generated) - generate_ptable(&pd_eofb_HTM); - - return PTABLEVAL(pd_eofb_HTM.ptable, cube.eofb); -} - -static int -check_coud_HTM(Cube cube) -{ - if (!pd_coud_HTM.generated) - generate_ptable(&pd_coud_HTM); - - return PTABLEVAL(pd_coud_HTM.ptable, cube.coud); -} - -static int -check_coud_URF(Cube cube) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - int ud = check_coud_HTM(cube); - int rl = check_coud_HTM(apply_move(z, cube)); - int fb = check_coud_HTM(apply_move(x, cube)); - - return MIN(ud, MIN(rl, fb)); -} - -static int -check_corners_HTM(Cube cube) -{ - if (!pd_corners_HTM.generated) - generate_ptable(&pd_corners_HTM); - - return PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); -} - -static int -check_corners_URF(Cube cube) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int ret = 15; - Cube c; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - c = apply_alg(trans_algs[i], cube); - ret = MIN(ret, check_corners_HTM(c)); - } - - return ret; -} - -static int -check_edges_HTM(Cube cube) -{ - int ret = 0; - - if (!pd_ep_HTM.generated) - generate_ptable(&pd_ep_HTM); - - ret = MAX(ret, PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube))); - ret = MAX(ret, check_eofb_HTM(cube)); - ret = MAX(ret, check_eofb_HTM(apply_trans(ur, cube))); - ret = MAX(ret, check_eofb_HTM(apply_trans(fd, cube))); - - return ret; -} - -static int -check_drud_HTM(Cube cube) -{ - if (!pd_drud_HTM.generated) - generate_ptable(&pd_drud_HTM); - - return PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); -} - -static int -check_optimal_HTM(Cube cube) -{ - int dr1, dr2, dr3, drmax, cor; /*ep;*/ - - if (!pd_drud_HTM.generated) - generate_ptable(&pd_drud_HTM); - if (!pd_corners_HTM.generated) - generate_ptable(&pd_corners_HTM); - /* - *if (!pd_ep_HTM.generated) - * generate_ptable(&pd_ep_HTM); - */ - - dr1 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); - dr2 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(rf, cube))); - dr3 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(fd, cube))); - - drmax = MAX(dr1, MAX(dr2, dr3)); - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - drmax++; - - cor = PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); - /* ep = PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube)); */ - - /*return MAX(drmax, MAX(ep, cor));*/ - if (drmax == 0 && cor == 0) - return is_solved(cube, false) ? 0 : 1; - return MAX(drmax, cor); -} - - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - Cube moved = {0}; - - moved.epose = epose_mtable[m][cube.epose]; - moved.eposs = eposs_mtable[m][cube.eposs]; - moved.eposm = eposm_mtable[m][cube.eposm]; - moved.eofb = eofb_mtable[m][cube.eofb]; - moved.eorl = eorl_mtable[m][cube.eorl]; - moved.eoud = eoud_mtable[m][cube.eoud]; - moved.coud = coud_mtable[m][cube.coud]; - moved.cofb = cofb_mtable[m][cube.cofb]; - moved.corl = corl_mtable[m][cube.corl]; - moved.cp = cp_mtable[m][cube.cp]; - moved.cpos = cpos_mtable[m][cube.cpos]; - - return moved; -} - -Cube -apply_trans(Trans t, Cube cube) -{ - Cube transformed = {0}; - uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - transformed.epose = epose_ttable[t][aux_epos[epose_source[t]]]; - transformed.eposs = eposs_ttable[t][aux_epos[eposs_source[t]]]; - transformed.eposm = eposm_ttable[t][aux_epos[eposm_source[t]]]; - transformed.eofb = eo_ttable[t][aux_eo[eofb_source[t]]]; - transformed.eorl = eo_ttable[t][aux_eo[eorl_source[t]]]; - transformed.eoud = eo_ttable[t][aux_eo[eoud_source[t]]]; - transformed.coud = co_ttable[t][aux_co[coud_source[t]]]; - transformed.corl = co_ttable[t][aux_co[corl_source[t]]]; - transformed.cofb = co_ttable[t][aux_co[cofb_source[t]]]; - transformed.cp = cp_ttable[t][cube.cp]; - transformed.cpos = cpos_ttable[t][cube.cpos]; - - return transformed; -} - -/* TODO: this has to be changed using pre-computations */ -bool -block_solved(Cube cube, Block block) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - int i; - bool ret = true; - - for (i = 0; i < 12; i++) - ret = ret && !(block.edge[i] && (arr->ep[i] != i || arr->eofb[i])); - for (i = 0; i < 8; i++) - ret = ret && !(block.corner[i] && (arr->cp[i] != i || arr->coud[i])); - for (i = 0; i < 6; i++) - ret = ret && !(block.center[i] && arr->cpos[i] != i); - - free_cubearray(arr, pf_all); - - return ret; -} - -Center -center_at(Cube cube, Center c) -{ - int ret; - CubeArray *arr = new_cubearray(cube, pf_cpos); - - ret = arr->cpos[c]; - free_cubearray(arr, pf_cpos); - - return ret; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -Corner -corner_at(Cube cube, Corner c) -{ - int ret; - CubeArray *arr = new_cubearray(cube, pf_cp); - - ret = arr->cp[c]; - free_cubearray(arr, pf_cp); - - return ret; -} - -Edge -edge_at(Cube cube, Edge e) -{ - int ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - free_cubearray(arr, pf_ep); - - return ret; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - Trans i; - - if (reorient) - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(trans_algs[i],cube), false)) - return true; - - return equal(cube, (Cube){0}); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b; - uint16_t x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - AlgListNode *node; - AlgList *sols = new_alglist(); - Cube c = apply_trans(step.pre_trans, cube); - DfsData dd = { - .m = 0, - .niss = false, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && !step.ready(c)) - return sols; - - moveset_to_list(step.moveset, step.check, dd.sorted_moves); - - for (dd.d = MAX(opts->min_moves, step.check(c)); - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - solve_dfs(c, step, opts, &dd); - if (opts->feedback) - fprintf(stderr, - "Depth %d completed, found %d solutions\n", - dd.d, sols->len); - } - - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans_aux[step.pre_trans], node->alg); - - return sols; -} - -Alg * -inverse_alg(Alg *alg) -{ - Alg *ret = new_alg(""); - AlgNode *i; - - for (i = alg->last; i != NULL; i = i->prev) - append_move(ret, i->m, i->inverse); - - return ret; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->first = NULL; - alg->last = NULL; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - AlgNode *i; - - for (i = alg->first; i != NULL; i = i->next) - append_move(ret, i->m, !i->inverse); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - char fill[4]; - AlgNode *i; - bool niss = false; - - for (i = alg->first; i != NULL; i = i->next) { - if (!niss && i->inverse) - strcpy(fill, i == alg->first ? "(" : " ("); - if (niss && !i->inverse) - strcpy(fill, ") "); - if (niss == i->inverse) - strcpy(fill, i == alg->first ? "" : " "); - - printf("%s%s", fill, move_string[i->m]); - niss = i->inverse; - } - - if (niss) - printf(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - memset(a, 0, 16 * sizeof(uint64_t)); - - if (!pd->generated) - generate_ptable(pd); - - for (i = 0; i < pd->size; i++) - a[PTABLEVAL(pd->ptable, i)]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -remove_last_move(Alg *alg) -{ - AlgNode *newlast = alg->last->prev; - free(alg->last); - if (newlast != NULL) - newlast->next = NULL; - alg->last = newlast; - alg->len--; -} - -void -transform_alg(Trans t, Alg *alg) -{ - AlgNode *i; - - for (i = alg->first; i != NULL; i = i->next) - i->m = moves_ttable[t][i->m]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_trans_aux(); - init_trans(); - init_steps(); -} - - diff --git a/old/2021-06-14-oldalg/cube.h b/old/2021-06-14-oldalg/cube.h @@ -1,73 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> -#include "cubetypes.h" - -/* Steps *********************************************************************/ - -extern Step eofb_HTM; -extern Step eorl_HTM; -extern Step eoud_HTM; -extern Step coud_HTM; -extern Step corl_HTM; -extern Step cofb_HTM; -extern Step coud_URF; -extern Step corl_URF; -extern Step cofb_URF; -extern Step corners_HTM; -extern Step corners_URF; -extern Step edges_HTM; -extern Step drud_HTM; -extern Step optimal_HTM; - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_ep_HTM; -extern PruneData pd_drud_HTM; - -/* Public functions **********************************************************/ - -Cube apply_alg(Alg *alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Center center_at(Cube cube, Center c); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -Corner corner_at(Cube cube, Corner c); -Edge edge_at(Cube cube, Edge e); -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_admissible(Cube cube); -bool is_solved(Cube cube, bool reorient); -int piece_orientation(Cube cube, int piece, char *orientation); -void print_cube(Cube cube); -Cube random_cube(); -AlgList * solve(Cube cube, Step step, SolveOptions *opts); - -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Alg * new_alg(char *str); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); -void remove_last_move(Alg *alg); -void transform_alg(Trans t, Alg *alg); - -void print_ptable(PruneData *pd); - -void init(); - -#endif - diff --git a/old/2021-06-14-oldalg/cubetypes.h b/old/2021-06-14-oldalg/cubetypes.h @@ -1,210 +0,0 @@ -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct algnode AlgNode; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct block Block; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - mirror, /* R|L */ -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - AlgNode * first; - AlgNode * last; - int len; -}; - -struct -algnode -{ - Move m; - bool inverse; - AlgNode * next; - AlgNode * prev; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -cube -{ - uint16_t epose; - uint16_t eposs; - uint16_t eposm; - uint16_t eofb; - uint16_t eorl; - uint16_t eoud; - uint16_t cp; - uint16_t coud; - uint16_t cofb; - uint16_t corl; - uint16_t cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -dfsdata -{ - int d; - int m; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[z3+1]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - uint8_t * reached; - bool generated; - uint64_t n; - uint64_t size; - uint64_t (*index)(Cube); - bool (*moveset)(Move); -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; -}; - -struct -step -{ - int (*check)(Cube); - int (*ready)(Cube); - bool (*moveset)(Move); - Trans pre_trans; -}; diff --git a/old/2021-06-14-oldalg/main.c b/old/2021-06-14-oldalg/main.c @@ -1,56 +0,0 @@ -#include <stdio.h> -#include "cube.h" - -int main() { - Alg *algo; - AlgList *sols; - Cube cube; - SolveOptions opts; - char line[1000]; - int i, ns = 2, nrand = 100000, sum; - - Step *stps[20] = {&drud_HTM, &optimal_HTM}; - char sss[30][30] = {"DR on U/D", "Optimal solution"}; - - opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 20, - .optimal_only = true, - .max_solutions = 1, - .can_niss = false, - .feedback = true - }; - - init(); - -/* - print_ptable(&pd_drud_HTM); - print_ptable(&pd_ep_HTM); - print_ptable(&pd_corners_HTM); -*/ - - srand(time(NULL)); - sum = 0; - for (i = 0; i < nrand; i++) - sum += optimal_HTM.check(random_cube()); - printf("Average pruning value: %lf\n", ((double)sum) / ((double) nrand)); - - printf("Welcome to nissy 2.0! Insert a scramble:\n"); - - if (fgets(line, 1000, stdin) != NULL) { - algo = new_alg(line); - cube = apply_alg(algo, (Cube){0}); - - for (i = 0; i < ns; i++) { - if (stps[i]->check == NULL) - fprintf(stderr, "Check function for step %d is null\n", i); - sols = solve(cube, *stps[i], &opts); - printf("%s: %d solutions found:\n", sss[i], sols->len); - print_alglist(sols, true); - free_alglist(sols); - } - free(algo); - } - - return 0; -} diff --git a/old/2021-06-15-before-separating-steps/cube.c b/old/2021-06-15-before-separating-steps/cube.c @@ -1,2836 +0,0 @@ -#include "cube.h" - -/* Constants and macros *****************************************************/ - -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define BASEALGLEN 50 -#define NMOVES (z3+1) -#define NTRANS (mirror+1) -#define NROTATIONS (NTRANS-1) -#define PTABLESIZE(n) ((n+1) / 2) -#define PTABLEVAL(tab,ind) (((ind)%2) ? (tab[(ind)/2] / 16) : \ - (tab[(ind)/2] % 16)) - - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static uint16_t array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static Move base_move(Move m); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent(int pos1, int pos2); -static uint16_t epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(uint16_t epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void generate_ptable(PruneData *pd); -static void generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void moveset_to_list(bool (*ms)(Move), int (*f)(Cube), Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static void ptable_set_reached(PruneData *pd, uint64_t ind); -static void ptable_update(PruneData *pd, uint64_t ind, int m); -static bool read_ptable_file(PruneData *pd); -static bool read_ttables_file(); -static bool read_mtables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static void solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_ptable_file(PruneData *pd); -static bool write_ttables_file(); -static bool write_mtables_file(); - -static void init_auxtables(); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_steps(); -static void init_strings(); -static void init_trans(); -static void init_trans_aux(); - -static bool moveset_HTM(Move m); -static bool moveset_URF(Move m); - -/* Steps and related functions and data **************************************/ - -Step eofb_HTM; -Step eorl_HTM; -Step eoud_HTM; -Step coud_HTM; -Step corl_HTM; -Step cofb_HTM; -Step coud_URF; -Step corl_URF; -Step cofb_URF; -Step corners_HTM; -Step corners_URF; -Step edges_HTM; -Step drud_HTM; -Step optimal_HTM; - -PruneData pd_eofb_HTM; -PruneData pd_coud_HTM; -PruneData pd_corners_HTM; -PruneData pd_ep_HTM; -PruneData pd_drud_HTM; - -static uint64_t index_eofb(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_ep(Cube cube); -static uint64_t index_drud(Cube cube); - -static int check_nothing(Cube cube); -static int check_eofb_HTM(Cube cube); -static int check_coud_HTM(Cube cube); -static int check_coud_URF(Cube cube); -static int check_corners_HTM(Cube cube); -static int check_corners_URF(Cube cube); -static int check_edges_HTM(Cube cube); -static int check_drud_HTM(Cube cube); -static int check_optimal_HTM(Cube cube); - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; - -static uint16_t epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eo_ttable[NTRANS][POW2TO11]; -static uint16_t cp_ttable[NTRANS][FACTORIAL8]; -static uint16_t co_ttable[NTRANS][POW3TO7]; -static uint16_t cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static uint16_t epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eofb_mtable[NMOVES][POW2TO11]; -static uint16_t eorl_mtable[NMOVES][POW2TO11]; -static uint16_t eoud_mtable[NMOVES][POW2TO11]; -static uint16_t cp_mtable[NMOVES][FACTORIAL8]; -static uint16_t coud_mtable[NMOVES][POW3TO7]; -static uint16_t cofb_mtable[NMOVES][POW3TO7]; -static uint16_t corl_mtable[NMOVES][POW3TO7]; -static uint16_t cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * trans_algs[NROTATIONS]; - - -/* Local functions implementation ********************************************/ - -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static 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; -} - -static void -append_move(Alg *alg, Move m, bool inverse) -{ - if (alg->len == alg->allocated) { - if (alg->len > 1000000) { - fprintf(stderr, "Warning: very long alg,"); - fprintf(stderr, "something might be wrong.\n"); - } - alg->move = realloc(alg->move, 2 * alg->len * sizeof(Move)); - alg->inv = realloc(alg->inv, 2 * alg->len * sizeof(bool)); - alg->allocated *= 2; - } - - alg->move[alg->len] = m; - alg->inv [alg->len] = inverse; - alg->len++; -} - -static Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static uint16_t -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 1) - ep8[j++] = (edge_slice(ep[i]) == 0) ? 1 : 0; - - return subset_to_index(ep8, 8, 4); -} - -static uint16_t -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(uint16_t epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -generate_ptable(PruneData *pd) -{ - uint64_t j; - DfsData dd; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - pd->ptable = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - dd.m = 0; - dd.last1 = NULLMOVE; - dd.last2 = NULLMOVE; - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->size; j++) - ptable_update(pd, j, 15); - - moveset_to_list(pd->moveset, NULL, dd.sorted_moves); - - pd->reached = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); - for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { - memset(pd->reached, 0, PTABLESIZE(pd->size)*sizeof(uint8_t)); - generate_ptable_dfs((Cube){0}, pd, &dd); - fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", - dd.d, pd->n, pd->size); - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; - free(pd->reached); -} - -static void -generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd) -{ - uint64_t ind = pd->index(c); - int oldval = PTABLEVAL(pd->ptable, ind); - Move i, move, l1 = dd->last1, l2 = dd->last2; - - if (oldval < dd->m || PTABLEVAL(pd->reached, ind) || pd->n == pd->size) - return; - - ptable_set_reached(pd, ind); - - if (dd->m == dd->d) { - if (dd->m < oldval) - ptable_update(pd, ind, dd->m); - return; - } - - dd->m++; - dd->last2 = dd->last1; - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (possible_next[l2][l1][move]) { - dd->last1 = move; - generate_ptable_dfs(apply_move(move, c), pd, dd); - } - } - - dd->m--; - dd->last1 = l1; - dd->last2 = l2; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -moveset_to_list(bool (*ms)(Move m), int (*f)(Cube), Move *r) -{ - Cube c; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - c = apply_move(i, (Cube){0}); - if (f != NULL && f(c)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; /* Truncate */ - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static void -ptable_set_reached(PruneData *pd, uint64_t ind) -{ - uint8_t oldval2 = pd->reached[ind/2]; - int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; - - pd->reached[ind/2] = ind % 2 ? 16 + other : 16*other + 1; -} - -static void -ptable_update(PruneData *pd, uint64_t ind, int n) -{ - uint8_t oldval2 = pd->ptable[ind/2]; - int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = ind % 2 ? 16*n + other : 16*other + n; - pd->n++; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(uint16_t); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); - fclose(f); - - return r == PTABLESIZE(pd->size); -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(uint16_t); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - Alg *inv; - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Cube ret; - - if (r != mirror) { - ret = apply_alg_generic(trans_algs[r], c, f, true); - inv = on_inverse(trans_algs[r]); - ret = apply_alg_generic(inv, ret, f, true); - free_alg(inv); - } else { - ret = move_via_arrays(&ma, (Cube){0}, f); - ret = compose_filtered(c, ret, f); - ret = move_via_arrays(&ma, ret, f); - } - - return ret; -} - -static void -solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move move, l1 = dd->last1, l2 = dd->last2; - int i, lower_bound = s.check(c); - bool found_many, prune, niss_make_sense, nissbackup = dd->niss; - - if (opts->can_niss && !dd->niss) - lower_bound = MIN(1, lower_bound); - - found_many = dd->sols->len >= opts->max_solutions; - prune = dd->current_alg->len + lower_bound > dd->d; - if (found_many || prune) - return; - - if (lower_bound == 0) { - if (dd->current_alg->len == dd->d) - append_alg(dd->sols, dd->current_alg); - return; - } - - dd->last2 = dd->last1; - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (possible_next[l2][l1][move]) { - dd->last1 = move; - append_move(dd->current_alg, move, dd->niss); - solve_dfs(apply_move(move, c), s, opts, dd); - dd->current_alg->len--; - } - } - - niss_make_sense = !dd->current_alg->len || - (s.check(apply_move(l1,(Cube){0}))); - if (opts->can_niss && !dd->niss && niss_make_sense) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - solve_dfs(inverse_cube(c), s, opts, dd); - } - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = nissbackup; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(uint16_t); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); - fclose(f); - - return written == PTABLESIZE(pd->size); -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(uint16_t); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - uint64_t ui, uj; - int i, j, k; - bool cij, p1, p2; - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj] = epos_dependent(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2); - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[mirror] = mirror; -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - uint16_t ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray){ - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_steps() -{ - /* PruneData */ - pd_eofb_HTM.filename = "ptable_eofb_HTM"; - pd_eofb_HTM.size = POW2TO11; - pd_eofb_HTM.index = index_eofb; - pd_eofb_HTM.moveset = moveset_HTM; - - pd_coud_HTM.filename = "ptable_coud_HTM"; - pd_coud_HTM.size = POW3TO7; - pd_coud_HTM.index = index_coud; - pd_coud_HTM.moveset = moveset_HTM; - - pd_corners_HTM.filename = "ptable_corners_HTM"; - pd_corners_HTM.size = POW3TO7 * FACTORIAL8; - pd_corners_HTM.index = index_corners; - pd_corners_HTM.moveset = moveset_HTM; - - pd_ep_HTM.filename = "ptable_ep_HTM"; - pd_ep_HTM.size = FACTORIAL12; - pd_ep_HTM.index = index_ep; - pd_ep_HTM.moveset = moveset_HTM; - - pd_drud_HTM.filename = "ptable_drud_HTM"; - pd_drud_HTM.size = POW2TO11 * POW3TO7 * BINOM12ON4; - pd_drud_HTM.index = index_drud; - pd_drud_HTM.moveset = moveset_HTM; - - - /* Actual steps */ - eofb_HTM.check = check_eofb_HTM; - eofb_HTM.ready = check_nothing; - eofb_HTM.pre_trans = uf; - eofb_HTM.moveset = moveset_HTM; - - eorl_HTM.check = check_eofb_HTM; - eorl_HTM.ready = check_nothing; - eorl_HTM.pre_trans = ur; - eorl_HTM.moveset = moveset_HTM; - - eoud_HTM.check = check_eofb_HTM; - eoud_HTM.ready = check_nothing; - eoud_HTM.pre_trans = bu; - eoud_HTM.moveset = moveset_HTM; - - - coud_HTM.check = check_coud_HTM; - coud_HTM.ready = check_nothing; - coud_HTM.pre_trans = uf; - coud_HTM.moveset = moveset_HTM; - - corl_HTM.check = check_coud_HTM; - corl_HTM.ready = check_nothing; - corl_HTM.pre_trans = rf; - corl_HTM.moveset = moveset_HTM; - - cofb_HTM.check = check_coud_HTM; - cofb_HTM.ready = check_nothing; - cofb_HTM.pre_trans = fd; - cofb_HTM.moveset = moveset_HTM; - - coud_URF.check = check_coud_URF; - coud_URF.ready = check_nothing; - coud_URF.pre_trans = uf; - coud_URF.moveset = moveset_URF; - - corl_URF.check = check_coud_URF; - corl_URF.ready = check_nothing; - corl_URF.pre_trans = rf; - corl_URF.moveset = moveset_URF; - - cofb_URF.check = check_coud_URF; - cofb_URF.ready = check_nothing; - cofb_URF.pre_trans = fd; - cofb_URF.moveset = moveset_URF; - - corners_HTM.check = check_corners_HTM; - corners_HTM.ready = check_nothing; - corners_HTM.pre_trans = uf; - corners_HTM.moveset = moveset_HTM; - - corners_URF.check = check_corners_URF; - corners_URF.ready = check_nothing; - corners_URF.pre_trans = uf; - corners_URF.moveset = moveset_URF; - - edges_HTM.check = check_edges_HTM; - edges_HTM.ready = check_nothing; - edges_HTM.pre_trans = uf; - edges_HTM.moveset = moveset_HTM; - - drud_HTM.check = check_drud_HTM; - drud_HTM.ready = check_nothing; - drud_HTM.pre_trans = uf; - drud_HTM.moveset = moveset_HTM; - - optimal_HTM.check = check_optimal_HTM; - optimal_HTM.ready = check_nothing; - optimal_HTM.pre_trans = uf; - optimal_HTM.moveset = moveset_HTM; -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_trans() { - Cube aux, cube, c[3]; - CubeArray epcp; - int eparr[12], eoarr[12]; - int cparr[8], coarr[8]; - int i; - bool b1, b2, b3; - uint16_t ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - if (i == mirror) - cube = (Cube){0}; - else - cube = apply_alg(trans_algs[i], (Cube){0}); - - epose_source[i] = edge_slice(edge_at(cube, FR)); - eposs_source[i] = edge_slice(edge_at(cube, UR)); - eposm_source[i] = edge_slice(edge_at(cube, UF)); - eofb_source[i] = center_at(cube, F_center)/2; - eorl_source[i] = center_at(cube, R_center)/2; - eoud_source[i] = center_at(cube, U_center)/2; - coud_source[i] = center_at(cube, U_center)/2; - cofb_source[i] = center_at(cube, F_center)/2; - corl_source[i] = center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - if (m == mirror) { - memcpy(eparr, ep_mirror, 12 * sizeof(int)); - memcpy(cparr, cp_mirror, 8 * sizeof(int)); - } else { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(trans_algs[m], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m == mirror) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - if (m == mirror) { - b1 = (mi >= U && mi <= Bw3); - b2 = (mi >= S && mi <= E3); - b3 = (mi >= x && mi <= z3); - if (b1 || b2 || b3) - moves_ttable[m][mi] = - inverse_move_aux[mi]; - else - moves_ttable[m][mi] = mi; - - if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) - moves_ttable[m][mi] += 3; - if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) - moves_ttable[m][mi] -= 3; - } else { - aux = apply_trans(m, apply_move(mi,(Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move( - inverse_move_aux[move], aux); - if (is_solved(cube, false)) - moves_ttable[m][mi] = move; - } - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - trans_algs[uf] = new_alg(""); - trans_algs[ur] = new_alg("y"); - trans_algs[ub] = new_alg("y2"); - trans_algs[ul] = new_alg("y3"); - - trans_algs[df] = new_alg("z2"); - trans_algs[dr] = new_alg("y z2"); - trans_algs[db] = new_alg("x2"); - trans_algs[dl] = new_alg("y3 z2"); - - trans_algs[rf] = new_alg("z3"); - trans_algs[rd] = new_alg("z3 y"); - trans_algs[rb] = new_alg("z3 y2"); - trans_algs[ru] = new_alg("z3 y3"); - - trans_algs[lf] = new_alg("z"); - trans_algs[ld] = new_alg("z y3"); - trans_algs[lb] = new_alg("z y2"); - trans_algs[lu] = new_alg("z y"); - - trans_algs[fu] = new_alg("x y2"); - trans_algs[fr] = new_alg("x y"); - trans_algs[fd] = new_alg("x"); - trans_algs[fl] = new_alg("x y3"); - - trans_algs[bu] = new_alg("x3"); - trans_algs[br] = new_alg("x3 y"); - trans_algs[bd] = new_alg("x3 y2"); - trans_algs[bl] = new_alg("x3 y3"); -} - -/* Linearization functions implementation ************************************/ - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_ep(Cube cube) -{ - uint64_t a, b, c; - - /* TODO: remove this check */ - if (epos_dependent_aux[cube.eposs/FACTORIAL4][cube.epose/FACTORIAL4] ==BINOM8ON4) - fprintf(stderr, "Impossible\n"); - - a = cube.eposs; - b = (cube.epose % FACTORIAL4) + - epos_dependent_aux[cube.eposs/FACTORIAL4][cube.epose/FACTORIAL4] * - FACTORIAL4; - c = cube.eposm % FACTORIAL4; - - b *= FACTORIAL4 * BINOM12ON4; - c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; - - return a + b + c; -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -/* Step checking functions implementation ************************************/ - -static int -check_nothing(Cube cube) -{ - return true; -} - -static int -check_eofb_HTM(Cube cube) -{ - if (!pd_eofb_HTM.generated) - generate_ptable(&pd_eofb_HTM); - - return PTABLEVAL(pd_eofb_HTM.ptable, cube.eofb); -} - -static int -check_coud_HTM(Cube cube) -{ - if (!pd_coud_HTM.generated) - generate_ptable(&pd_coud_HTM); - - return PTABLEVAL(pd_coud_HTM.ptable, cube.coud); -} - -static int -check_coud_URF(Cube cube) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - int ud = check_coud_HTM(cube); - int rl = check_coud_HTM(apply_move(z, cube)); - int fb = check_coud_HTM(apply_move(x, cube)); - - return MIN(ud, MIN(rl, fb)); -} - -static int -check_corners_HTM(Cube cube) -{ - if (!pd_corners_HTM.generated) - generate_ptable(&pd_corners_HTM); - - return PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); -} - -static int -check_corners_URF(Cube cube) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int ret = 15; - Cube c; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - c = apply_alg(trans_algs[i], cube); - ret = MIN(ret, check_corners_HTM(c)); - } - - return ret; -} - -static int -check_edges_HTM(Cube cube) -{ - int ret = 0; - - if (!pd_ep_HTM.generated) - generate_ptable(&pd_ep_HTM); - - ret = MAX(ret, PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube))); - ret = MAX(ret, check_eofb_HTM(cube)); - ret = MAX(ret, check_eofb_HTM(apply_trans(ur, cube))); - ret = MAX(ret, check_eofb_HTM(apply_trans(fd, cube))); - - return ret; -} - -static int -check_drud_HTM(Cube cube) -{ - if (!pd_drud_HTM.generated) - generate_ptable(&pd_drud_HTM); - - return PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); -} - -static int -check_optimal_HTM(Cube cube) -{ - int dr1, dr2, dr3, drmax, cor; /*ep;*/ - - if (!pd_drud_HTM.generated) - generate_ptable(&pd_drud_HTM); - if (!pd_corners_HTM.generated) - generate_ptable(&pd_corners_HTM); - /* - *if (!pd_ep_HTM.generated) - * generate_ptable(&pd_ep_HTM); - */ - - dr1 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); - dr2 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(rf, cube))); - dr3 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(fd, cube))); - - drmax = MAX(dr1, MAX(dr2, dr3)); - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - drmax++; - - cor = PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); - /* ep = PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube)); */ - - /*return MAX(drmax, MAX(ep, cor));*/ - if (drmax == 0 && cor == 0) - return is_solved(cube, false) ? 0 : 1; - return MAX(drmax, cor); -} - - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - Cube moved = {0}; - - moved.epose = epose_mtable[m][cube.epose]; - moved.eposs = eposs_mtable[m][cube.eposs]; - moved.eposm = eposm_mtable[m][cube.eposm]; - moved.eofb = eofb_mtable[m][cube.eofb]; - moved.eorl = eorl_mtable[m][cube.eorl]; - moved.eoud = eoud_mtable[m][cube.eoud]; - moved.coud = coud_mtable[m][cube.coud]; - moved.cofb = cofb_mtable[m][cube.cofb]; - moved.corl = corl_mtable[m][cube.corl]; - moved.cp = cp_mtable[m][cube.cp]; - moved.cpos = cpos_mtable[m][cube.cpos]; - - return moved; -} - -Cube -apply_trans(Trans t, Cube cube) -{ - Cube transformed = {0}; - uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - transformed.epose = epose_ttable[t][aux_epos[epose_source[t]]]; - transformed.eposs = eposs_ttable[t][aux_epos[eposs_source[t]]]; - transformed.eposm = eposm_ttable[t][aux_epos[eposm_source[t]]]; - transformed.eofb = eo_ttable[t][aux_eo[eofb_source[t]]]; - transformed.eorl = eo_ttable[t][aux_eo[eorl_source[t]]]; - transformed.eoud = eo_ttable[t][aux_eo[eoud_source[t]]]; - transformed.coud = co_ttable[t][aux_co[coud_source[t]]]; - transformed.corl = co_ttable[t][aux_co[corl_source[t]]]; - transformed.cofb = co_ttable[t][aux_co[cofb_source[t]]]; - transformed.cp = cp_ttable[t][cube.cp]; - transformed.cpos = cpos_ttable[t][cube.cpos]; - - return transformed; -} - -/* TODO: this has to be changed using pre-computations */ -bool -block_solved(Cube cube, Block block) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - int i; - bool ret = true; - - for (i = 0; i < 12; i++) - ret = ret && !(block.edge[i] && (arr->ep[i] != i || arr->eofb[i])); - for (i = 0; i < 8; i++) - ret = ret && !(block.corner[i] && (arr->cp[i] != i || arr->coud[i])); - for (i = 0; i < 6; i++) - ret = ret && !(block.center[i] && arr->cpos[i] != i); - - free_cubearray(arr, pf_all); - - return ret; -} - -Center -center_at(Cube cube, Center c) -{ - int ret; - CubeArray *arr = new_cubearray(cube, pf_cpos); - - ret = arr->cpos[c]; - free_cubearray(arr, pf_cpos); - - return ret; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -Corner -corner_at(Cube cube, Corner c) -{ - int ret; - CubeArray *arr = new_cubearray(cube, pf_cp); - - ret = arr->cp[c]; - free_cubearray(arr, pf_cp); - - return ret; -} - -Edge -edge_at(Cube cube, Edge e) -{ - int ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - free_cubearray(arr, pf_ep); - - return ret; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - Trans i; - - if (reorient) - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(trans_algs[i],cube), false)) - return true; - - return equal(cube, (Cube){0}); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b; - uint16_t x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - AlgListNode *node; - AlgList *sols = new_alglist(); - Cube c = apply_trans(step.pre_trans, cube); - DfsData dd = { - .m = 0, - .niss = false, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && !step.ready(c)) - return sols; - - moveset_to_list(step.moveset, step.check, dd.sorted_moves); - - for (dd.d = MAX(opts->min_moves, step.check(c)); - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - solve_dfs(c, step, opts, &dd); - if (opts->feedback) - fprintf(stderr, - "Depth %d completed, found %d solutions\n", - dd.d, sols->len); - } - - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans_aux[step.pre_trans], node->alg); - - return sols; -} - -Alg * -inverse_alg(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = alg->len-1; i >= 0; i--) - append_move(ret, alg->move[i], alg->inv[i]); - - return ret; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - memset(a, 0, 16 * sizeof(uint64_t)); - - if (!pd->generated) - generate_ptable(pd); - - for (i = 0; i < pd->size; i++) - a[PTABLEVAL(pd->ptable, i)]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_trans_aux(); - init_trans(); - init_steps(); -} - - diff --git a/old/2021-06-15-before-separating-steps/cube.h b/old/2021-06-15-before-separating-steps/cube.h @@ -1,72 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> -#include "cubetypes.h" - -/* Steps *********************************************************************/ - -extern Step eofb_HTM; -extern Step eorl_HTM; -extern Step eoud_HTM; -extern Step coud_HTM; -extern Step corl_HTM; -extern Step cofb_HTM; -extern Step coud_URF; -extern Step corl_URF; -extern Step cofb_URF; -extern Step corners_HTM; -extern Step corners_URF; -extern Step edges_HTM; -extern Step drud_HTM; -extern Step optimal_HTM; - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_ep_HTM; -extern PruneData pd_drud_HTM; - -/* Public functions **********************************************************/ - -Cube apply_alg(Alg *alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Center center_at(Cube cube, Center c); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -Corner corner_at(Cube cube, Corner c); -Edge edge_at(Cube cube, Edge e); -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_admissible(Cube cube); -bool is_solved(Cube cube, bool reorient); -int piece_orientation(Cube cube, int piece, char *orientation); -void print_cube(Cube cube); -Cube random_cube(); -AlgList * solve(Cube cube, Step step, SolveOptions *opts); - -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Alg * new_alg(char *str); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); -void transform_alg(Trans t, Alg *alg); - -void print_ptable(PruneData *pd); - -void init(); - -#endif - diff --git a/old/2021-06-15-before-separating-steps/cubetypes.h b/old/2021-06-15-before-separating-steps/cubetypes.h @@ -1,201 +0,0 @@ -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct block Block; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - mirror, /* R|L */ -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - Move * move; - bool * inv; - int len; - int allocated; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -cube -{ - uint16_t epose; - uint16_t eposs; - uint16_t eposm; - uint16_t eofb; - uint16_t eorl; - uint16_t eoud; - uint16_t cp; - uint16_t coud; - uint16_t cofb; - uint16_t corl; - uint16_t cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -dfsdata -{ - int d; - int m; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[z3+1]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - uint8_t * reached; - bool generated; - uint64_t n; - uint64_t size; - uint64_t (*index)(Cube); - bool (*moveset)(Move); -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; -}; - -struct -step -{ - int (*check)(Cube); - int (*ready)(Cube); - bool (*moveset)(Move); - Trans pre_trans; -}; diff --git a/old/2021-06-15-before-separating-steps/main.c b/old/2021-06-15-before-separating-steps/main.c @@ -1,60 +0,0 @@ -#include <stdio.h> -#include "cube.h" - -int main() { - Alg *algo; - AlgList *sols; - Cube cube; - SolveOptions opts; - char line[1000]; - int i, ns = 2, nrand = 100000, sum1, sum2; - - Step *stps[20] = {&drud_HTM, &optimal_HTM}; - char sss[30][30] = {"DR on U/D", "Optimal solution"}; - - opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 20, - .optimal_only = true, - .max_solutions = 1, - .can_niss = false, - .feedback = true - }; - - init(); - -/* - print_ptable(&pd_drud_HTM); - print_ptable(&pd_ep_HTM); - print_ptable(&pd_corners_HTM); -*/ - - srand(time(NULL)); - sum1 = 0; - sum2 = 0; - for (i = 0; i < nrand; i++) { - sum1 += optimal_HTM.check(random_cube()); - sum2 += corners_HTM.check(random_cube()); - } - printf("Average optimal pruning: %lf\n", ((double)sum1) / ((double) nrand)); - printf("Average corners pruning: %lf\n", ((double)sum2) / ((double) nrand)); - - printf("Welcome to nissy 2.0! Insert a scramble:\n"); - - if (fgets(line, 1000, stdin) != NULL) { - algo = new_alg(line); - cube = apply_alg(algo, (Cube){0}); - - for (i = 0; i < ns; i++) { - if (stps[i]->check == NULL) - fprintf(stderr, "Check function for step %d is null\n", i); - sols = solve(cube, *stps[i], &opts); - printf("%s: %d solutions found:\n", sss[i], sols->len); - print_alglist(sols, true); - free_alglist(sols); - } - free(algo); - } - - return 0; -} diff --git a/old/2021-06-15-before-separating-steps/steps.h b/old/2021-06-15-before-separating-steps/steps.h @@ -1,20 +0,0 @@ -extern Step eofb_HTM; -extern Step eorl_HTM; -extern Step eoud_HTM; -extern Step coud_HTM; -extern Step corl_HTM; -extern Step cofb_HTM; -extern Step coud_URF; -extern Step corl_URF; -extern Step cofb_URF; -extern Step corners_HTM; -extern Step corners_URF; -extern Step edges_HTM; -extern Step drud_HTM; -extern Step optimal_HTM; - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_ep_HTM; -extern PruneData pd_drud_HTM; diff --git a/old/2021-06-17-cachedata/cube.c b/old/2021-06-17-cachedata/cube.c @@ -1,2738 +0,0 @@ -#include "cube.h" - -/* Constants and macros *****************************************************/ - -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define NMOVES (z3+1) -#define NTRANS (mirror+1) -#define NROTATIONS (NTRANS-1) -#define PTABLESIZE(n) ((n+1) / 2) - - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static bool allowed_next_move(Move move, DfsData *dd); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static uint16_t array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent(int pos1, int pos2); -static uint16_t epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(uint16_t epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void generate_ctable_dfs(Cube c, CacheData *cd, DfsData *dd); -static void generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void movelist_to_position(Move *movelist, int *position); -static void moveset_to_list(Moveset ms, Checker f, Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -/*static int powint(int a, int b);*/ -static void ptable_set_reached(PruneData *pd, uint64_t ind); -static void ptable_update(PruneData *pd, uint64_t ind, int m); -static void push_cachenode(CacheData *cd, Cube c, Alg *alg); -static void realloc_alg(Alg *alg, int n); -static bool read_ctable_file(CacheData *cd); -static bool read_mtables_file(); -static bool read_ptable_file(PruneData *pd); -static bool read_ttables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static void solve_cd(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static void solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_ctable_file(CacheData *cd); -static bool write_mtables_file(); -static bool write_ptable_file(PruneData *pd); -static bool write_ttables_file(); - -static void init_auxtables(); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_strings(); -static void init_trans(); -static void init_trans_aux(); - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; - -static uint16_t epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eo_ttable[NTRANS][POW2TO11]; -static uint16_t cp_ttable[NTRANS][FACTORIAL8]; -static uint16_t co_ttable[NTRANS][POW3TO7]; -static uint16_t cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static uint16_t epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eofb_mtable[NMOVES][POW2TO11]; -static uint16_t eorl_mtable[NMOVES][POW2TO11]; -static uint16_t eoud_mtable[NMOVES][POW2TO11]; -static uint16_t cp_mtable[NMOVES][FACTORIAL8]; -static uint16_t coud_mtable[NMOVES][POW3TO7]; -static uint16_t cofb_mtable[NMOVES][POW3TO7]; -static uint16_t corl_mtable[NMOVES][POW3TO7]; -static uint16_t cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * trans_algs[NROTATIONS]; - - -/* Local functions implementation ********************************************/ - -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static bool -allowed_next_move(Move move, DfsData *dd) -{ - if (!possible_next[dd->last2][dd->last1][move]) - return false; - - if (commute[dd->last1][move]) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -} - -static 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; -} - -static 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 Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static uint16_t -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 1) - ep8[j++] = (edge_slice(ep[i]) == 0) ? 1 : 0; - - return subset_to_index(ep8, 8, 4); -} - -static uint16_t -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(uint16_t epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -generate_ctable_dfs(Cube c, CacheData *cd, DfsData *dd) -{ - int i; - bool flag; - Move move, l1 = dd->last1, l2 = dd->last2; - - if (dd->current_alg->len > 0) { - for (i = 0, flag = true; i < cd->nind; i++) { - if (cd->index[i](c) != cd->index[i]((Cube){0})) { - flag = false; - break; - } - } - if (flag) - return; - } - - if (dd->current_alg->len == dd->d) { - push_cachenode(cd, c, dd->current_alg); - return; - } - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (allowed_next_move(move, dd)) { - dd->last2 = dd->last1; - dd->last1 = move; - append_move(dd->current_alg, move, false); - generate_ctable_dfs(apply_move(move, c), cd, dd); - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } -} - -static void -generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd) -{ - uint64_t ind = pd->index(c); - int oldval = PTABLEVAL(pd->ptable, ind); - Move i, move, l1 = dd->last1, l2 = dd->last2; - - if (oldval < dd->m || PTABLEVAL(pd->reached, ind) || pd->n == pd->size) - return; - - ptable_set_reached(pd, ind); - - if (dd->m == dd->d) { - if (dd->m < oldval) - ptable_update(pd, ind, dd->m); - return; - } - - dd->m++; - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (allowed_next_move(move, dd)) { - dd->last2 = dd->last1; - dd->last1 = move; - generate_ptable_dfs(apply_move(move, c), pd, dd); - dd->last2 = l2; - dd->last1 = l1; - } - } - - dd->m--; - dd->last1 = l1; - dd->last2 = l2; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -static void -moveset_to_list(bool (*ms)(Move m), int (*f)(Cube), Move *r) -{ - Cube c; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - c = apply_move(i, (Cube){0}); - if (f != NULL && f(c)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -/* -static int -powint(int a, int b) -{ - if (b < 0) - return 0; - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} -*/ - -static void -ptable_set_reached(PruneData *pd, uint64_t ind) -{ - uint8_t oldval2 = pd->reached[ind/2]; - int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; - - pd->reached[ind/2] = ind % 2 ? 16 + other : 16*other + 1; -} - -static void -ptable_update(PruneData *pd, uint64_t ind, int n) -{ - uint8_t oldval2 = pd->ptable[ind/2]; - int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = ind % 2 ? 16*n + other : 16*other + n; - pd->n++; -} - -static void -push_cachenode(CacheData *cd, Cube c, Alg *alg) -{ - CacheNode *node = malloc(sizeof(CacheNode)); - uint64_t ind0 = cd->index[0](c); - int i; - - node->indexval = malloc((cd->nind - 1) * sizeof(uint64_t)); - for (i = 1; i < cd->nind; i++) - node->indexval[i-1] = cd->index[i](c); - - node->sol = inverse_alg(alg); - realloc_alg(node->sol, cd->len); - node->next = cd->ctable[ind0]; - cd->ctable[ind0] = node; -} - -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); - alg->inv = realloc(alg->inv, n); - alg->allocated = n; -} - -static bool -read_ctable_file(CacheData *cd) -{ - return false; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(uint16_t); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); - fclose(f); - - return r == PTABLESIZE(pd->size); -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(uint16_t); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - Alg *inv; - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Cube ret; - - if (r != mirror) { - ret = apply_alg_generic(trans_algs[r], c, f, true); - inv = on_inverse(trans_algs[r]); - ret = apply_alg_generic(inv, ret, f, true); - free_alg(inv); - } else { - ret = move_via_arrays(&ma, (Cube){0}, f); - ret = compose_filtered(c, ret, f); - ret = move_via_arrays(&ma, ret, f); - } - - return ret; -} - -static void -solve_cd(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - int j, k; - bool flag; - uint64_t ind0; - CacheNode *i; - - if (!s.cd->generated) - generate_ctable(s.cd); - - ind0 = s.cd->index[0](c); - for (i = s.cd->ctable[ind0]; - i != NULL && dd->sols->len < opts->max_solutions; - i = i->next) { - for (j = 1, flag = true; j < s.cd->nind; j++) { - if (s.cd->index[j](c) != i->indexval[j-1]) { - flag = false; - break; - } - } - if (flag) { - for (k = 0; k < s.cd->len; k++) - append_move(dd->current_alg, - i->sol->move[k], dd->niss); - append_alg(dd->sols, dd->current_alg); - if (opts->feedback) { - printf("[cached] "); - print_alg(dd->current_alg, false); - } - } - } -} - -static void -solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move move, l1 = dd->last1, l2 = dd->last2; - int i, lower_bound; - bool nissbackup = dd->niss; - - if (dd->sols->len >= opts->max_solutions) - return; - - lower_bound = s.check(c); - if (opts->can_niss && !dd->niss) - lower_bound = MIN(1, lower_bound); - - if (dd->current_alg->len + lower_bound > dd->d) - return; - - if (lower_bound == 0) { - if (dd->current_alg->len == dd->d) { - append_alg(dd->sols, dd->current_alg); - if (opts->feedback) - print_alg(dd->current_alg, false); - } - return; - } - - if (s.cd != NULL && s.cd->len == dd->d - dd->current_alg->len) { - solve_cd(c, s, opts, dd); - } else { - for (i = 0; - dd->sorted_moves[i] != NULLMOVE && - dd->sols->len < opts->max_solutions; - i++) { - move = dd->sorted_moves[i]; - if (allowed_next_move(move, dd)) { - dd->last2 = dd->last1; - dd->last1 = move; - append_move(dd->current_alg, move, dd->niss); - solve_dfs(apply_move(move, c), s, opts, dd); - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } - } - - if (opts->can_niss && !dd->niss) { - if (dd->current_alg->len == 0 || - (s.check(apply_move(inverse_move(l1), (Cube){0})))) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - solve_dfs(inverse_cube(c), s, opts, dd); - } - } - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = nissbackup; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_ctable_file(CacheData *cd) -{ - return false; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(uint16_t); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); - fclose(f); - - return written == PTABLESIZE(pd->size); -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(uint16_t); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - uint64_t ui, uj; - int i, j, k; - bool cij, p1, p2; - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj] = epos_dependent(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2) && i && j; - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[mirror] = mirror; -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - uint16_t ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray) { - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_trans() { - Cube aux, cube, c[3]; - CubeArray epcp; - int eparr[12], eoarr[12]; - int cparr[8], coarr[8]; - int i; - bool b1, b2, b3; - uint16_t ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - if (i == mirror) - cube = (Cube){0}; - else - cube = apply_alg(trans_algs[i], (Cube){0}); - - epose_source[i] = edge_slice(edge_at(cube, FR)); - eposs_source[i] = edge_slice(edge_at(cube, UR)); - eposm_source[i] = edge_slice(edge_at(cube, UF)); - eofb_source[i] = center_at(cube, F_center)/2; - eorl_source[i] = center_at(cube, R_center)/2; - eoud_source[i] = center_at(cube, U_center)/2; - coud_source[i] = center_at(cube, U_center)/2; - cofb_source[i] = center_at(cube, F_center)/2; - corl_source[i] = center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - if (m == mirror) { - memcpy(eparr, ep_mirror, 12 * sizeof(int)); - memcpy(cparr, cp_mirror, 8 * sizeof(int)); - } else { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(trans_algs[m], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m == mirror) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - if (m == mirror) { - b1 = (mi >= U && mi <= Bw3); - b2 = (mi >= S && mi <= E3); - b3 = (mi >= x && mi <= z3); - if (b1 || b2 || b3) - moves_ttable[m][mi] = - inverse_move_aux[mi]; - else - moves_ttable[m][mi] = mi; - - if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) - moves_ttable[m][mi] += 3; - if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) - moves_ttable[m][mi] -= 3; - } else { - aux = apply_trans(m, apply_move(mi,(Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move( - inverse_move_aux[move], aux); - if (is_solved(cube, false)) - moves_ttable[m][mi] = move; - } - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - trans_algs[uf] = new_alg(""); - trans_algs[ur] = new_alg("y"); - trans_algs[ub] = new_alg("y2"); - trans_algs[ul] = new_alg("y3"); - - trans_algs[df] = new_alg("z2"); - trans_algs[dr] = new_alg("y z2"); - trans_algs[db] = new_alg("x2"); - trans_algs[dl] = new_alg("y3 z2"); - - trans_algs[rf] = new_alg("z3"); - trans_algs[rd] = new_alg("z3 y"); - trans_algs[rb] = new_alg("z3 y2"); - trans_algs[ru] = new_alg("z3 y3"); - - trans_algs[lf] = new_alg("z"); - trans_algs[ld] = new_alg("z y3"); - trans_algs[lb] = new_alg("z y2"); - trans_algs[lu] = new_alg("z y"); - - trans_algs[fu] = new_alg("x y2"); - trans_algs[fr] = new_alg("x y"); - trans_algs[fd] = new_alg("x"); - trans_algs[fl] = new_alg("x y3"); - - trans_algs[bu] = new_alg("x3"); - trans_algs[br] = new_alg("x3 y"); - trans_algs[bd] = new_alg("x3 y2"); - trans_algs[bl] = new_alg("x3 y3"); -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - return (Cube) { - .epose = epose_mtable[m][cube.epose], - .eposs = eposs_mtable[m][cube.eposs], - .eposm = eposm_mtable[m][cube.eposm], - .eofb = eofb_mtable[m][cube.eofb], - .eorl = eorl_mtable[m][cube.eorl], - .eoud = eoud_mtable[m][cube.eoud], - .coud = coud_mtable[m][cube.coud], - .cofb = cofb_mtable[m][cube.cofb], - .corl = corl_mtable[m][cube.corl], - .cp = cp_mtable[m][cube.cp], - .cpos = cpos_mtable[m][cube.cpos] - }; -} - -Cube -apply_trans(Trans t, Cube cube) -{ - uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - return (Cube) { - .epose = epose_ttable[t][aux_epos[epose_source[t]]], - .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], - .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], - .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], - .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], - .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], - .coud = co_ttable[t][aux_co[coud_source[t]]], - .corl = co_ttable[t][aux_co[corl_source[t]]], - .cofb = co_ttable[t][aux_co[cofb_source[t]]], - .cp = cp_ttable[t][cube.cp], - .cpos = cpos_ttable[t][cube.cpos] - }; -} - -Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -/* TODO: this has to be changed using pre-computations */ -bool -block_solved(Cube cube, Block block) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - int i; - bool ret = true; - - for (i = 0; i < 12; i++) - ret = ret && !(block.edge[i] && (arr->ep[i] != i || arr->eofb[i])); - for (i = 0; i < 8; i++) - ret = ret && !(block.corner[i] && (arr->cp[i] != i || arr->coud[i])); - for (i = 0; i < 6; i++) - ret = ret && !(block.center[i] && arr->cpos[i] != i); - - free_cubearray(arr, pf_all); - - return ret; -} - -Center -center_at(Cube cube, Center c) -{ - int ret; - CubeArray *arr = new_cubearray(cube, pf_cpos); - - ret = arr->cpos[c]; - free_cubearray(arr, pf_cpos); - - return ret; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -Corner -corner_at(Cube cube, Corner c) -{ - int ret; - CubeArray *arr = new_cubearray(cube, pf_cp); - - ret = arr->cp[c]; - free_cubearray(arr, pf_cp); - - return ret; -} - -Edge -edge_at(Cube cube, Edge e) -{ - int ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - free_cubearray(arr, pf_ep); - - return ret; -} - -uint64_t -epos_dependent_cube(Cube c) -{ - return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -void -generate_ctable(CacheData *cd) -{ - uint64_t i; - DfsData dd = { - .d = cd->len, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .current_alg = new_alg("") - }; - - if (cd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - cd->ctable = malloc(cd->maxind0 * sizeof(CacheNode *)); - for (i = 0; i < cd->maxind0; i++) - cd->ctable[i] = NULL; - - if (read_ctable_file(cd)) { - cd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", cd->filename); - - moveset_to_list(cd->moveset, NULL, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - generate_ctable_dfs((Cube){0}, cd, &dd); - - if (!write_ctable_file(cd)) - fprintf(stderr, "Error writing ctable file\n"); - - cd->generated = true; -} - -void -generate_ptable(PruneData *pd) -{ - uint64_t j; - DfsData dd = { - .m = 0, - .last1 = NULLMOVE, - .last2 = NULLMOVE - }; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - pd->ptable = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->size; j++) - ptable_update(pd, j, 15); - - moveset_to_list(pd->moveset, NULL, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - pd->reached = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); - for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { - memset(pd->reached, 0, PTABLESIZE(pd->size)*sizeof(uint8_t)); - generate_ptable_dfs((Cube){0}, pd, &dd); - fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", - dd.d, pd->n, pd->size); - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; - free(pd->reached); -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - Trans i; - - if (reorient) - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(trans_algs[i],cube), false)) - return true; - - return equal(cube, (Cube){0}); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b; - uint16_t x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - AlgListNode *node; - AlgList *sols = new_alglist(); - Cube c = apply_trans(opts->pre_trans, cube); - DfsData dd = { - .m = 0, - .niss = false, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && !step.ready(c)) { - fprintf(stderr, "Cube not ready for solving step\n"); - return sols; - } - - moveset_to_list(step.moveset, step.check, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = MAX(opts->min_moves, step.check(c)); - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - if (opts->feedback) - fprintf(stderr, - "Found %d solutions, searching depth %d...\n", - sols->len, dd.d); - solve_dfs(c, step, opts, &dd); - } - - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans_aux[opts->pre_trans], node->alg); - - return sols; -} - -Alg * -inverse_alg(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = alg->len-1; i >= 0; i--) - append_move(ret, alg->move[i], alg->inv[i]); - - return ret; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - /* TODO: make it possible to print to stdout or to string */ - /* Maybe just return a string */ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -print_cachedata(CacheData *cd, bool printalgs) -{ - CacheNode *j; - uint64_t i, s, maxa = 0, maxs = 0, n = 0, empty = 0; - - if (!cd->generated) - generate_ctable(cd); - - for (i = 0; i < cd->maxind0; i++) { - if (cd->ctable[i] == NULL) { - empty++; - continue; - } - - for (j = cd->ctable[i], s = 0; - j != NULL; j = j->next, n++, s++) - if (printalgs) - print_alg(j->sol, false); - - if (s > maxs) { - maxs = s; - maxa = i; - } - } - - printf("Cache data %s\n", cd->filename); - printf("Length: %d\n", cd->len); - printf("Main table cells: %lu (of which %lu empty)\n", i, empty); - printf("%lu solutions cached ", n); - printf("(most crowded cell: %lu with %lu)\n", maxa, maxs); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - for (i = 0; i < 16; i++) - a[i] = 0; - - if (!pd->generated) - generate_ptable(pd); - - for (i = 0; i < pd->size; i++) - a[PTABLEVAL(pd->ptable, i)]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - - -Alg * -trans_alg(Trans i) -{ - return trans_algs[i]; -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_trans_aux(); - init_trans(); -} - diff --git a/old/2021-06-17-cachedata/cube.h b/old/2021-06-17-cachedata/cube.h @@ -1,79 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> - -/* Constants and macros *****************************************************/ - -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define NMOVES (z3+1) -#define NTRANS (mirror+1) -#define NROTATIONS (NTRANS-1) -#define PTABLESIZE(n) ((n+1) / 2) -#define PTABLEVAL(t,i) (((i)%2) ? (t[(i)/2] / 16) : (t[(i)/2] % 16)) - -/* Type definitions **********************************************************/ - -#include "cubetypes.h" - -/* Public functions **********************************************************/ - -Cube apply_alg(Alg *alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Center center_at(Cube cube, Center c); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -Corner corner_at(Cube cube, Corner c); -Edge edge_at(Cube cube, Edge e); -uint64_t epos_dependent_cube(Cube cube); -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_admissible(Cube cube); -bool is_solved(Cube cube, bool reorient); -int piece_orientation(Cube cube, int piece, char *orientation); -void print_cube(Cube cube); -Cube random_cube(); -AlgList * solve(Cube cube, Step step, SolveOptions *opts); - -Move base_move(Move m); -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Alg * new_alg(char *str); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); -Alg * trans_alg(Trans i); -void transform_alg(Trans t, Alg *alg); - -void generate_ctable(CacheData *cd); -void generate_ptable(PruneData *pd); -void print_cachedata(CacheData *cd, bool printalgs); -void print_ptable(PruneData *pd); - -void init(); - -#endif - diff --git a/old/2021-06-17-cachedata/cubetypes.h b/old/2021-06-17-cachedata/cubetypes.h @@ -1,232 +0,0 @@ -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct block Block; -typedef struct cachedata CacheData; -typedef struct cachenode CacheNode; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; - -typedef int (*Checker)(Cube); -typedef uint64_t (*Indexer)(Cube); -typedef bool (*Moveset)(Move); - - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - mirror, /* R|L */ -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - Move * move; - bool * inv; - int len; - int allocated; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -cachedata -{ - char * filename; - CacheNode ** ctable; - bool generated; - uint64_t maxind0; - int len; - int nind; - Indexer index[20]; /* Should be enough */ - Checker check; - Moveset moveset; -}; - -struct -cachenode -{ - uint64_t * indexval; - Alg * sol; - CacheNode * next; -}; - -struct -cube -{ - uint16_t epose; - uint16_t eposs; - uint16_t eposm; - uint16_t eofb; - uint16_t eorl; - uint16_t eoud; - uint16_t cp; - uint16_t coud; - uint16_t cofb; - uint16_t corl; - uint16_t cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -dfsdata -{ - int d; - int m; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[NMOVES]; - int move_position[NMOVES]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - uint8_t * reached; - bool generated; - uint64_t n; - uint64_t size; - Indexer index; - Moveset moveset; -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; - Trans pre_trans; -}; - -struct -step -{ - Checker check; - Checker ready; - Moveset moveset; - CacheData * cd; -}; diff --git a/old/2021-06-17-cachedata/main.c b/old/2021-06-17-cachedata/main.c @@ -1,63 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "steps.h" - -int main() { - Alg *algo; - AlgList *sols; - Cube cube; - SolveOptions opts; - char line[1000]; - int i, ns = 3; /*, nrand = 100000, sum1, sum2;*/ - - Step *stps[20] = {&eofb_HTM, &corners_URF, &optimal_HTM}; - char sss[30][30] = {"EO on F/B", "Corners URF", "Optimal solution"}; - - opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 20, - .optimal_only = true, - .max_solutions = 1, - .can_niss = false, - .feedback = true, - .pre_trans = uf - }; - - init(); - -/* - print_ptable(&pd_corners_HTM); - - srand(time(NULL)); - sum1 = 0; - sum2 = 0; - for (i = 0; i < nrand; i++) { - sum1 += optimal_HTM.check(random_cube()); - sum2 += corners_HTM.check(random_cube()); - } - printf("Average optimal pruning: %lf\n", ((double)sum1) / ((double) nrand)); - printf("Average corners pruning: %lf\n", ((double)sum2) / ((double) nrand)); -*/ - - print_cachedata(&cd_optimal_HTM_6, false); - - printf("Welcome to nissy 2.0! Insert a scramble:\n"); - - if (fgets(line, 1000, stdin) != NULL) { - algo = new_alg(line); - cube = apply_alg(algo, (Cube){0}); - - for (i = 0; i < ns; i++) { - if (stps[i]->check == NULL) - fprintf(stderr, "Check function for step %d is null\n", i); - sols = solve(cube, *stps[i], &opts); - printf("%s: %d solutions found:\n", sss[i], sols->len); - print_alglist(sols, true); - free_alglist(sols); - } - free(algo); - } - - return 0; -} - diff --git a/old/2021-06-17-cachedata/steps.c b/old/2021-06-17-cachedata/steps.c @@ -1,327 +0,0 @@ -#include "steps.h" - -/* Check functions ***********************************************************/ - -static int check_nothing(Cube cube); -static int check_eofb_HTM(Cube cube); -static int check_coud_HTM(Cube cube); -static int check_coud_URF(Cube cube); -static int check_corners_HTM(Cube cube); -static int check_corners_URF(Cube cube); -static int check_edges_HTM(Cube cube); -static int check_drud_HTM(Cube cube); -static int check_optimal_HTM(Cube cube); - - -/* Index functions ***********************************************************/ - -static uint64_t index_eofb(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_ep(Cube cube); -static uint64_t index_drud(Cube cube); - - -/* Steps *********************************************************************/ - -Step -eofb_HTM = { - .check = check_eofb_HTM, - .ready = check_nothing, - .moveset = moveset_HTM -}; - -Step -coud_HTM = { - .check = check_coud_HTM, - .ready = check_nothing, - .moveset = moveset_HTM -}; - -Step -coud_URF = { - .check = check_coud_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_HTM = { - .check = check_corners_HTM, - .ready = check_nothing, - .moveset = moveset_HTM -}; - -Step -corners_URF = { - .check = check_corners_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -edges_HTM = { - .check = check_edges_HTM, - .ready = check_nothing, - .moveset = moveset_HTM -}; - -Step -drud_HTM = { - .check = check_drud_HTM, - .ready = check_nothing, - .moveset = moveset_HTM -}; - -Step -optimal_HTM = { - .check = check_optimal_HTM, - .ready = check_nothing, - .moveset = moveset_HTM, - .cd = &cd_optimal_HTM_6 -}; - - -/* Cache solutions ***********************************************************/ - -CacheData -cd_optimal_HTM_6 = { - .filename = "cd_optimal_HTM_6", - .maxind0 = POW3TO7 * FACTORIAL8, - .len = 6, - .nind = 3, - .index = { index_corners, index_eofb, index_ep }, - .moveset = moveset_HTM -}; - - -/* Pruning tables ************************************************************/ - -PruneData -pd_eofb_HTM = { - .filename = "ptable_eofb_HTM", - .size = POW2TO11, - .index = index_eofb, - .moveset = moveset_HTM -}; - -PruneData -pd_coud_HTM = { - .filename = "ptable_coud_HTM", - .size = POW3TO7, - .index = index_coud, - .moveset = moveset_HTM -}; - -PruneData -pd_corners_HTM = { - .filename = "ptable_corners_HTM", - .size = POW3TO7 * FACTORIAL8, - .index = index_corners, - .moveset = moveset_HTM -}; - -PruneData -pd_ep_HTM = { - .filename = "ptable_ep_HTM", - .size = FACTORIAL12, - .index = index_ep, - .moveset = moveset_HTM -}; - -PruneData -pd_drud_HTM = { - .filename = "ptable_drud_HTM", - .size = POW2TO11 * POW3TO7 * BINOM12ON4, - .index = index_drud, - .moveset = moveset_HTM -}; - - -/* Check functions implementation ********************************************/ - -static int -check_nothing(Cube cube) -{ - /* At least we check that it is admissible */ - return is_admissible(cube); -} - -static int -check_eofb_HTM(Cube cube) -{ - if (!pd_eofb_HTM.generated) - generate_ptable(&pd_eofb_HTM); - - return PTABLEVAL(pd_eofb_HTM.ptable, cube.eofb); -} - -static int -check_coud_HTM(Cube cube) -{ - if (!pd_coud_HTM.generated) - generate_ptable(&pd_coud_HTM); - - return PTABLEVAL(pd_coud_HTM.ptable, cube.coud); -} - -static int -check_coud_URF(Cube cube) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - int ud = check_coud_HTM(cube); - int rl = check_coud_HTM(apply_move(z, cube)); - int fb = check_coud_HTM(apply_move(x, cube)); - - return MIN(ud, MIN(rl, fb)); -} - -static int -check_corners_HTM(Cube cube) -{ - if (!pd_corners_HTM.generated) - generate_ptable(&pd_corners_HTM); - - return PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); -} - -static int -check_corners_URF(Cube cube) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) - ret = MIN(ret,check_corners_HTM(apply_alg(trans_alg(i),cube))); - - return ret; -} - -static int -check_edges_HTM(Cube cube) -{ - int ret = 0; - - if (!pd_ep_HTM.generated) - generate_ptable(&pd_ep_HTM); - - ret = MAX(ret, PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube))); - ret = MAX(ret, check_eofb_HTM(cube)); - ret = MAX(ret, check_eofb_HTM(apply_trans(ur, cube))); - ret = MAX(ret, check_eofb_HTM(apply_trans(fd, cube))); - - return ret; -} - -static int -check_drud_HTM(Cube cube) -{ - if (!pd_drud_HTM.generated) - generate_ptable(&pd_drud_HTM); - - return PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); -} - -static int -check_optimal_HTM(Cube cube) -{ - int dr1, dr2, dr3, drmax, cor; /*ep;*/ - - if (!pd_drud_HTM.generated) - generate_ptable(&pd_drud_HTM); - if (!pd_corners_HTM.generated) - generate_ptable(&pd_corners_HTM); - /* - *if (!pd_ep_HTM.generated) - * generate_ptable(&pd_ep_HTM); - */ - - dr1 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); - dr2 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(rf, cube))); - dr3 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(fd, cube))); - - drmax = MAX(dr1, MAX(dr2, dr3)); - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - drmax++; - - cor = PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); - /* ep = PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube)); */ - - /*return MAX(drmax, MAX(ep, cor));*/ - if (drmax == 0 && cor == 0) - return is_solved(cube, false) ? 0 : 1; - return MAX(drmax, cor); -} - - -/* Index functions implementation ********************************************/ - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_ep(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eposs; - b = (cube.epose % FACTORIAL4) + epos_dependent_cube(cube)*FACTORIAL4; - c = cube.eposm % FACTORIAL4; - - b *= FACTORIAL4 * BINOM12ON4; - c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; - - return a + b + c; -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - diff --git a/old/2021-06-17-cachedata/steps.h b/old/2021-06-17-cachedata/steps.h @@ -1,34 +0,0 @@ -#ifndef STEPS_H -#define STEPS_H - -#include "cube.h" - -/* Steps *********************************************************************/ - -extern Step eofb_HTM; -extern Step coud_HTM; -extern Step coud_URF; -extern Step corners_HTM; -extern Step corners_URF; -extern Step edges_HTM; -extern Step drud_HTM; -extern Step optimal_HTM; - -/* Cache solutions ***********************************************************/ - -extern CacheData cd_optimal_HTM_6; - -/* Pruning tables ************************************************************/ - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_ep_HTM; -extern PruneData pd_drud_HTM; - -/* Movesets ******************************************************************/ - -bool moveset_HTM(Move m); -bool moveset_URF(Move m); - -#endif diff --git a/old/2021-06-23-realizing-bad-tables/HERE b/old/2021-06-23-realizing-bad-tables/HERE @@ -1 +0,0 @@ -Here you can also find some tables data that I have removed, like ep and tripleeo diff --git a/old/2021-06-23-realizing-bad-tables/cube.c b/old/2021-06-23-realizing-bad-tables/cube.c @@ -1,2844 +0,0 @@ -#include "cube.h" - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static bool allowed_next(Move move, DfsData *dd); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static int array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); -static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent_pos(int pos1, int pos2); -static int epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(int epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); -static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void movelist_to_position(Move *movelist, int *position); -static void moveset_to_list(Moveset ms, Checker f, Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static bool ptable_has_reached(PruneData *pd, uint64_t ind); -static void ptable_set_reached(PruneData *pd, uint64_t ind); -static void ptable_update(PruneData *pd, uint64_t ind, int m); -static void realloc_alg(Alg *alg, int n); -static bool read_algset_file(AlgSet *as); -static bool read_mtables_file(); -static bool read_ptable_file(PruneData *pd); -static bool read_ttables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_algset_file(AlgSet *as); -static bool write_mtables_file(); -static bool write_ptable_file(PruneData *pd); -static bool write_ttables_file(); - -static void init_auxtables(); -static void init_cphtr_cosets(); -static void init_cphtr_cosets_bfs(int i, int c); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_strings(); -static void init_trans(); -static void init_trans_aux(); - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; -static int cphtr_cosets[FACTORIAL8]; -static Center what_center_at_aux[FACTORIAL6][6]; -static Corner what_corner_at_aux[FACTORIAL8][8]; -static int what_orientation_last_corner_aux[POW3TO7]; -static int what_orientation_last_edge_aux[POW2TO11]; -static Center where_is_center_aux[FACTORIAL6][6]; -static Corner where_is_corner_aux[FACTORIAL8][8]; -static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; - -static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eo_ttable[NTRANS][POW2TO11]; -static int cp_ttable[NTRANS][FACTORIAL8]; -static int co_ttable[NTRANS][POW3TO7]; -static int cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eofb_mtable[NMOVES][POW2TO11]; -static int eorl_mtable[NMOVES][POW2TO11]; -static int eoud_mtable[NMOVES][POW2TO11]; -static int cp_mtable[NMOVES][FACTORIAL8]; -static int coud_mtable[NMOVES][POW3TO7]; -static int cofb_mtable[NMOVES][POW3TO7]; -static int corl_mtable[NMOVES][POW3TO7]; -static int cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * trans_algs[NROTATIONS]; - - -/* Local functions implementation ********************************************/ - -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static bool -allowed_next(Move move, DfsData *dd) -{ - if (!possible_next[dd->last2][dd->last1][move]) - return false; - - if (commute[dd->last1][move]) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -} - -static 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; -} - -static 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 Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static int -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -/* -static int -cphtr_cp(int cp) -{ - int i, a[8]; - - index_to_perm(cp, 8, a); - - for (i = 0; i < 8; i++) - if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) - a[i] = 0; - else - a[i] = 1; - - swap(&a[1], &a[5]); - swap(&a[3], &a[7]); - - return subset_to_index(a, 8, 4); -} -*/ - -static void -dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - if (dfs_stop(c, s, opts, dd)) - return; - - if (dfs_check_solved(opts, dd)) - return; - - dfs_branch(c, s, opts, dd); - - if (opts->can_niss && !dd->niss) - dfs_niss(c, s, opts, dd); -} - -static void -dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; - - int i, maxnsol = opts->max_solutions; - - for (i = 0; (m=moves[i]) != NULLMOVE && dd->sols->len < maxnsol; i++) { - if (allowed_next(m, dd)) { - dd->last2 = dd->last1; - dd->last1 = m; - append_move(dd->current_alg, m, dd->niss); - - dfs(apply_move(m, c), s, opts, dd); - - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } -} - -static bool -dfs_check_solved(SolveOptions *opts, DfsData *dd) -{ - if (dd->lb != 0) - return false; - - if (dd->current_alg->len == dd->d) { - append_alg(dd->sols, dd->current_alg); - - if (opts->feedback) - print_alg(dd->current_alg, false); - } - - return true; -} - -static void -dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move l1 = dd->last1, l2 = dd->last2; - - if (dd->current_alg->len == 0 || - (s.check(apply_move(inverse_move(l1), (Cube){0}), 1))) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - - dfs(inverse_cube(c), s, opts, dd); - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = false; - } -} - -static bool -dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - if (dd->sols->len >= opts->max_solutions) - return true; - - dd->lb = s.check(c, dd->d - dd->current_alg->len); - if (opts->can_niss && !dd->niss) - dd->lb = MIN(1, dd->lb); - - if (dd->current_alg->len + dd->lb > dd->d) - return true; - - return false; -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent_pos(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 0) - ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; - - swap(&ep8[1], &ep8[4]); - swap(&ep8[3], &ep8[6]); - - return subset_to_index(ep8, 8, 4); -} - -static int -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(int epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -genptable_dfs(Cube c, PruneData *pd, DfsData *dd) -{ - uint64_t ind = pd->index(c); - int oldval = ptableval(pd, ind); - - if (oldval < dd->m || ptable_has_reached(pd, ind) || pd->n == pd->size) - return; - - ptable_set_reached(pd, ind); - - if (dd->m == dd->d) { - if (dd->m < oldval) - ptable_update(pd, ind, dd->m); - return; - } - - genptable_dfs_branch(c, pd, dd); -} - -static void -genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) -{ - Move i, move, l1 = dd->last1, l2 = dd->last2; - - dd->m++; - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (allowed_next(move, dd)) { - dd->last2 = dd->last1; - dd->last1 = move; - - genptable_dfs(apply_move(move, c), pd, dd); - - dd->last2 = l2; - dd->last1 = l1; - } - } - - dd->m--; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -static void -moveset_to_list(Moveset ms, Checker f, Move *r) -{ - Cube c; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - c = apply_move(i, (Cube){0}); - if (f != NULL && f(c, 1)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static bool -ptable_has_reached(PruneData *pd, uint64_t ind) -{ - return (ind % 2) ? pd->reached[ind/2] / 16 : pd->reached[ind/2] % 16; -} - -static void -ptable_set_reached(PruneData *pd, uint64_t ind) -{ - uint8_t oldval2 = pd->reached[ind/2]; - int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; - - pd->reached[ind/2] = (ind % 2) ? 16 + other : 16*other + 1; -} - -static void -ptable_update(PruneData *pd, uint64_t ind, int n) -{ - uint8_t oldval2 = pd->ptable[ind/2]; - int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; - pd->n++; -} - -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; -} - -static bool -read_algset_file(AlgSet *as) -{ - return false; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return r == ptablesize(pd); -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(int); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - Alg *inv; - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Cube ret; - - if (r != mirror) { - ret = apply_alg_generic(trans_algs[r], c, f, true); - inv = on_inverse(trans_algs[r]); - ret = apply_alg_generic(inv, ret, f, true); - free_alg(inv); - } else { - ret = move_via_arrays(&ma, (Cube){0}, f); - ret = compose_filtered(c, ret, f); - ret = move_via_arrays(&ma, ret, f); - } - - return ret; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_algset_file(AlgSet *as) -{ - return false; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return written == ptablesize(pd); -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(int); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - CubeArray *arr; - uint64_t ui, uj; - int i, j, k, auxarr[12]; - bool cij, p1, p2; - - for (ui = 0; ui < FACTORIAL6; ui++) { - arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); - for (i = 0; i < 6; i++) { - what_center_at_aux[ui][i] = arr->cpos[i]; - where_is_center_aux[ui][arr->cpos[i]] = i; - } - free_cubearray(arr, pf_cpos); - } - - for (ui = 0; ui < FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.cp = ui}, pf_cp); - for (i = 0; i < 8; i++) { - what_corner_at_aux[ui][i] = arr->cp[i]; - where_is_corner_aux[ui][arr->cp[i]] = i; - } - free_cubearray(arr, pf_cp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.epose = ui}, pf_e); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 0) - where_is_edge_aux[0][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_e); - - arr = new_cubearray((Cube){.eposs = ui}, pf_s); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 1) - where_is_edge_aux[1][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_s); - - arr = new_cubearray((Cube){.eposm = ui}, pf_m); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 2) - where_is_edge_aux[2][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_m); - } - - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, auxarr); - what_orientation_last_corner_aux[ui] = auxarr[7]; - } - - for (ui = 0; ui < POW2TO11; ui++) { - int_to_sum_zero_array(ui, 2, 12, auxarr); - what_orientation_last_edge_aux[ui] = auxarr[11]; - } - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2) && i && j; - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[mirror] = mirror; -} - -/* - * There is certainly a bette way to do this, but for now I just use - * a "graph coloring" algorithm to compute the cosets for cphtr. - * - * For doing it better "Mathematically", we need 3 things: - * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other - * This is easy and it is done in the commented function cphtr_cp(). - * - Check that there is no ep/cp parity - * - Check that we are not in the "3c" case; this is the part I don't - * know how to do. - */ -static void -init_cphtr_cosets() -{ - unsigned int i; - int c = 0; - - for (i = 0; i < FACTORIAL8; i++) - cphtr_cosets[i] = -1; - - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_cosets[i] == -1) - init_cphtr_cosets_bfs(i, c++); -} - -static void -init_cphtr_cosets_bfs(int i, int c) -{ - int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; - Move moves[6] = {U2, D2, R2, L2, F2, B2}; - - n = 1; - next[0] = i; - cphtr_cosets[i] = c; - - while (n != 0) { - for (j = 0, n2 = 0; j < n; j++) { - for (k = 0; k < 6; k++) { - jj = cp_mtable[moves[k]][next[j]]; - if (cphtr_cosets[jj] == -1) { - cphtr_cosets[jj] = c; - next2[n2++] = jj; - } - } - } - - for (j = 0; j < n2; j++) - next[j] = next2[j]; - n = n2; - } -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - unsigned int ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray) { - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_trans() { - Cube aux, cube, c[3]; - CubeArray epcp; - int eparr[12], eoarr[12]; - int cparr[8], coarr[8]; - int i; - unsigned int ui; - bool b1, b2, b3; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - if (i == mirror) - cube = (Cube){0}; - else - cube = apply_alg(trans_algs[i], (Cube){0}); - - epose_source[i] = edge_slice(what_edge_at(cube, FR)); - eposs_source[i] = edge_slice(what_edge_at(cube, UR)); - eposm_source[i] = edge_slice(what_edge_at(cube, UF)); - eofb_source[i] = what_center_at(cube, F_center)/2; - eorl_source[i] = what_center_at(cube, R_center)/2; - eoud_source[i] = what_center_at(cube, U_center)/2; - coud_source[i] = what_center_at(cube, U_center)/2; - cofb_source[i] = what_center_at(cube, F_center)/2; - corl_source[i] = what_center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - if (m == mirror) { - memcpy(eparr, ep_mirror, 12 * sizeof(int)); - memcpy(cparr, cp_mirror, 8 * sizeof(int)); - } else { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(trans_algs[m], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m == mirror) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - if (m == mirror) { - b1 = (mi >= U && mi <= Bw3); - b2 = (mi >= S && mi <= E3); - b3 = (mi >= x && mi <= z3); - if (b1 || b2 || b3) - moves_ttable[m][mi] = - inverse_move_aux[mi]; - else - moves_ttable[m][mi] = mi; - - if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) - moves_ttable[m][mi] += 3; - if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) - moves_ttable[m][mi] -= 3; - } else { - aux = apply_trans(m, apply_move(mi,(Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move( - inverse_move_aux[move], aux); - if (is_solved(cube, false)) - moves_ttable[m][mi] = move; - } - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - trans_algs[uf] = new_alg(""); - trans_algs[ur] = new_alg("y"); - trans_algs[ub] = new_alg("y2"); - trans_algs[ul] = new_alg("y3"); - - trans_algs[df] = new_alg("z2"); - trans_algs[dr] = new_alg("y z2"); - trans_algs[db] = new_alg("x2"); - trans_algs[dl] = new_alg("y3 z2"); - - trans_algs[rf] = new_alg("z3"); - trans_algs[rd] = new_alg("z3 y"); - trans_algs[rb] = new_alg("z3 y2"); - trans_algs[ru] = new_alg("z3 y3"); - - trans_algs[lf] = new_alg("z"); - trans_algs[ld] = new_alg("z y3"); - trans_algs[lb] = new_alg("z y2"); - trans_algs[lu] = new_alg("z y"); - - trans_algs[fu] = new_alg("x y2"); - trans_algs[fr] = new_alg("x y"); - trans_algs[fd] = new_alg("x"); - trans_algs[fl] = new_alg("x y3"); - - trans_algs[bu] = new_alg("x3"); - trans_algs[br] = new_alg("x3 y"); - trans_algs[bd] = new_alg("x3 y2"); - trans_algs[bl] = new_alg("x3 y3"); -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - return (Cube) { - .epose = epose_mtable[m][cube.epose], - .eposs = eposs_mtable[m][cube.eposs], - .eposm = eposm_mtable[m][cube.eposm], - .eofb = eofb_mtable[m][cube.eofb], - .eorl = eorl_mtable[m][cube.eorl], - .eoud = eoud_mtable[m][cube.eoud], - .coud = coud_mtable[m][cube.coud], - .cofb = cofb_mtable[m][cube.cofb], - .corl = corl_mtable[m][cube.corl], - .cp = cp_mtable[m][cube.cp], - .cpos = cpos_mtable[m][cube.cpos] - }; -} - -Cube -apply_trans(Trans t, Cube cube) -{ - int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - return (Cube) { - .epose = epose_ttable[t][aux_epos[epose_source[t]]], - .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], - .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], - .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], - .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], - .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], - .coud = co_ttable[t][aux_co[coud_source[t]]], - .corl = co_ttable[t][aux_co[corl_source[t]]], - .cofb = co_ttable[t][aux_co[cofb_source[t]]], - .cp = cp_ttable[t][cube.cp], - .cpos = cpos_ttable[t][cube.cpos] - }; -} - -Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -uint64_t -cphtr(Cube cube) -{ - return cphtr_cosets[cube.cp]; -} - -uint64_t -epos_dependent(Cube c) -{ - return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -void -genalgset(AlgSet *as) -{ - uint64_t i; - - if (as->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - as->table = malloc(as->size * sizeof(AlgList *)); - - if (read_algset_file(as)) { - as->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", as->filename); - - for (i = 0; i < as->size; i++) { - as->table[i] = solve(as->antindex(i), as->step, &as->opts); - fprintf(stderr, "Generated %lu / %lu cases\n", i, as->size); - } - - if (!write_algset_file(as)) - fprintf(stderr, "Error writing algset file\n"); - - as->generated = true; -} - -void -genptable(PruneData *pd) -{ - uint64_t j; - DfsData dd = { - .m = 0, - .last1 = NULLMOVE, - .last2 = NULLMOVE - }; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->size; j++) - ptable_update(pd, j, 15); - - moveset_to_list(pd->moveset, NULL, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - pd->reached = malloc(ptablesize(pd) * sizeof(uint8_t)); - for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { - memset(pd->reached, 0, ptablesize(pd)*sizeof(uint8_t)); - genptable_dfs((Cube){0}, pd, &dd); - fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", - dd.d, pd->n, pd->size); - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; - free(pd->reached); -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - Trans i; - - if (reorient) - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(trans_algs[i],cube), false)) - return true; - - return equal(cube, (Cube){0}); -} - -bool -is_solved_block(Cube cube, Block block) -{ - int i; - - for (i = 0; i < 12; i++) - if (block.edge[i] && !is_solved_edge(cube, i)) - return false; - for (i = 0; i < 8; i++) - if (block.corner[i] && !is_solved_corner(cube, i)) - return false; - for (i = 0; i < 6; i++) - if (block.center[i] && !is_solved_center(cube, i)) - return false; - - return true; -} - -bool -is_solved_center(Cube cube, Center c) -{ - return what_center_at(cube, c) == c; -} - -bool -is_solved_corner(Cube cube, Corner c) -{ - return what_corner_at(cube, c) == c && - what_orientation_corner(cube.coud, c); -} - -bool -is_solved_edge(Cube cube, Edge e) -{ - return what_edge_at(cube, e) == e && - what_orientation_edge(cube.eofb, e); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b, x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ -/* - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -*/ - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[what_edge_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %d ", what_orientation_edge(cube.eofb, i)); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[what_corner_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %d ", what_orientation_corner(cube.coud, i)); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[what_center_at(cube, i)]); - printf("\n"); - -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - AlgListNode *node; - AlgList *sols = new_alglist(); - Cube c = apply_trans(opts->pre_trans, cube); - DfsData dd = { - .m = 0, - .niss = false, - .lb = -1, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && step.ready(c, 1) != 0) { - fprintf(stderr, "Cube not ready for solving step\n"); - return sols; - } - - moveset_to_list(step.moveset, step.check, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = opts->min_moves; - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - if (opts->feedback) - fprintf(stderr, - "Found %d solutions, searching depth %d...\n", - sols->len, dd.d); - dfs(c, step, opts, &dd); - } - - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans_aux[opts->pre_trans], node->alg); - - free_alg(dd.current_alg); - return sols; -} - -Alg * -inverse_alg(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = alg->len-1; i >= 0; i--) - append_move(ret, alg->move[i], alg->inv[i]); - - return ret; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - /* TODO: make it possible to print to stdout or to string */ - /* Maybe just return a string */ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - for (i = 0; i < 16; i++) - a[i] = 0; - - if (!pd->generated) - genptable(pd); - - for (i = 0; i < pd->size; i++) - a[ptableval(pd, i)]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -uint64_t -ptablesize(PruneData *pd) -{ - return (pd->size + 1) / 2; -} - -int -ptableval(PruneData *pd, uint64_t ind) -{ - return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; -} - - -Alg * -trans_alg(Trans i) -{ - return trans_algs[i]; -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} - -Center -what_center_at(Cube cube, Center c) -{ - return what_center_at_aux[cube.cpos][c]; -} - -Corner -what_corner_at(Cube cube, Corner c) -{ - return what_corner_at_aux[cube.cp][c]; -} - -Edge -what_edge_at(Cube cube, Edge e) -{ - Edge ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - - free_cubearray(arr, pf_ep); - return ret; -} - -int -what_orientation_corner(int co, Corner c) -{ - if (c < 7) - return (co / powint(3, c)) % 3; - else - return what_orientation_last_corner_aux[co]; -} - -int -what_orientation_edge(int eo, Edge e) -{ - if (e < 11) - return (eo & (1 << e)) ? 1 : 0; - else - return what_orientation_last_edge_aux[eo]; -} - -Center -where_is_center(Cube cube, Center c) -{ - return where_is_center_aux[cube.cpos][c]; -} - -Corner -where_is_corner(Cube cube, Corner c) -{ - return where_is_corner_aux[cube.cp][c]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_cphtr_cosets(); - init_trans_aux(); - init_trans(); -} - diff --git a/old/2021-06-23-realizing-bad-tables/cube.h b/old/2021-06-23-realizing-bad-tables/cube.h @@ -1,88 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> - -/* Constants and macros *****************************************************/ - -#define POW2TO6 64ULL -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL7 5040ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define NMOVES (z3+1) -#define NTRANS (mirror+1) -#define NROTATIONS (NTRANS-1) - -/* Type definitions **********************************************************/ - -#include "cubetypes.h" - -/* Public functions **********************************************************/ - -Cube apply_alg(Alg *alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -uint64_t cphtr(Cube cube); -uint64_t epos_dependent(Cube cube); -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_admissible(Cube cube); -bool is_solved(Cube cube, bool reorient); -bool is_solved_center(Cube cube, Center c); -bool is_solved_corner(Cube cube, Corner c); -bool is_solved_edge(Cube cube, Edge e); -void print_cube(Cube cube); -Cube random_cube(); -AlgList * solve(Cube cube, Step step, SolveOptions *opts); -Center what_center_at(Cube cube, Center c); -Corner what_corner_at(Cube cube, Corner c); -Edge what_edge_at(Cube cube, Edge e); -int what_orientation_corner(int co, Corner c); -int what_orientation_edge(int eo, Edge e); -Center where_is_center(Cube cube, Center c); -Corner where_is_corner(Cube cube, Corner c); -Edge where_is_edge(Cube cube, Edge e); - -Move base_move(Move m); -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Alg * new_alg(char *str); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); -Alg * trans_alg(Trans i); -void transform_alg(Trans t, Alg *alg); - -void genalgset(AlgSet *as); -void genptable(PruneData *pd); -void print_ptable(PruneData *pd); -uint64_t ptablesize(PruneData *pd); -int ptableval(PruneData *pd, uint64_t ind); - -void init(); - -#endif - diff --git a/old/2021-06-23-realizing-bad-tables/cubetypes.h b/old/2021-06-23-realizing-bad-tables/cubetypes.h @@ -1,224 +0,0 @@ -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct algset AlgSet; -typedef struct block Block; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; - -typedef Cube (*AntiIndexer) (uint64_t); -typedef int (*Checker) (Cube, int); -typedef uint64_t (*Indexer) (Cube); -typedef bool (*Moveset) (Move); - - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - mirror, /* R|L */ -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - Move * move; - bool * inv; - int len; - int allocated; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -cube -{ - int epose; - int eposs; - int eposm; - int eofb; - int eorl; - int eoud; - int cp; - int coud; - int cofb; - int corl; - int cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -dfsdata -{ - int d; - int m; - int lb; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[NMOVES]; - int move_position[NMOVES]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - uint8_t * reached; - bool generated; - uint64_t n; - uint64_t size; - Indexer index; - Moveset moveset; -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; - Trans pre_trans; -}; - -struct -step -{ - Checker check; - Checker ready; - Moveset moveset; -}; - -/* TODO: I put it here because it needs the definition of Step, sort it out */ -struct -algset -{ - char * filename; - AlgList ** table; - bool generated; - uint64_t size; - Indexer index; - AntiIndexer antindex; - Step step; - SolveOptions opts; -}; diff --git a/old/2021-06-23-realizing-bad-tables/main.c b/old/2021-06-23-realizing-bad-tables/main.c @@ -1,70 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "steps.h" - -int main() { - Alg *algo; - AlgList *sols; - Cube cube; - SolveOptions opts; - char line[1000]; - int i, ns = 3; -/* int nrand = 10000, sum1, sum2, sum3;*/ - - Step *stps[20] = {&corners_HTM, &eofb_HTM, &optimal_HTM}; - char sss[30][30] = {"Corners", "EO on F/B", "Optimal solution"}; - - opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 20, - .optimal_only = true, - .max_solutions = 1, - .can_niss = false, - .feedback = true, - .pre_trans = uf - }; - - init(); - - print_ptable(&pd_corners_HTM); - -/* - srand(time(NULL)); - sum1 = 0; - sum2 = 0; - sum3 = 0; - for (i = 0; i < nrand; i++) { - cube = random_cube(); - sum1 += corners_HTM.check(cube, 20); - sum2 += cornershtr_HTM.check(cube, 20); - sum3 += optimal_HTM.check(cube, 20); - } - printf("Average corners pruning: %lf\n", ((double)sum1) / ((double) nrand)); - printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); - printf("Average optimal pruning: %lf\n", ((double)sum3) / ((double) nrand)); -*/ - - printf("Welcome to nissy 2.0! Insert a scramble:\n"); - - if (fgets(line, 1000, stdin) != NULL) { - algo = new_alg(line); - cube = apply_alg(algo, (Cube){0}); - - print_cube(cube); - printf("Index: %lu\n", pd_cornershtr_HTM.index(cube)); - - for (i = 0; i < ns; i++) { - if (stps[i]->check == NULL) - fprintf(stderr, "Check function for step %d is null\n", i); - printf("Check: %d\n", stps[i]->check(cube, 20)); - sols = solve(cube, *stps[i], &opts); - printf("%s: %d solutions found:\n", sss[i], sols->len); - print_alglist(sols, true); - free_alglist(sols); - } - free_alg(algo); - } - - return 0; -} - diff --git a/old/2021-06-23-realizing-bad-tables/steps.c b/old/2021-06-23-realizing-bad-tables/steps.c @@ -1,486 +0,0 @@ -#include "steps.h" - -/* Check functions ***********************************************************/ - -static int check_nothing(Cube cube, int target); -static int check_centers(Cube cube, int target); -static int check_eofb_HTM(Cube cube, int target); -static int check_coud_HTM(Cube cube, int target); -static int check_coud_URF(Cube cube, int target); -static int check_corners_HTM(Cube cube, int target); -static int check_cornershtr_HTM(Cube cube, int target); -static int check_corners_URF(Cube cube, int target); -static int check_cornershtr_URF(Cube cube, int target); -static int check_ep_HTM(Cube cube, int target); -static int check_edges_HTM(Cube cube, int target); -static int check_drud_HTM(Cube cube, int target); -static int check_optimal_HTM(Cube cube, int target); -static int check_corners6eo_HTM(Cube cube, int target); -static int check_tripleeo_HTM(Cube cube, int target); - - -/* Index functions ***********************************************************/ - -static uint64_t index_eofb(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_cornershtr(Cube cube); -static uint64_t index_ep(Cube cube); -static uint64_t index_drud(Cube cube); -static uint64_t index_corners6eo(Cube cube); -static uint64_t index_tripleeo(Cube cube); - - -/* Steps *********************************************************************/ - -Step -eofb_HTM = { - .check = check_eofb_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_HTM = { - .check = check_coud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_URF = { - .check = check_coud_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_HTM = { - .check = check_corners_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_HTM = { - .check = check_cornershtr_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_URF = { - .check = check_cornershtr_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_URF = { - .check = check_corners_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -edges_HTM = { - .check = check_edges_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -drud_HTM = { - .check = check_drud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -optimal_HTM = { - .check = check_optimal_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -tripleeo_HTM = { - .check = check_tripleeo_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - - -/* Blocks ********************************************************************/ - -Block -block_223dl = { - .edge = { [DF] = 1, [DL] = 1, [DB] = 1, [FL] = 1, [BL] = 1 }, - .corner = { [DFL] = 1, [DBL] = 1 }, - .center = { [D_center] = 1, [L_center] = 1 } -}; - - -/* Pruning tables ************************************************************/ - -PruneData -pd_eofb_HTM = { - .filename = "ptable_eofb_HTM", - .size = POW2TO11, - .index = index_eofb, - .moveset = moveset_HTM -}; - -PruneData -pd_coud_HTM = { - .filename = "ptable_coud_HTM", - .size = POW3TO7, - .index = index_coud, - .moveset = moveset_HTM -}; - -PruneData -pd_cornershtr_HTM = { - .filename = "ptable_cornershtr_HTM", - .size = POW3TO7 * BINOM8ON4 * 6, /*TODO: check */ - .index = index_cornershtr, - .moveset = moveset_HTM -}; - -PruneData -pd_corners_HTM = { - .filename = "ptable_corners_HTM", - .size = POW3TO7 * FACTORIAL8, - .index = index_corners, - .moveset = moveset_HTM -}; - -PruneData -pd_ep_HTM = { - .filename = "ptable_ep_HTM", - .size = FACTORIAL12, - .index = index_ep, - .moveset = moveset_HTM -}; - -PruneData -pd_drud_HTM = { - .filename = "ptable_drud_HTM", - .size = POW2TO11 * POW3TO7 * BINOM12ON4, - .index = index_drud, - .moveset = moveset_HTM -}; - -PruneData -pd_corners6eo_HTM = { - .filename = "ptable_corners6eo_HTM", - .size = POW2TO6 * POW3TO7 * FACTORIAL8, - .index = index_corners6eo, - .moveset = moveset_HTM -}; - -PruneData -pd_tripleeo_HTM = { - .filename = "ptable_tripleeo_HTM", - .size = BINOM12ON4 * BINOM8ON4 * POW2TO11, - .index = index_tripleeo, - .moveset = moveset_HTM -}; - - -/* Alg sets ******************************************************************/ - -/* TODO: remove this (I am only keeping it as an example for future algesets) -AlgSet -as_ephtr_HTM = { - .filename = "algset_ephtr_HTM", - .size = FACTORIAL4 * FACTORIAL4 * FACTORIAL4, - .index = index_ephtr, - .antindex = index_to_cube_ephtr, - .step = (Step) { - .check = check_optimal_HTM, - .ready = check_htr_solved_corners_HTM, - .moveset = moveset_HTM - }, - .opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 20, - .max_solutions = 1, - .optimal_only = true, - .can_niss = false, - .feedback = true, - .pre_trans = uf - } -}; -*/ - - -/* Check functions implementation ********************************************/ - -static int -check_nothing(Cube cube, int target) -{ - return 0; -} - -static int -check_centers(Cube cube, int target) -{ - return (cube.cpos == 0) ? 0 : 1; -} - -static int -check_eofb_HTM(Cube cube, int target) -{ - if (!pd_eofb_HTM.generated) - genptable(&pd_eofb_HTM); - - return ptableval(&pd_eofb_HTM, cube.eofb); -} - -static int -check_coud_HTM(Cube cube, int target) -{ - if (!pd_coud_HTM.generated) - genptable(&pd_coud_HTM); - - return ptableval(&pd_coud_HTM, cube.coud); -} - -static int -check_coud_URF(Cube cube, int target) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - int ud = check_coud_HTM(cube, target); - int rl = check_coud_HTM(apply_move(z, cube), target); - int fb = check_coud_HTM(apply_move(x, cube), target); - - return MIN(ud, MIN(rl, fb)); -} - -static int -check_corners_HTM(Cube cube, int target) -{ - if (!pd_corners_HTM.generated) - genptable(&pd_corners_HTM); - - return ptableval(&pd_corners_HTM, index_corners(cube)); -} - -static int -check_cornershtr_HTM(Cube cube, int target) -{ - if (!pd_cornershtr_HTM.generated) - genptable(&pd_cornershtr_HTM); - - return ptableval(&pd_cornershtr_HTM, index_cornershtr(cube)); -} - -static int -check_cornershtr_URF(Cube cube, int target) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - c = check_cornershtr_HTM(apply_alg(trans_alg(i),cube), target); - ret = MIN(ret, c); - } - - return ret; -} - -static int -check_corners_URF(Cube cube, int target) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) - ret = MIN(ret, check_corners_HTM( - apply_alg(trans_alg(i), cube), target)); - - return ret; -} - -static int -check_ep_HTM(Cube cube, int target) -{ - if (!pd_ep_HTM.generated) - genptable(&pd_ep_HTM); - - return ptableval(&pd_ep_HTM, index_ep(cube)); -} - -static int -check_edges_HTM(Cube cube, int target) -{ - return MAX(check_ep_HTM(cube, target), - check_tripleeo_HTM(cube, target)); -} - -static int -check_drud_HTM(Cube cube, int target) -{ - if (!pd_drud_HTM.generated) - genptable(&pd_drud_HTM); - - return ptableval(&pd_drud_HTM, index_drud(cube)); -} - -static int -check_optimal_HTM(Cube cube, int target) -{ - int dr1, dr2, dr3, cor, ret; - Cube cube2, cube3; - - dr1 = check_drud_HTM(cube, target); - /*cor = check_corners6eo_HTM(cube, target);*/ - cor = check_corners_HTM(cube, target); - ret = MAX(dr1, cor); - - if (ret > target) - return ret; - - cube2 = apply_trans(rf, cube); - dr2 = check_drud_HTM(cube2, target); - /*cor = check_corners6eo_HTM(cube2, target); - ret = MAX(ret, MAX(dr2, cor));*/ - ret = MAX(ret, dr2); - - if (ret > target) - return ret; - - cube3 = apply_trans(bd, cube); - dr3 = check_drud_HTM(cube3, target); - /*cor = check_corners6eo_HTM(cube3, target);*/ - - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - dr3++; - - /*ret = MAX(ret, MAX(dr3, cor));*/ - ret = MAX(ret, dr3); - - if (ret == 0) - return (!cube.epose && !cube.eposs && !cube.eposm) ? 0 : 6; - - return ret; -} - -static int -check_corners6eo_HTM(Cube cube, int target) -{ - if (!pd_corners6eo_HTM.generated) - genptable(&pd_corners6eo_HTM); - - return ptableval(&pd_corners6eo_HTM, index_corners6eo(cube)); -} - -static int -check_tripleeo_HTM(Cube cube, int target) -{ - if (!pd_tripleeo_HTM.generated) - genptable(&pd_tripleeo_HTM); - - return ptableval(&pd_tripleeo_HTM, index_tripleeo(cube)); -} - - -/* Index functions implementation ********************************************/ - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_cornershtr(Cube cube) -{ - return cube.coud * BINOM8ON4 * 6 + cphtr(cube); -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_ep(Cube cube) -{ - uint64_t a, b, c; - - a = cube.epose; - b = (cube.eposs % FACTORIAL4) + epos_dependent(cube)*FACTORIAL4; - c = cube.eposm % FACTORIAL4; - - b *= FACTORIAL4 * BINOM12ON4; - c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; - - return a + b + c; -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -static uint64_t -index_corners6eo(Cube cube) -{ - return (cube.coud*FACTORIAL8 + cube.cp)*POW2TO6 + (cube.eofb%POW2TO6); -} - -static uint64_t -index_tripleeo(Cube cube) -{ - uint64_t ee, es; - - ee = cube.epose / FACTORIAL4; - es = epos_dependent(cube); - - return (ee * BINOM8ON4 + es) * POW2TO11 + cube.eofb; -} - - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - diff --git a/old/2021-06-23-realizing-bad-tables/steps.h b/old/2021-06-23-realizing-bad-tables/steps.h @@ -1,42 +0,0 @@ -#ifndef STEPS_H -#define STEPS_H - -#include "cube.h" - -/* Steps *********************************************************************/ - -extern Step eofb_HTM; -extern Step coud_HTM; -extern Step coud_URF; -extern Step corners_HTM; -extern Step cornershtr_HTM; -extern Step corners_URF; -extern Step cornershtr_URF; -extern Step edges_HTM; -extern Step drud_HTM; -extern Step optimal_HTM; -extern Step tripleeo_HTM; - -/* Blocks ********************************************************************/ - -extern Block block_223dl; - -/* Pruning tables ************************************************************/ - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_cornershtr_HTM; -extern PruneData pd_ep_HTM; -extern PruneData pd_drud_HTM; -extern PruneData pd_tripleeo_HTM; - -/* Alg sets ******************************************************************/ - - -/* Movesets ******************************************************************/ - -bool moveset_HTM(Move m); -bool moveset_URF(Move m); - -#endif diff --git a/old/2021-06-23-uint16t/cube.c b/old/2021-06-23-uint16t/cube.c @@ -1,2762 +0,0 @@ -#include "cube.h" - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static bool allowed_next(Move move, DfsData *dd); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static uint16_t array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); -static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent(int pos1, int pos2); -static uint16_t epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(uint16_t epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); -static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void movelist_to_position(Move *movelist, int *position); -static void moveset_to_list(Moveset ms, Checker f, Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static bool ptable_has_reached(PruneData *pd, uint64_t ind); -static void ptable_set_reached(PruneData *pd, uint64_t ind); -static void ptable_update(PruneData *pd, uint64_t ind, int m); -static void realloc_alg(Alg *alg, int n); -static bool read_algset_file(AlgSet *as); -static bool read_mtables_file(); -static bool read_ptable_file(PruneData *pd); -static bool read_ttables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_algset_file(AlgSet *as); -static bool write_mtables_file(); -static bool write_ptable_file(PruneData *pd); -static bool write_ttables_file(); - -static void init_auxtables(); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_strings(); -static void init_trans(); -static void init_trans_aux(); - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; -static Center what_center_at_aux[FACTORIAL6][6]; -static Corner what_corner_at_aux[FACTORIAL8][8]; -static int what_orientation_last_corner_aux[POW3TO7]; -static int what_orientation_last_edge_aux[POW2TO11]; -static Center where_is_center_aux[FACTORIAL6][6]; -static Corner where_is_corner_aux[FACTORIAL8][8]; -static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; - -static uint16_t epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static uint16_t eo_ttable[NTRANS][POW2TO11]; -static uint16_t cp_ttable[NTRANS][FACTORIAL8]; -static uint16_t co_ttable[NTRANS][POW3TO7]; -static uint16_t cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static uint16_t epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static uint16_t eofb_mtable[NMOVES][POW2TO11]; -static uint16_t eorl_mtable[NMOVES][POW2TO11]; -static uint16_t eoud_mtable[NMOVES][POW2TO11]; -static uint16_t cp_mtable[NMOVES][FACTORIAL8]; -static uint16_t coud_mtable[NMOVES][POW3TO7]; -static uint16_t cofb_mtable[NMOVES][POW3TO7]; -static uint16_t corl_mtable[NMOVES][POW3TO7]; -static uint16_t cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * trans_algs[NROTATIONS]; - - -/* Local functions implementation ********************************************/ - -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static bool -allowed_next(Move move, DfsData *dd) -{ - if (!possible_next[dd->last2][dd->last1][move]) - return false; - - if (commute[dd->last1][move]) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -} - -static 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; -} - -static 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 Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static uint16_t -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -static void -dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - if (dfs_stop(c, s, opts, dd)) - return; - - if (dfs_check_solved(opts, dd)) - return; - - dfs_branch(c, s, opts, dd); - - if (opts->can_niss && !dd->niss) - dfs_niss(c, s, opts, dd); -} - -static void -dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; - - int i, maxnsol = opts->max_solutions; - - for (i = 0; (m=moves[i]) != NULLMOVE && dd->sols->len < maxnsol; i++) { - if (allowed_next(m, dd)) { - dd->last2 = dd->last1; - dd->last1 = m; - append_move(dd->current_alg, m, dd->niss); - - dfs(apply_move(m, c), s, opts, dd); - - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } -} - -static bool -dfs_check_solved(SolveOptions *opts, DfsData *dd) -{ - if (dd->lb != 0) - return false; - - if (dd->current_alg->len == dd->d) { - append_alg(dd->sols, dd->current_alg); - - if (opts->feedback) - print_alg(dd->current_alg, false); - } - - return true; -} - -static void -dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move l1 = dd->last1, l2 = dd->last2; - - if (dd->current_alg->len == 0 || - (s.check(apply_move(inverse_move(l1), (Cube){0}), 1))) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - - dfs(inverse_cube(c), s, opts, dd); - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = false; - } -} - -static bool -dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - if (dd->sols->len >= opts->max_solutions) - return true; - - dd->lb = s.check(c, dd->d - dd->current_alg->len); - if (opts->can_niss && !dd->niss) - dd->lb = MIN(1, dd->lb); - - if (dd->current_alg->len + dd->lb > dd->d) - return true; - - return false; -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 0) - ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; - - swap(&ep8[1], &ep8[4]); - swap(&ep8[3], &ep8[6]); - - return subset_to_index(ep8, 8, 4); -} - -static uint16_t -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(uint16_t epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -genptable_dfs(Cube c, PruneData *pd, DfsData *dd) -{ - uint64_t ind = pd->index(c); - int oldval = ptableval(pd, ind); - - if (oldval < dd->m || ptable_has_reached(pd, ind) || pd->n == pd->size) - return; - - ptable_set_reached(pd, ind); - - if (dd->m == dd->d) { - if (dd->m < oldval) - ptable_update(pd, ind, dd->m); - return; - } - - genptable_dfs_branch(c, pd, dd); -} - -static void -genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) -{ - Move i, move, l1 = dd->last1, l2 = dd->last2; - - dd->m++; - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (allowed_next(move, dd)) { - dd->last2 = dd->last1; - dd->last1 = move; - - genptable_dfs(apply_move(move, c), pd, dd); - - dd->last2 = l2; - dd->last1 = l1; - } - } - - dd->m--; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -static void -moveset_to_list(Moveset ms, Checker f, Move *r) -{ - Cube c; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - c = apply_move(i, (Cube){0}); - if (f != NULL && f(c, 1)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static bool -ptable_has_reached(PruneData *pd, uint64_t ind) -{ - return ind % 2 ? pd->reached[ind/2] / 16 : pd->reached[ind/2] % 16; -} - -static void -ptable_set_reached(PruneData *pd, uint64_t ind) -{ - uint8_t oldval2 = pd->reached[ind/2]; - int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; - - pd->reached[ind/2] = ind % 2 ? 16 + other : 16*other + 1; -} - -static void -ptable_update(PruneData *pd, uint64_t ind, int n) -{ - uint8_t oldval2 = pd->ptable[ind/2]; - int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = ind % 2 ? 16*n + other : 16*other + n; - pd->n++; -} - -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; -} - -static bool -read_algset_file(AlgSet *as) -{ - return false; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(uint16_t); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return r == ptablesize(pd); -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(uint16_t); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - Alg *inv; - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Cube ret; - - if (r != mirror) { - ret = apply_alg_generic(trans_algs[r], c, f, true); - inv = on_inverse(trans_algs[r]); - ret = apply_alg_generic(inv, ret, f, true); - free_alg(inv); - } else { - ret = move_via_arrays(&ma, (Cube){0}, f); - ret = compose_filtered(c, ret, f); - ret = move_via_arrays(&ma, ret, f); - } - - return ret; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_algset_file(AlgSet *as) -{ - return false; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(uint16_t); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return written == ptablesize(pd); -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(uint16_t); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - CubeArray *arr; - uint64_t ui, uj; - int i, j, k, auxarr[12]; - bool cij, p1, p2; - - for (ui = 0; ui < FACTORIAL6; ui++) { - arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); - for (i = 0; i < 6; i++) { - what_center_at_aux[ui][i] = arr->cpos[i]; - where_is_center_aux[ui][arr->cpos[i]] = i; - } - free_cubearray(arr, pf_cpos); - } - - for (ui = 0; ui < FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.cp = ui}, pf_cp); - for (i = 0; i < 8; i++) { - what_corner_at_aux[ui][i] = arr->cp[i]; - where_is_corner_aux[ui][arr->cp[i]] = i; - } - free_cubearray(arr, pf_cp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.epose = ui}, pf_e); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 0) - where_is_edge_aux[0][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_e); - - arr = new_cubearray((Cube){.eposs = ui}, pf_s); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 1) - where_is_edge_aux[1][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_s); - - arr = new_cubearray((Cube){.eposm = ui}, pf_m); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 2) - where_is_edge_aux[2][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_m); - } - - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, auxarr); - what_orientation_last_corner_aux[ui] = auxarr[7]; - } - - for (ui = 0; ui < POW2TO11; ui++) { - int_to_sum_zero_array(ui, 2, 12, auxarr); - what_orientation_last_edge_aux[ui] = auxarr[11]; - } - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj] = epos_dependent(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2) && i && j; - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[mirror] = mirror; -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - uint16_t ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray) { - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_trans() { - Cube aux, cube, c[3]; - CubeArray epcp; - int eparr[12], eoarr[12]; - int cparr[8], coarr[8]; - int i; - bool b1, b2, b3; - uint16_t ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - if (i == mirror) - cube = (Cube){0}; - else - cube = apply_alg(trans_algs[i], (Cube){0}); - - epose_source[i] = edge_slice(what_edge_at(cube, FR)); - eposs_source[i] = edge_slice(what_edge_at(cube, UR)); - eposm_source[i] = edge_slice(what_edge_at(cube, UF)); - eofb_source[i] = what_center_at(cube, F_center)/2; - eorl_source[i] = what_center_at(cube, R_center)/2; - eoud_source[i] = what_center_at(cube, U_center)/2; - coud_source[i] = what_center_at(cube, U_center)/2; - cofb_source[i] = what_center_at(cube, F_center)/2; - corl_source[i] = what_center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - if (m == mirror) { - memcpy(eparr, ep_mirror, 12 * sizeof(int)); - memcpy(cparr, cp_mirror, 8 * sizeof(int)); - } else { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(trans_algs[m], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m == mirror) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - if (m == mirror) { - b1 = (mi >= U && mi <= Bw3); - b2 = (mi >= S && mi <= E3); - b3 = (mi >= x && mi <= z3); - if (b1 || b2 || b3) - moves_ttable[m][mi] = - inverse_move_aux[mi]; - else - moves_ttable[m][mi] = mi; - - if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) - moves_ttable[m][mi] += 3; - if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) - moves_ttable[m][mi] -= 3; - } else { - aux = apply_trans(m, apply_move(mi,(Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move( - inverse_move_aux[move], aux); - if (is_solved(cube, false)) - moves_ttable[m][mi] = move; - } - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - trans_algs[uf] = new_alg(""); - trans_algs[ur] = new_alg("y"); - trans_algs[ub] = new_alg("y2"); - trans_algs[ul] = new_alg("y3"); - - trans_algs[df] = new_alg("z2"); - trans_algs[dr] = new_alg("y z2"); - trans_algs[db] = new_alg("x2"); - trans_algs[dl] = new_alg("y3 z2"); - - trans_algs[rf] = new_alg("z3"); - trans_algs[rd] = new_alg("z3 y"); - trans_algs[rb] = new_alg("z3 y2"); - trans_algs[ru] = new_alg("z3 y3"); - - trans_algs[lf] = new_alg("z"); - trans_algs[ld] = new_alg("z y3"); - trans_algs[lb] = new_alg("z y2"); - trans_algs[lu] = new_alg("z y"); - - trans_algs[fu] = new_alg("x y2"); - trans_algs[fr] = new_alg("x y"); - trans_algs[fd] = new_alg("x"); - trans_algs[fl] = new_alg("x y3"); - - trans_algs[bu] = new_alg("x3"); - trans_algs[br] = new_alg("x3 y"); - trans_algs[bd] = new_alg("x3 y2"); - trans_algs[bl] = new_alg("x3 y3"); -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - return (Cube) { - .epose = epose_mtable[m][cube.epose], - .eposs = eposs_mtable[m][cube.eposs], - .eposm = eposm_mtable[m][cube.eposm], - .eofb = eofb_mtable[m][cube.eofb], - .eorl = eorl_mtable[m][cube.eorl], - .eoud = eoud_mtable[m][cube.eoud], - .coud = coud_mtable[m][cube.coud], - .cofb = cofb_mtable[m][cube.cofb], - .corl = corl_mtable[m][cube.corl], - .cp = cp_mtable[m][cube.cp], - .cpos = cpos_mtable[m][cube.cpos] - }; -} - -Cube -apply_trans(Trans t, Cube cube) -{ - uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - return (Cube) { - .epose = epose_ttable[t][aux_epos[epose_source[t]]], - .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], - .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], - .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], - .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], - .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], - .coud = co_ttable[t][aux_co[coud_source[t]]], - .corl = co_ttable[t][aux_co[corl_source[t]]], - .cofb = co_ttable[t][aux_co[cofb_source[t]]], - .cp = cp_ttable[t][cube.cp], - .cpos = cpos_ttable[t][cube.cpos] - }; -} - -Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -uint64_t -epos_dependent_cube(Cube c) -{ - return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -void -genalgset(AlgSet *as) -{ - uint64_t i; - - if (as->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - as->table = malloc(as->size * sizeof(AlgList *)); - - if (read_algset_file(as)) { - as->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", as->filename); - - for (i = 0; i < as->size; i++) { - as->table[i] = solve(as->antindex(i), as->step, &as->opts); - fprintf(stderr, "Generated %lu / %lu cases\n", i, as->size); - } - - if (!write_algset_file(as)) - fprintf(stderr, "Error writing algset file\n"); - - as->generated = true; -} - -void -genptable(PruneData *pd) -{ - uint64_t j; - DfsData dd = { - .m = 0, - .last1 = NULLMOVE, - .last2 = NULLMOVE - }; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->size; j++) - ptable_update(pd, j, 15); - - moveset_to_list(pd->moveset, NULL, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - pd->reached = malloc(ptablesize(pd) * sizeof(uint8_t)); - for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { - memset(pd->reached, 0, ptablesize(pd)*sizeof(uint8_t)); - genptable_dfs((Cube){0}, pd, &dd); - fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", - dd.d, pd->n, pd->size); - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; - free(pd->reached); -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - Trans i; - - if (reorient) - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(trans_algs[i],cube), false)) - return true; - - return equal(cube, (Cube){0}); -} - -bool -is_solved_block(Cube cube, Block block) -{ - int i; - - for (i = 0; i < 12; i++) - if (block.edge[i] && !is_solved_edge(cube, i)) - return false; - for (i = 0; i < 8; i++) - if (block.corner[i] && !is_solved_corner(cube, i)) - return false; - for (i = 0; i < 6; i++) - if (block.center[i] && !is_solved_center(cube, i)) - return false; - - return true; -} - -bool -is_solved_center(Cube cube, Center c) -{ - return what_center_at(cube, c) == c; -} - -bool -is_solved_corner(Cube cube, Corner c) -{ - return what_corner_at(cube, c) == c && - what_orientation_corner(cube.coud, c); -} - -bool -is_solved_edge(Cube cube, Edge e) -{ - return what_edge_at(cube, e) == e && - what_orientation_edge(cube.eofb, e); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b; - uint16_t x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ -/* - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -*/ - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[what_edge_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %d ", what_orientation_edge(cube.eofb, i)); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[what_corner_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %d ", what_orientation_corner(cube.coud, i)); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[what_center_at(cube, i)]); - printf("\n"); - -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - AlgListNode *node; - AlgList *sols = new_alglist(); - Cube c = apply_trans(opts->pre_trans, cube); - DfsData dd = { - .m = 0, - .niss = false, - .lb = -1, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && step.ready(c, 1) != 0) { - fprintf(stderr, "Cube not ready for solving step\n"); - return sols; - } - - moveset_to_list(step.moveset, step.check, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = opts->min_moves; - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - if (opts->feedback) - fprintf(stderr, - "Found %d solutions, searching depth %d...\n", - sols->len, dd.d); - dfs(c, step, opts, &dd); - } - - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans_aux[opts->pre_trans], node->alg); - - free_alg(dd.current_alg); - return sols; -} - -Alg * -inverse_alg(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = alg->len-1; i >= 0; i--) - append_move(ret, alg->move[i], alg->inv[i]); - - return ret; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - /* TODO: make it possible to print to stdout or to string */ - /* Maybe just return a string */ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - for (i = 0; i < 16; i++) - a[i] = 0; - - if (!pd->generated) - genptable(pd); - - for (i = 0; i < pd->size; i++) - a[ptableval(pd, i)]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -uint64_t -ptablesize(PruneData *pd) -{ - return (pd->size + 1) / 2; -} - -int -ptableval(PruneData *pd, uint64_t ind) -{ - return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; -} - - -Alg * -trans_alg(Trans i) -{ - return trans_algs[i]; -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} - -Center -what_center_at(Cube cube, Center c) -{ - return what_center_at_aux[cube.cpos][c]; -} - -Corner -what_corner_at(Cube cube, Corner c) -{ - return what_corner_at_aux[cube.cp][c]; -} - -Edge -what_edge_at(Cube cube, Edge e) -{ - Edge ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - - free_cubearray(arr, pf_ep); - return ret; -} - -int -what_orientation_corner(int co, Corner c) -{ - if (c < 7) - return (co / powint(3, c)) % 3; - else - return what_orientation_last_corner_aux[co]; -} - -int -what_orientation_edge(int eo, Edge e) -{ - if (e < 11) - return (eo & (1 << e)) ? 1 : 0; - else - return what_orientation_last_edge_aux[eo]; -} - -Center -where_is_center(Cube cube, Center c) -{ - return where_is_center_aux[cube.cpos][c]; -} - -Corner -where_is_corner(Cube cube, Corner c) -{ - return where_is_corner_aux[cube.cp][c]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_trans_aux(); - init_trans(); -} - diff --git a/old/2021-06-23-uint16t/cube.h b/old/2021-06-23-uint16t/cube.h @@ -1,87 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> - -/* Constants and macros *****************************************************/ - -#define POW2TO6 64ULL -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL7 5040ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define NMOVES (z3+1) -#define NTRANS (mirror+1) -#define NROTATIONS (NTRANS-1) - -/* Type definitions **********************************************************/ - -#include "cubetypes.h" - -/* Public functions **********************************************************/ - -Cube apply_alg(Alg *alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -uint64_t epos_dependent_cube(Cube cube); -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_admissible(Cube cube); -bool is_solved(Cube cube, bool reorient); -bool is_solved_center(Cube cube, Center c); -bool is_solved_corner(Cube cube, Corner c); -bool is_solved_edge(Cube cube, Edge e); -void print_cube(Cube cube); -Cube random_cube(); -AlgList * solve(Cube cube, Step step, SolveOptions *opts); -Center what_center_at(Cube cube, Center c); -Corner what_corner_at(Cube cube, Corner c); -Edge what_edge_at(Cube cube, Edge e); -int what_orientation_corner(int co, Corner c); -int what_orientation_edge(int eo, Edge e); -Center where_is_center(Cube cube, Center c); -Corner where_is_corner(Cube cube, Corner c); -Edge where_is_edge(Cube cube, Edge e); - -Move base_move(Move m); -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Alg * new_alg(char *str); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); -Alg * trans_alg(Trans i); -void transform_alg(Trans t, Alg *alg); - -void genalgset(AlgSet *as); -void genptable(PruneData *pd); -void print_ptable(PruneData *pd); -uint64_t ptablesize(PruneData *pd); -int ptableval(PruneData *pd, uint64_t ind); - -void init(); - -#endif - diff --git a/old/2021-06-23-uint16t/cubetypes.h b/old/2021-06-23-uint16t/cubetypes.h @@ -1,224 +0,0 @@ -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct algset AlgSet; -typedef struct block Block; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; - -typedef Cube (*AntiIndexer) (uint64_t); -typedef int (*Checker) (Cube, int); -typedef uint64_t (*Indexer) (Cube); -typedef bool (*Moveset) (Move); - - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - mirror, /* R|L */ -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - Move * move; - bool * inv; - int len; - int allocated; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -cube -{ - uint16_t epose; - uint16_t eposs; - uint16_t eposm; - uint16_t eofb; - uint16_t eorl; - uint16_t eoud; - uint16_t cp; - uint16_t coud; - uint16_t cofb; - uint16_t corl; - uint16_t cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -dfsdata -{ - int d; - int m; - int lb; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[NMOVES]; - int move_position[NMOVES]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - uint8_t * reached; - bool generated; - uint64_t n; - uint64_t size; - Indexer index; - Moveset moveset; -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; - Trans pre_trans; -}; - -struct -step -{ - Checker check; - Checker ready; - Moveset moveset; -}; - -/* TODO: I put it here because it needs the definition of Step, sort it out */ -struct -algset -{ - char * filename; - AlgList ** table; - bool generated; - uint64_t size; - Indexer index; - AntiIndexer antindex; - Step step; - SolveOptions opts; -}; diff --git a/old/2021-06-30-noreached/cube.c b/old/2021-06-30-noreached/cube.c @@ -1,3394 +0,0 @@ -#include "cube.h" - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static Cube admissible_eos_from_eofbepos(Cube cube); -static bool allowed_next(Move move, DfsData *dd); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static int array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); -static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent_pos(int pos1, int pos2); -static int epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(int epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); -static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); -static void gensym(SymData *sd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void init_auxtables(); -static void init_cphtr_cosets(); -static void init_cphtr_left_cosets_bfs(int i, int c); -static void init_cphtr_right_cosets_color(int i, int c); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_strings(); -static void init_symdata(); -static void init_trans(); -static void init_trans_aux(); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void movelist_to_position(Move *movelist, int *position); -static void moveset_to_list(Moveset ms, Estimator f, Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static void ptable_update(PruneData *pd, Cube cube, int m); -static void realloc_alg(Alg *alg, int n); -static bool read_mtables_file(); -static bool read_ptable_file(PruneData *pd); -static bool read_symdata_file(SymData *sd); -static bool read_ttables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_mtables_file(); -static bool write_ptable_file(PruneData *pd); -static bool write_symdata_file(SymData *sd); -static bool write_ttables_file(); - - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; -static int cphtr_left_cosets[FACTORIAL8]; -static int cphtr_right_cosets[FACTORIAL8]; -static int cphtr_right_rep[BINOM8ON4*6]; -static Center what_center_at_aux[FACTORIAL6][6]; -static Corner what_corner_at_aux[FACTORIAL8][8]; -static int what_orientation_last_corner_aux[POW3TO7]; -static int what_orientation_last_edge_aux[POW2TO11]; -static Center where_is_center_aux[FACTORIAL6][6]; -static Corner where_is_corner_aux[FACTORIAL8][8]; -static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; - -static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eo_ttable[NTRANS][POW2TO11]; -static int cp_ttable[NTRANS][FACTORIAL8]; -static int co_ttable[NTRANS][POW3TO7]; -static int cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eofb_mtable[NMOVES][POW2TO11]; -static int eorl_mtable[NMOVES][POW2TO11]; -static int eoud_mtable[NMOVES][POW2TO11]; -static int cp_mtable[NMOVES][FACTORIAL8]; -static int coud_mtable[NMOVES][POW3TO7]; -static int cofb_mtable[NMOVES][POW3TO7]; -static int corl_mtable[NMOVES][POW3TO7]; -static int cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * rotation_algs[NROTATIONS]; - - -/* Symmetry data for some coordinates ****************************************/ - -static Trans -trans_group_udfix[16] = { - uf, ur, ub, ul, - df, dr, db, dl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, -}; - -SymData -sd_coud_16 = { - .filename = "sd_coud_16", - .coord = &coord_coud, - .sym_coord = &coord_coud_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -SymData -sd_eofbepos_16 = { - .filename = "sd_eofbepos_16", - .coord = &coord_eofbepos, - .sym_coord = &coord_eofbepos_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static int n_all_symdata = 2; -static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; - -/* Coordinates and their implementation **************************************/ - -static uint64_t index_eofb(Cube cube); -static uint64_t index_eofbepos(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_cornershtr(Cube cube); -static uint64_t index_drud(Cube cube); -static uint64_t index_coud_sym16(Cube cube); -static uint64_t index_eofbepos_sym16(Cube cube); -static uint64_t index_drud_sym16(Cube cube); -static uint64_t index_khuge(Cube cube); - -static Cube antindex_eofb(uint64_t ind); -static Cube antindex_eofbepos(uint64_t ind); -static Cube antindex_coud(uint64_t ind); -static Cube antindex_corners(uint64_t ind); -static Cube antindex_cornershtr(uint64_t ind); -static Cube antindex_drud(uint64_t ind); -static Cube antindex_coud_sym16(uint64_t ind); -static Cube antindex_eofbepos_sym16(uint64_t ind); -static Cube antindex_drud_sym16(uint64_t ind); -static Cube antindex_khuge(uint64_t ind); - -Coordinate -coord_eofb = { - .index = index_eofb, - .cube = antindex_eofb, - .check = check_eofb, - .max = POW2TO11 -}; - -Coordinate -coord_eofbepos = { - .index = index_eofbepos, - .cube = antindex_eofbepos, - .check = check_eofbepos, - .max = POW2TO11 * BINOM12ON4 -}; - -Coordinate -coord_coud = { - .index = index_coud, - .cube = antindex_coud, - .check = check_coud, - .max = POW3TO7 -}; - -Coordinate -coord_corners = { - .index = index_corners, - .cube = antindex_corners, - .check = check_corners, - .max = POW3TO7 * FACTORIAL8 -}; - -Coordinate -coord_cornershtr = { - .index = index_cornershtr, - .cube = antindex_cornershtr, - .check = check_cornershtr, - .max = POW3TO7 * BINOM8ON4 * 6 -}; - -Coordinate -coord_drud = { - .index = index_drud, - .cube = antindex_drud, - .check = check_drud, - .max = POW2TO11 * POW3TO7 * BINOM12ON4 -}; - -Coordinate -coord_eofbepos_sym16 = { - .index = index_eofbepos_sym16, - .cube = antindex_eofbepos_sym16, - .check = check_eofbepos, -}; - -Coordinate -coord_coud_sym16 = { - .index = index_coud_sym16, - .cube = antindex_coud_sym16, - .check = check_coud, -}; - -Coordinate -coord_drud_sym16 = { - .index = index_drud_sym16, - .cube = antindex_drud_sym16, - .check = check_drud, - .max = POW3TO7 * 64430 -}; - -Coordinate -coord_khuge = { - .index = index_khuge, - .cube = antindex_khuge, - .check = check_khuge, - .max = POW3TO7 * FACTORIAL4 * 64430 -}; - - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_eofbepos(Cube cube) -{ - return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_cornershtr(Cube cube) -{ - return cube.coud * BINOM8ON4 * 6 + cphtr(cube); -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -static uint64_t -index_coud_sym16(Cube cube) -{ - return sd_coud_16.class[index_coud(cube)]; -} - -static uint64_t -index_drud_sym16(Cube cube) -{ - Trans t; - Cube c; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - - return index_eofbepos_sym16(c) * POW3TO7 + c.coud; -} - -static uint64_t -index_eofbepos_sym16(Cube cube) -{ - return sd_eofbepos_16.class[index_eofbepos(cube)]; -} - -static uint64_t -index_khuge(Cube cube) -{ - Trans t; - Cube c; - uint64_t a; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); - - return a * POW3TO7 + c.coud; -} - - -/* TODO: rename */ -static Cube -antindex_eofb(uint64_t ind) -{ - return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; -} - -static Cube -antindex_eofbepos(uint64_t ind) -{ - return admissible_ee_aux[ind]; -} - -/* TODO: rename */ -static Cube -antindex_coud(uint64_t ind) -{ - return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_corners(uint64_t ind) -{ - Cube c = {0}; - - c.coud = ind / FACTORIAL8; - c.cp = ind % FACTORIAL8; - - return c; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_cornershtr(uint64_t ind) -{ - Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); - - c.coud = ind / (BINOM8ON4 * 6); - - return c; -} - -/* TODO: admissible eos and cos */ -static Cube -antindex_drud(uint64_t ind) -{ - Cube c = {0}; - - c.eofb = ind % POW2TO11; - c.coud = (ind / POW2TO11) % POW3TO7; - c.epose = (ind % (POW2TO11 * POW3TO7)) * FACTORIAL4; - - return c; -} - -static Cube -antindex_coud_sym16(uint64_t ind) -{ - return sd_coud_16.rep[ind]; -} - -static Cube -antindex_eofbepos_sym16(uint64_t ind) -{ - return sd_eofbepos_16.rep[ind]; -} - -static Cube -antindex_drud_sym16(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/POW3TO7]; - c.coud = ind % POW3TO7; - c.cofb = c.coud; - c.corl = c.coud; - - return c; -} - -static Cube -antindex_khuge(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; - c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); - c.coud = ind % POW3TO7; - - return c; -} - - -/* Checkers ******************************************************************/ - -bool -check_centers(Cube cube) -{ - return cube.cpos == 0; -} - -bool -check_corners(Cube cube) -{ - return cube.cp == 0 && cube.coud == 0; -} - -bool -check_cornershtr(Cube cube) -{ - return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ -} - -bool -check_coud(Cube cube) -{ - return cube.coud == 0; -} - -bool -check_drud(Cube cube) -{ - return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; -} - -bool -check_eofb(Cube cube) -{ - return cube.eofb == 0; -} - -bool -check_eofbepos(Cube cube) -{ - return cube.eofb == 0 && cube.epose / 24 == 0; -} - -bool -check_epose(Cube cube) -{ - return cube.epose == 0; -} - -bool -check_ep(Cube cube) -{ - return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; -} - -bool -check_khuge(Cube cube) -{ - return check_drud(cube) && cube.epose % 24 == 0; -} - -bool -check_nothing(Cube cube) -{ - return is_admissible(cube); /*TODO: maybe change?*/ -} - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - - -/* Local functions implementation ********************************************/ - -/* TODO: this should be an anti index (maybe?) */ -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static Cube -admissible_eos_from_eofbepos(Cube cube) -{ - Edge e; - Cube ret; - CubeArray *arr = new_cubearray(cube, pf_all); - - memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); - memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); - - for (e = 0; e < 12; e++) { - if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || - (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) - arr->eorl[e] = 1 - arr->eorl[e]; - if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || - (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) - arr->eoud[e] = 1 - arr->eoud[e]; - } - - ret = arrays_to_cube(arr, pf_all); - free_cubearray(arr, pf_all); - - return ret; -} - -static bool -allowed_next(Move move, DfsData *dd) -{ - if (!possible_next[dd->last2][dd->last1][move]) - return false; - - if (commute[dd->last1][move]) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -} - -static 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; -} - -static 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 Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static int -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -/* -static int -cphtr_cp(int cp) -{ - int i, a[8]; - - index_to_perm(cp, 8, a); - - for (i = 0; i < 8; i++) - if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) - a[i] = 0; - else - a[i] = 1; - - swap(&a[1], &a[5]); - swap(&a[3], &a[7]); - - return subset_to_index(a, 8, 4); -} -*/ - -static void -dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - if (dfs_stop(c, s, opts, dd)) - return; - - if (dfs_check_solved(opts, dd)) - return; - - dfs_branch(c, s, opts, dd); - - if (opts->can_niss && !dd->niss) - dfs_niss(c, s, opts, dd); -} - -static void -dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; - - int i, maxnsol = opts->max_solutions; - - for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { - m = moves[i]; - if (allowed_next(m, dd)) { - dd->last2 = dd->last1; - dd->last1 = m; - append_move(dd->current_alg, m, dd->niss); - - dfs(apply_move(m, c), s, opts, dd); - - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } -} - -static bool -dfs_check_solved(SolveOptions *opts, DfsData *dd) -{ - if (dd->lb != 0) - return false; - - if (dd->current_alg->len == dd->d) { - append_alg(dd->sols, dd->current_alg); - - if (opts->feedback) - print_alg(dd->current_alg, false); - } - - return true; -} - -static void -dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move l1 = dd->last1, l2 = dd->last2; - CubeTarget ct; - - ct.cube = apply_move(inverse_move(l1), (Cube){0}); - ct.target = 1; - - if (dd->current_alg->len == 0 || s.estimate(ct)) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - - dfs(inverse_cube(c), s, opts, dd); - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = false; - } -} - -static bool -dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - CubeTarget ct = { - .cube = c, - .target = dd->d - dd->current_alg->len - }; - - if (dd->sols->len >= opts->max_solutions) - return true; - - dd->lb = s.estimate(ct); - if (opts->can_niss && !dd->niss) - dd->lb = MIN(1, dd->lb); - - if (dd->current_alg->len + dd->lb > dd->d) - return true; - - return false; -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent_pos(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 0) - ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; - - swap(&ep8[1], &ep8[4]); - swap(&ep8[3], &ep8[6]); - - return subset_to_index(ep8, 8, 4); -} - -static int -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(int epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -genptable_dfs(Cube c, PruneData *pd, DfsData *dd) -{ - int oldval = ptableval(pd, c); - - if (oldval < dd->m || pd->n == pd->coord->max || - (dd->m != 0 && pd->coord->check(c)) ) - return; - - if (dd->m == dd->d) { - if (dd->m < oldval) - ptable_update(pd, c, dd->m); - return; - } - - genptable_dfs_branch(c, pd, dd); -} - -static void -genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) -{ - Move i, move, l1 = dd->last1, l2 = dd->last2; - - dd->m++; - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (allowed_next(move, dd)) { - dd->last2 = dd->last1; - dd->last1 = move; - - genptable_dfs(apply_move(move, c), pd, dd); - - dd->last2 = l2; - dd->last1 = l1; - } - } - - dd->m--; -} - -static void -gensym(SymData *sd) -{ - uint64_t i, in, nreps = 0; - int j; - Cube c, d; - - if (sd->generated) - return; - - sd->class = malloc(sd->coord->max * sizeof(uint64_t)); - sd->rep = malloc(sd->coord->max * sizeof(Cube)); - sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); - - if (read_symdata_file(sd)) { - sd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); - - for (i = 0; i < sd->coord->max; i++) - sd->class[i] = sd->coord->max + 1; - - for (i = 0; i < sd->coord->max; i++) { - if (sd->class[i] == sd->coord->max + 1) { - c = sd->coord->cube(i); - sd->rep[nreps] = c; - for (j = 0; j < sd->ntrans; j++) { - d = apply_trans(sd->trans[j], c); - in = sd->coord->index(d); - - if (sd->class[in] == sd->coord->max + 1) { - sd->class[in] = nreps; - sd->transtorep[in] = - inverse_trans(sd->trans[j]); - } - } - nreps++; - } - } - - sd->sym_coord->max = nreps; - sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); - sd->generated = true; - - fprintf(stderr, "Found %lu classes\n", nreps); - - if (!write_symdata_file(sd)) - fprintf(stderr, "Error writing SymData file\n"); - - return; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -static void -moveset_to_list(Moveset ms, Estimator f, Move *r) -{ - CubeTarget ct = { .target = 1 }; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - ct.cube = apply_move(i, (Cube){0}); - if (f != NULL && f(ct)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static void -ptable_update(PruneData *pd, Cube cube, int n) -{ - uint64_t ind = pd->coord->index(cube); - uint8_t oldval2 = pd->ptable[ind/2]; - int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; - pd->n++; -} - -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; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return r == ptablesize(pd); -} - -static bool -read_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(int); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); - Cube ret = {0}; - - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - ret = apply_alg_generic(inv, ret, f, true); - - ret = compose_filtered(c, ret, f); - - ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - - free_alg(inv); - return ret; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return written == ptablesize(pd); -} - -static bool -write_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(int); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - CubeArray *arr; - uint64_t ui, uj; - int i, j, k, auxarr[12]; - bool cij, p1, p2; - - for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { - k = (ui / POW2TO11) * 24; - c1 = admissible_ep((Cube){ .epose = k }, pf_e); - c1.eofb = ui % POW2TO11; - c1 = admissible_eos_from_eofbepos(c1); - admissible_ee_aux[ui] = c1; - } - - for (ui = 0; ui < FACTORIAL6; ui++) { - arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); - for (i = 0; i < 6; i++) { - what_center_at_aux[ui][i] = arr->cpos[i]; - where_is_center_aux[ui][arr->cpos[i]] = i; - } - free_cubearray(arr, pf_cpos); - } - - for (ui = 0; ui < FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.cp = ui}, pf_cp); - for (i = 0; i < 8; i++) { - what_corner_at_aux[ui][i] = arr->cp[i]; - where_is_corner_aux[ui][arr->cp[i]] = i; - } - free_cubearray(arr, pf_cp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.epose = ui}, pf_e); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 0) - where_is_edge_aux[0][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_e); - - arr = new_cubearray((Cube){.eposs = ui}, pf_s); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 1) - where_is_edge_aux[1][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_s); - - arr = new_cubearray((Cube){.eposm = ui}, pf_m); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 2) - where_is_edge_aux[2][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_m); - } - - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, auxarr); - what_orientation_last_corner_aux[ui] = auxarr[7]; - } - - for (ui = 0; ui < POW2TO11; ui++) { - int_to_sum_zero_array(ui, 2, 12, auxarr); - what_orientation_last_edge_aux[ui] = auxarr[11]; - } - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2) && i && j; - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[uf_mirror] = uf_mirror; - inverse_trans_aux[ur_mirror] = ur_mirror; - inverse_trans_aux[ul_mirror] = ul_mirror; - inverse_trans_aux[ub_mirror] = ub_mirror; - - inverse_trans_aux[df_mirror] = df_mirror; - inverse_trans_aux[dr_mirror] = dl_mirror; - inverse_trans_aux[dl_mirror] = dr_mirror; - inverse_trans_aux[db_mirror] = db_mirror; - - inverse_trans_aux[rf_mirror] = rf_mirror; - inverse_trans_aux[rd_mirror] = br_mirror; - inverse_trans_aux[rb_mirror] = lb_mirror; - inverse_trans_aux[ru_mirror] = fl_mirror; - - inverse_trans_aux[lf_mirror] = lf_mirror; - inverse_trans_aux[ld_mirror] = bl_mirror; - inverse_trans_aux[lb_mirror] = rb_mirror; - inverse_trans_aux[lu_mirror] = fr_mirror; - - inverse_trans_aux[fu_mirror] = fu_mirror; - inverse_trans_aux[fr_mirror] = lu_mirror; - inverse_trans_aux[fd_mirror] = bu_mirror; - inverse_trans_aux[fl_mirror] = ru_mirror; - - inverse_trans_aux[bu_mirror] = fd_mirror; - inverse_trans_aux[br_mirror] = rd_mirror; - inverse_trans_aux[bd_mirror] = bd_mirror; - inverse_trans_aux[bl_mirror] = ld_mirror; -} - -/* - * There is certainly a bette way to do this, but for now I just use - * a "graph coloring" algorithm to compute the left cosets, and I compose - * with every possible cp to get the right cosets (it is possible that I am - * mixing up left and right). - * - * For doing it better "Mathematically", we need 3 things: - * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other - * This is easy and it is done in the commented function cphtr_cp(). - * - Check that there is no ep/cp parity - * - Check that we are not in the "3c" case; this is the part I don't - * know how to do. - */ -static void -init_cphtr_cosets() -{ - unsigned int i; - int c = 0, d = 0; - - for (i = 0; i < FACTORIAL8; i++) { - cphtr_left_cosets[i] = -1; - cphtr_right_cosets[i] = -1; - } - - /* First we compute left cosets with a bfs */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_left_cosets[i] == -1) - init_cphtr_left_cosets_bfs(i, c++); - - /* Then we compute right cosets using compose() */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_right_cosets[i] == -1) - init_cphtr_right_cosets_color(i, d++); -} - -static void -init_cphtr_left_cosets_bfs(int i, int c) -{ - int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; - Move moves[6] = {U2, D2, R2, L2, F2, B2}; - - n = 1; - next[0] = i; - cphtr_left_cosets[i] = c; - - while (n != 0) { - for (j = 0, n2 = 0; j < n; j++) { - for (k = 0; k < 6; k++) { - jj = cp_mtable[moves[k]][next[j]]; - if (cphtr_left_cosets[jj] == -1) { - cphtr_left_cosets[jj] = c; - next2[n2++] = jj; - } - } - } - - for (j = 0; j < n2; j++) - next[j] = next2[j]; - n = n2; - } -} - -static void -init_cphtr_right_cosets_color(int i, int d) -{ - int cp; - unsigned int j; - - cphtr_right_rep[d] = i; - for (j = 0; j < FACTORIAL8; j++) { - if (cphtr_left_cosets[j] == 0) { - /* TODO: use antindexer, it's nicer */ - cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; - cphtr_right_cosets[cp] = d; - } - } -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - unsigned int ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray) { - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_symdata() -{ - int i; - - for (i = 0; i < n_all_symdata; i++) - gensym(all_sd[i]); -} - -static void -init_trans() { - Cube aux, cube, mirr, c[3]; - CubeArray epcp; - int i, eparr[12], eoarr[12], cparr[8], coarr[8]; - unsigned int ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); - - epose_source[i] = edge_slice(what_edge_at(cube, FR)); - eposs_source[i] = edge_slice(what_edge_at(cube, UR)); - eposm_source[i] = edge_slice(what_edge_at(cube, UF)); - eofb_source[i] = what_center_at(cube, F_center)/2; - eorl_source[i] = what_center_at(cube, R_center)/2; - eoud_source[i] = what_center_at(cube, U_center)/2; - coud_source[i] = what_center_at(cube, U_center)/2; - cofb_source[i] = what_center_at(cube, F_center)/2; - corl_source[i] = what_center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - if (m >= NROTATIONS) { - apply_permutation(ep_mirror, eparr, 12); - apply_permutation(cp_mirror, cparr, 8); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m >= NROTATIONS) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - aux = apply_trans(m, apply_move(mi, (Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move(inverse_move_aux[move], aux); - mirr = apply_trans(uf_mirror, cube); - if (is_solved(cube, false) || - is_solved(mirr, false)) - moves_ttable[m][mi] = move; - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - rotation_algs[uf] = new_alg(""); - rotation_algs[ur] = new_alg("y"); - rotation_algs[ub] = new_alg("y2"); - rotation_algs[ul] = new_alg("y3"); - - rotation_algs[df] = new_alg("z2"); - rotation_algs[dr] = new_alg("y z2"); - rotation_algs[db] = new_alg("x2"); - rotation_algs[dl] = new_alg("y3 z2"); - - rotation_algs[rf] = new_alg("z3"); - rotation_algs[rd] = new_alg("z3 y"); - rotation_algs[rb] = new_alg("z3 y2"); - rotation_algs[ru] = new_alg("z3 y3"); - - rotation_algs[lf] = new_alg("z"); - rotation_algs[ld] = new_alg("z y3"); - rotation_algs[lb] = new_alg("z y2"); - rotation_algs[lu] = new_alg("z y"); - - rotation_algs[fu] = new_alg("x y2"); - rotation_algs[fr] = new_alg("x y"); - rotation_algs[fd] = new_alg("x"); - rotation_algs[fl] = new_alg("x y3"); - - rotation_algs[bu] = new_alg("x3"); - rotation_algs[br] = new_alg("x3 y"); - rotation_algs[bd] = new_alg("x3 y2"); - rotation_algs[bl] = new_alg("x3 y3"); -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - return (Cube) { - .epose = epose_mtable[m][cube.epose], - .eposs = eposs_mtable[m][cube.eposs], - .eposm = eposm_mtable[m][cube.eposm], - .eofb = eofb_mtable[m][cube.eofb], - .eorl = eorl_mtable[m][cube.eorl], - .eoud = eoud_mtable[m][cube.eoud], - .coud = coud_mtable[m][cube.coud], - .cofb = cofb_mtable[m][cube.cofb], - .corl = corl_mtable[m][cube.corl], - .cp = cp_mtable[m][cube.cp], - .cpos = cpos_mtable[m][cube.cpos] - }; -} - - -Cube -apply_trans(Trans t, Cube cube) -{ - int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - return (Cube) { - .epose = epose_ttable[t][aux_epos[epose_source[t]]], - .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], - .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], - .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], - .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], - .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], - .coud = co_ttable[t][aux_co[coud_source[t]]], - .corl = co_ttable[t][aux_co[corl_source[t]]], - .cofb = co_ttable[t][aux_co[cofb_source[t]]], - .cp = cp_ttable[t][cube.cp], - .cpos = cpos_ttable[t][cube.cpos] - }; -} - -Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -/*TODO maybe move the next two */ -uint64_t -cphtr(Cube cube) -{ - return cphtr_right_cosets[cube.cp]; -} - -Cube -anti_cphtr(uint64_t ind) -{ - return (Cube) { .cp = cphtr_right_rep[ind] }; -} - -uint64_t -epos_dependent(Cube c) -{ - return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -void -genptable(PruneData *pd) -{ - Cube cube; - uint64_t j, oldn = 0; - DfsData dd = { - .m = 0, - .last1 = NULLMOVE, - .last2 = NULLMOVE - }; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->coord->max; j++) - ptable_update(pd, pd->coord->cube(j), 15); - - moveset_to_list(pd->moveset, NULL, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->coord->max; dd.d++) { - for (j = 0; j < pd->coord->max; j++) { - cube = pd->coord->cube(j); - if (pd->coord->check(cube)) - genptable_dfs(cube, pd, &dd); - } - fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", - dd.d, pd->n-oldn, pd->n, pd->coord->max); - oldn = pd->n; - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - int i; - - if (reorient) { - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(rotation_algs[i], cube),false)) - return true; - return false; - } else { - return equal(cube, (Cube){0}); - } -} - -bool -is_solved_block(Cube cube, Block block) -{ - int i; - - for (i = 0; i < 12; i++) - if (block.edge[i] && !is_solved_edge(cube, i)) - return false; - for (i = 0; i < 8; i++) - if (block.corner[i] && !is_solved_corner(cube, i)) - return false; - for (i = 0; i < 6; i++) - if (block.center[i] && !is_solved_center(cube, i)) - return false; - - return true; -} - -bool -is_solved_center(Cube cube, Center c) -{ - return what_center_at(cube, c) == c; -} - -bool -is_solved_corner(Cube cube, Corner c) -{ - return what_corner_at(cube, c) == c && - what_orientation_corner(cube.coud, c); -} - -bool -is_solved_edge(Cube cube, Edge e) -{ - return what_edge_at(cube, e) == e && - what_orientation_edge(cube.eofb, e); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b, x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ -/* - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -*/ - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[what_edge_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %d ", what_orientation_edge(cube.eofb, i)); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[what_corner_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %d ", what_orientation_corner(cube.coud, i)); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[what_center_at(cube, i)]); - printf("\n"); - -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -/* TODO: clean pre_trans or put it back */ -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - /*AlgListNode *node;*/ - AlgList *sols = new_alglist(); - /*Cube c = apply_trans(opts->pre_trans, cube);*/ - DfsData dd = { - .m = 0, - .niss = false, - .lb = -1, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && !step.ready(cube)) { - fprintf(stderr, "Cube not ready for solving step\n"); - return sols; - } - - moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = opts->min_moves; - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - if (opts->feedback) - fprintf(stderr, - "Found %d solutions, searching depth %d...\n", - sols->len, dd.d); - dfs(cube, step, opts, &dd); - } - -/* - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans(opts->pre_trans), node->alg); -*/ - - free_alg(dd.current_alg); - return sols; -} - -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; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - /* TODO: make it possible to print to stdout or to string */ - /* Maybe just return a string */ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - for (i = 0; i < 16; i++) - a[i] = 0; - - if (!pd->generated) - genptable(pd); - - for (i = 0; i < pd->coord->max; i++) - a[ptableval(pd, pd->coord->cube(i))]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -uint64_t -ptablesize(PruneData *pd) -{ - return (pd->coord->max + 1) / 2; -} - -int -ptableval(PruneData *pd, Cube cube) -{ - uint64_t ind = pd->coord->index(cube); - - return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; -} - - -Alg * -rotation_alg(Trans i) -{ - return rotation_algs[i % NROTATIONS]; -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} - -Center -what_center_at(Cube cube, Center c) -{ - return what_center_at_aux[cube.cpos][c]; -} - -Corner -what_corner_at(Cube cube, Corner c) -{ - return what_corner_at_aux[cube.cp][c]; -} - -Edge -what_edge_at(Cube cube, Edge e) -{ - Edge ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - - free_cubearray(arr, pf_ep); - return ret; -} - -int -what_orientation_corner(int co, Corner c) -{ - if (c < 7) - return (co / powint(3, c)) % 3; - else - return what_orientation_last_corner_aux[co]; -} - -int -what_orientation_edge(int eo, Edge e) -{ - if (e < 11) - return (eo & (1 << e)) ? 1 : 0; - else - return what_orientation_last_edge_aux[eo]; -} - -Center -where_is_center(Cube cube, Center c) -{ - return where_is_center_aux[cube.cpos][c]; -} - -Corner -where_is_corner(Cube cube, Corner c) -{ - return where_is_corner_aux[cube.cp][c]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_cphtr_cosets(); - init_trans_aux(); - init_trans(); - init_symdata(); -} - diff --git a/old/2021-06-30-noreached/cube.h b/old/2021-06-30-noreached/cube.h @@ -1,90 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> - -#include "macros.h" -#include "cubetypes.h" - -extern Coordinate coord_eofb; -extern Coordinate coord_eofbepos; -extern Coordinate coord_coud; -extern Coordinate coord_corners; -extern Coordinate coord_cornershtr; -extern Coordinate coord_drud; -extern Coordinate coord_coud_sym16; -extern Coordinate coord_eofbepos_sym16; -extern Coordinate coord_drud_sym16; -extern Coordinate coord_khuge; - -Cube apply_alg(Alg *alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ -Cube anti_cphtr(uint64_t ind); /*TODO also this */ -uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_admissible(Cube cube); -bool is_solved(Cube cube, bool reorient); -bool is_solved_center(Cube cube, Center c); -bool is_solved_corner(Cube cube, Corner c); -bool is_solved_edge(Cube cube, Edge e); -void print_cube(Cube cube); -Cube random_cube(); -AlgList * solve(Cube cube, Step step, SolveOptions *opts); -Center what_center_at(Cube cube, Center c); -Corner what_corner_at(Cube cube, Corner c); -Edge what_edge_at(Cube cube, Edge e); -int what_orientation_corner(int co, Corner c); -int what_orientation_edge(int eo, Edge e); -Center where_is_center(Cube cube, Center c); -Corner where_is_corner(Cube cube, Corner c); -Edge where_is_edge(Cube cube, Edge e); - -bool check_centers(Cube cube); -bool check_corners(Cube cube); -bool check_cornershtr(Cube cube); -bool check_coud(Cube cube); -bool check_drud(Cube cube); -bool check_eofb(Cube cube); -bool check_eofbepos(Cube cube); -bool check_epose(Cube cube); -bool check_ep(Cube cube); -bool check_khuge(Cube cube); -bool check_nothing(Cube cube); - -bool moveset_HTM(Move m); -bool moveset_URF(Move m); - -Move base_move(Move m); -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Alg * new_alg(char *str); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); -Alg * rotation_alg(Trans i); -void transform_alg(Trans t, Alg *alg); - -void genptable(PruneData *pd); -void print_ptable(PruneData *pd); -uint64_t ptablesize(PruneData *pd); -int ptableval(PruneData *pd, Cube cube); - -void init(); - -#endif - diff --git a/old/2021-06-30-noreached/cubetypes.h b/old/2021-06-30-noreached/cubetypes.h @@ -1,250 +0,0 @@ -#ifndef CUBETYPES_H -#define CUBETYPES_H - -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct block Block; -typedef struct coordinate Coordinate; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct cubetarget CubeTarget; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; -typedef struct symdata SymData; - -typedef Cube (*AntiIndexer) (uint64_t); -typedef bool (*Checker) (Cube); -typedef int (*Estimator) (CubeTarget); -typedef uint64_t (*Indexer) (Cube); -typedef bool (*Moveset) (Move); - - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, - rf_mirror, rd_mirror, rb_mirror, ru_mirror, - lf_mirror, ld_mirror, lb_mirror, lu_mirror, - fu_mirror, fr_mirror, fd_mirror, fl_mirror, - bu_mirror, br_mirror, bd_mirror, bl_mirror, -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - Move * move; - bool * inv; - int len; - int allocated; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -coordinate -{ - Indexer index; - AntiIndexer cube; - Checker check; - uint64_t max; -}; - -struct -cube -{ - int epose; - int eposs; - int eposm; - int eofb; - int eorl; - int eoud; - int cp; - int coud; - int cofb; - int corl; - int cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -cubetarget -{ - Cube cube; - int target; -}; - -struct -dfsdata -{ - int d; - int m; - int lb; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[NMOVES]; - int move_position[NMOVES]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - bool generated; - uint64_t n; - Coordinate * coord; - Moveset moveset; -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; -}; - -struct -step -{ - Estimator estimate; - Checker ready; - Moveset moveset; -}; - -struct -symdata -{ - char * filename; - bool generated; - Coordinate * coord; - Coordinate * sym_coord; - int ntrans; - Trans * trans; - uint64_t * class; - Cube * rep; - Trans * transtorep; -}; - -#endif diff --git a/old/2021-06-30-noreached/macros.h b/old/2021-06-30-noreached/macros.h @@ -1,23 +0,0 @@ -#ifndef MACROS_H -#define MACROS_H - -#define POW2TO6 64ULL -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL7 5040ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define NMOVES (z3+1) -#define NTRANS 48 -#define NROTATIONS 24 - -#endif diff --git a/old/2021-06-30-noreached/main.c b/old/2021-06-30-noreached/main.c @@ -1,80 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "steps.h" - -int main() { - Alg *algo; - AlgList *sols; - Cube cube; - SolveOptions opts; - char line[1000]; - int i, ns = 2; -/* Move m;*/ -/* int nrand = 10000, sum1, sum2, sum3;*/ - - Step *stps[20] = {&drud_HTM, &optimal_HTM}; - char sss[30][30] = {"DR on UD", "Optimal solve"}; - - opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 20, - .optimal_only = true, - .max_solutions = 1, - .can_niss = false, - .feedback = true, - }; - - init(); - -/* - srand(time(NULL)); - sum1 = 0; - sum2 = 0; - sum3 = 0; - for (i = 0; i < nrand; i++) { - cube = random_cube(); - sum1 += drud_HTM.check(cube, 20); - sum2 += optimal_HTM.check(cube, 20); - sum3 += cornershtreofb_HTM.check(cube, 20); - } - printf("Average drud pruning: %lf\n", ((double)sum1) / ((double) nrand)); - printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); - printf("Average corners htr + eofb pruning: %lf\n", ((double)sum3) / ((double) nrand)); -*/ - -/* - for (m = U; m <= B3; m++) { - printf("Class eofbepos after %d: ", m); - printf("%lu\n", coord_khuge.index(apply_move(m,(Cube){0}))); - } -*/ - - printf("Welcome to nissy 2.0! Insert a scramble:\n"); - - if (fgets(line, 1000, stdin) != NULL) { - algo = new_alg(line); - cube = apply_alg(algo, (Cube){0}); - - print_alg(inverse_alg(algo), false); -/* - printf("After rb_mirror:\n"); - cube = apply_trans(rb_mirror, cube); - print_cube(cube); - printf("Going back:\n"); - cube = apply_trans(inverse_trans(rb_mirror), cube); -*/ - - print_cube(cube); - - for (i = 0; i < ns; i++) { - sols = solve(cube, *stps[i], &opts); - printf("%s: %d solutions found:\n", sss[i], sols->len); - print_alglist(sols, true); - free_alglist(sols); - } - free_alg(algo); - } - - return 0; -} - diff --git a/old/2021-06-30-noreached/steps.c b/old/2021-06-30-noreached/steps.c @@ -1,307 +0,0 @@ -#include "steps.h" - -/* Standard checkers (return lower bound) ************************************/ - -static int estimate_eofb_HTM(CubeTarget ct); -static int estimate_coud_HTM(CubeTarget ct); -static int estimate_coud_URF(CubeTarget ct); -static int estimate_corners_HTM(CubeTarget ct); -static int estimate_cornershtr_HTM(CubeTarget ct); -static int estimate_corners_URF(CubeTarget ct); -static int estimate_cornershtr_URF(CubeTarget ct); -static int estimate_drud_HTM(CubeTarget ct); -static int estimate_optimal_HTM(CubeTarget ct); - -/* Steps *********************************************************************/ - -Step -eofb_HTM = { - .estimate = estimate_eofb_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_HTM = { - .estimate = estimate_coud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_URF = { - .estimate = estimate_coud_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_HTM = { - .estimate = estimate_corners_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_HTM = { - .estimate = estimate_cornershtr_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_URF = { - .estimate = estimate_cornershtr_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_URF = { - .estimate = estimate_corners_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -drud_HTM = { - .estimate = estimate_drud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -optimal_HTM = { - .estimate = estimate_optimal_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - - -/* Pruning tables ************************************************************/ - -PruneData -pd_eofb_HTM = { - .filename = "ptable_eofb_HTM", - .coord = &coord_eofb, - .moveset = moveset_HTM -}; - -PruneData -pd_coud_HTM = { - .filename = "ptable_coud_HTM", - .coord = &coord_coud, - .moveset = moveset_HTM -}; - -PruneData -pd_cornershtr_HTM = { - .filename = "ptable_cornershtr_withcosets_HTM", - .coord = &coord_cornershtr, - .moveset = moveset_HTM -}; - -PruneData -pd_corners_HTM = { - .filename = "ptable_corners_HTM", - .coord = &coord_corners, - .moveset = moveset_HTM -}; - -PruneData -pd_drud_HTM = { - .filename = "ptable_drud_HTM", - .coord = &coord_drud, - .moveset = moveset_HTM -}; - -PruneData -pd_drud_sym16_HTM = { - .filename = "ptable_drud_sym16_HTM", - .coord = &coord_drud_sym16, - .moveset = moveset_HTM, -}; - -PruneData -pd_khuge_HTM = { - .filename = "ptable_khuge_HTM", - .coord = &coord_khuge, - .moveset = moveset_HTM -}; - - -/* Standard checkers (return lower bound) ************************************/ - -static int -estimate_eofb_HTM(CubeTarget ct) -{ - if (!pd_eofb_HTM.generated) - genptable(&pd_eofb_HTM); - - return ptableval(&pd_eofb_HTM, ct.cube); -} - -static int -estimate_coud_HTM(CubeTarget ct) -{ - if (!pd_coud_HTM.generated) - genptable(&pd_coud_HTM); - - return ptableval(&pd_coud_HTM, ct.cube); -} - -static int -estimate_coud_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; - CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; - - int ud = estimate_coud_HTM(ct); - int rl = estimate_coud_HTM(ct2); - int fb = estimate_coud_HTM(ct3); - - return MIN(ud, MIN(rl, fb)); -} - -static int -estimate_corners_HTM(CubeTarget ct) -{ - if (!pd_corners_HTM.generated) - genptable(&pd_corners_HTM); - - return ptableval(&pd_corners_HTM, ct.cube); -} - -static int -estimate_cornershtr_HTM(CubeTarget ct) -{ - if (!pd_cornershtr_HTM.generated) - genptable(&pd_cornershtr_HTM); - - return ptableval(&pd_cornershtr_HTM, ct.cube); -} - -static int -estimate_cornershtr_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_cornershtr_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_corners_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_corners_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_drud_HTM(CubeTarget ct) -{ -/* - if (!pd_drud_HTM.generated) - genptable(&pd_drud_HTM); - - return ptableval(&pd_drud_HTM, ct.cube); -*/ - - if (!pd_drud_sym16_HTM.generated) - genptable(&pd_drud_sym16_HTM); - - return ptableval(&pd_drud_sym16_HTM, ct.cube); -} - -/* TODO: if lucky, remove this */ -/* -static int -estimate_optimal_HTM(CubeTarget ct) -{ - static Trans t1 = { .rot = rf, .mirror = false }; - static Trans t2 = { .rot = bd, .mirror = false }; - int dr1, dr2, dr3, cor, ret; - Cube cube = ct.cube; - - dr1 = estimate_drud_HTM(ct); - cor = estimate_corners_HTM(ct); - ret = MAX(dr1, cor); - - if (ret > ct.target) - return ret; - - ct.cube = apply_trans(t1, cube); - dr2 = estimate_drud_HTM(ct); - ret = MAX(ret, dr2); - - if (ret > ct.target) - return ret; - - ct.cube = apply_trans(t2, cube); - dr3 = estimate_drud_HTM(ct); - - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - dr3++; - - ret = MAX(ret, dr3); - - if (ret == 0) - return check_ep(cube) ? 0 : 6; - - return ret; -} -*/ - -static int -estimate_optimal_HTM(CubeTarget ct) -{ - static Trans t2 = rf, t3 = bd; - - int dr1, dr2, dr3, cor, ret; - Cube cube = ct.cube; - - if (!pd_khuge_HTM.generated) - genptable(&pd_khuge_HTM); - - dr1 = ptableval(&pd_khuge_HTM, cube); - cor = estimate_corners_HTM(ct); - ret = MAX(dr1, cor); - - if (ret > ct.target) - return ret; - - cube = apply_trans(t2, ct.cube); - dr2 = ptableval(&pd_khuge_HTM, cube); - ret = MAX(ret, dr2); - - if (ret > ct.target) - return ret; - - cube = apply_trans(t3, ct.cube); - dr3 = ptableval(&pd_khuge_HTM, cube); - - return MAX(ret, dr3); -} diff --git a/old/2021-06-30-noreached/steps.h b/old/2021-06-30-noreached/steps.h @@ -1,24 +0,0 @@ -#ifndef STEPS_H -#define STEPS_H - -#include "cube.h" - -extern Step eofb_HTM; -extern Step coud_HTM; -extern Step coud_URF; -extern Step corners_HTM; -extern Step cornershtr_HTM; -extern Step corners_URF; -extern Step cornershtr_URF; -extern Step drud_HTM; -extern Step optimal_HTM; - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_cornershtr_HTM; -extern PruneData pd_cornershtreofb_HTM; -extern PruneData pd_drud_HTM; -extern PruneData pd_khuge_HTM; - -#endif diff --git a/old/2021-06-30-reached/cube.c b/old/2021-06-30-reached/cube.c @@ -1,3419 +0,0 @@ -#include "cube.h" - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static Cube admissible_eos_from_eofbepos(Cube cube); -static bool allowed_next(Move move, DfsData *dd); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static int array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); -static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent_pos(int pos1, int pos2); -static int epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(int epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); -static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); -static void gensym(SymData *sd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void init_auxtables(); -static void init_cphtr_cosets(); -static void init_cphtr_left_cosets_bfs(int i, int c); -static void init_cphtr_right_cosets_color(int i, int c); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_strings(); -static void init_symdata(); -static void init_trans(); -static void init_trans_aux(); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void movelist_to_position(Move *movelist, int *position); -static void moveset_to_list(Moveset ms, Estimator f, Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static bool ptable_has_reached(PruneData *pd, Cube cube); -static void ptable_set_reached(PruneData *pd, Cube cube); -static void ptable_update(PruneData *pd, Cube cube, int m); -static void realloc_alg(Alg *alg, int n); -static bool read_mtables_file(); -static bool read_ptable_file(PruneData *pd); -static bool read_symdata_file(SymData *sd); -static bool read_ttables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_mtables_file(); -static bool write_ptable_file(PruneData *pd); -static bool write_symdata_file(SymData *sd); -static bool write_ttables_file(); - - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; -static int cphtr_left_cosets[FACTORIAL8]; -static int cphtr_right_cosets[FACTORIAL8]; -static int cphtr_right_rep[BINOM8ON4*6]; -static Center what_center_at_aux[FACTORIAL6][6]; -static Corner what_corner_at_aux[FACTORIAL8][8]; -static int what_orientation_last_corner_aux[POW3TO7]; -static int what_orientation_last_edge_aux[POW2TO11]; -static Center where_is_center_aux[FACTORIAL6][6]; -static Corner where_is_corner_aux[FACTORIAL8][8]; -static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; - -static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eo_ttable[NTRANS][POW2TO11]; -static int cp_ttable[NTRANS][FACTORIAL8]; -static int co_ttable[NTRANS][POW3TO7]; -static int cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eofb_mtable[NMOVES][POW2TO11]; -static int eorl_mtable[NMOVES][POW2TO11]; -static int eoud_mtable[NMOVES][POW2TO11]; -static int cp_mtable[NMOVES][FACTORIAL8]; -static int coud_mtable[NMOVES][POW3TO7]; -static int cofb_mtable[NMOVES][POW3TO7]; -static int corl_mtable[NMOVES][POW3TO7]; -static int cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * rotation_algs[NROTATIONS]; - - -/* Symmetry data for some coordinates ****************************************/ - -static Trans -trans_group_udfix[16] = { - uf, ur, ub, ul, - df, dr, db, dl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, -}; - -SymData -sd_coud_16 = { - .filename = "sd_coud_16", - .coord = &coord_coud, - .sym_coord = &coord_coud_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -SymData -sd_eofbepos_16 = { - .filename = "sd_eofbepos_16", - .coord = &coord_eofbepos, - .sym_coord = &coord_eofbepos_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static int n_all_symdata = 2; -static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; - -/* Coordinates and their implementation **************************************/ - -static uint64_t index_eofb(Cube cube); -static uint64_t index_eofbepos(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_cornershtr(Cube cube); -static uint64_t index_drud(Cube cube); -static uint64_t index_coud_sym16(Cube cube); -static uint64_t index_eofbepos_sym16(Cube cube); -static uint64_t index_drud_sym16(Cube cube); -static uint64_t index_khuge(Cube cube); - -static Cube antindex_eofb(uint64_t ind); -static Cube antindex_eofbepos(uint64_t ind); -static Cube antindex_coud(uint64_t ind); -static Cube antindex_corners(uint64_t ind); -static Cube antindex_cornershtr(uint64_t ind); -static Cube antindex_drud(uint64_t ind); -static Cube antindex_coud_sym16(uint64_t ind); -static Cube antindex_eofbepos_sym16(uint64_t ind); -static Cube antindex_drud_sym16(uint64_t ind); -static Cube antindex_khuge(uint64_t ind); - -Coordinate -coord_eofb = { - .index = index_eofb, - .cube = antindex_eofb, - .check = check_eofb, - .max = POW2TO11 -}; - -Coordinate -coord_eofbepos = { - .index = index_eofbepos, - .cube = antindex_eofbepos, - .check = check_eofbepos, - .max = POW2TO11 * BINOM12ON4 -}; - -Coordinate -coord_coud = { - .index = index_coud, - .cube = antindex_coud, - .check = check_coud, - .max = POW3TO7 -}; - -Coordinate -coord_corners = { - .index = index_corners, - .cube = antindex_corners, - .check = check_corners, - .max = POW3TO7 * FACTORIAL8 -}; - -Coordinate -coord_cornershtr = { - .index = index_cornershtr, - .cube = antindex_cornershtr, - .check = check_cornershtr, - .max = POW3TO7 * BINOM8ON4 * 6 -}; - -Coordinate -coord_drud = { - .index = index_drud, - .cube = antindex_drud, - .check = check_drud, - .max = POW2TO11 * POW3TO7 * BINOM12ON4 -}; - -Coordinate -coord_eofbepos_sym16 = { - .index = index_eofbepos_sym16, - .cube = antindex_eofbepos_sym16, - .check = check_eofbepos, -}; - -Coordinate -coord_coud_sym16 = { - .index = index_coud_sym16, - .cube = antindex_coud_sym16, - .check = check_coud, -}; - -Coordinate -coord_drud_sym16 = { - .index = index_drud_sym16, - .cube = antindex_drud_sym16, - .check = check_drud, - .max = POW3TO7 * 64430 -}; - -Coordinate -coord_khuge = { - .index = index_khuge, - .cube = antindex_khuge, - .check = check_khuge, - .max = POW3TO7 * FACTORIAL4 * 64430 -}; - - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_eofbepos(Cube cube) -{ - return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_cornershtr(Cube cube) -{ - return cube.coud * BINOM8ON4 * 6 + cphtr(cube); -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -static uint64_t -index_coud_sym16(Cube cube) -{ - return sd_coud_16.class[index_coud(cube)]; -} - -static uint64_t -index_drud_sym16(Cube cube) -{ - Trans t; - Cube c; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - - return index_eofbepos_sym16(c) * POW3TO7 + c.coud; -} - -static uint64_t -index_eofbepos_sym16(Cube cube) -{ - return sd_eofbepos_16.class[index_eofbepos(cube)]; -} - -static uint64_t -index_khuge(Cube cube) -{ - Trans t; - Cube c; - uint64_t a; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); - - return a * POW3TO7 + c.coud; -} - - -/* TODO: rename */ -static Cube -antindex_eofb(uint64_t ind) -{ - return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; -} - -static Cube -antindex_eofbepos(uint64_t ind) -{ - return admissible_ee_aux[ind]; -} - -/* TODO: rename */ -static Cube -antindex_coud(uint64_t ind) -{ - return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_corners(uint64_t ind) -{ - Cube c = {0}; - - c.coud = ind / FACTORIAL8; - c.cp = ind % FACTORIAL8; - - return c; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_cornershtr(uint64_t ind) -{ - Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); - - c.coud = ind / (BINOM8ON4 * 6); - - return c; -} - -/* TODO: admissible eos and cos */ -static Cube -antindex_drud(uint64_t ind) -{ - Cube c = {0}; - - c.eofb = ind % POW2TO11; - c.coud = (ind / POW2TO11) % POW3TO7; - c.epose = (ind % (POW2TO11 * POW3TO7)) * FACTORIAL4; - - return c; -} - -static Cube -antindex_coud_sym16(uint64_t ind) -{ - return sd_coud_16.rep[ind]; -} - -static Cube -antindex_eofbepos_sym16(uint64_t ind) -{ - return sd_eofbepos_16.rep[ind]; -} - -static Cube -antindex_drud_sym16(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/POW3TO7]; - c.coud = ind % POW3TO7; - c.cofb = c.coud; - c.corl = c.coud; - - return c; -} - -static Cube -antindex_khuge(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; - c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); - c.coud = ind % POW3TO7; - - return c; -} - - -/* Checkers ******************************************************************/ - -bool -check_centers(Cube cube) -{ - return cube.cpos == 0; -} - -bool -check_corners(Cube cube) -{ - return cube.cp == 0 && cube.coud == 0; -} - -bool -check_cornershtr(Cube cube) -{ - return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ -} - -bool -check_coud(Cube cube) -{ - return cube.coud == 0; -} - -bool -check_drud(Cube cube) -{ - return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; -} - -bool -check_eofb(Cube cube) -{ - return cube.eofb == 0; -} - -bool -check_eofbepos(Cube cube) -{ - return cube.eofb == 0 && cube.epose / 24 == 0; -} - -bool -check_epose(Cube cube) -{ - return cube.epose == 0; -} - -bool -check_ep(Cube cube) -{ - return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; -} - -bool -check_khuge(Cube cube) -{ - return check_drud(cube) && cube.epose % 24 == 0; -} - -bool -check_nothing(Cube cube) -{ - return is_admissible(cube); /*TODO: maybe change?*/ -} - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - - -/* Local functions implementation ********************************************/ - -/* TODO: this should be an anti index (maybe?) */ -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static Cube -admissible_eos_from_eofbepos(Cube cube) -{ - Edge e; - Cube ret; - CubeArray *arr = new_cubearray(cube, pf_all); - - memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); - memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); - - for (e = 0; e < 12; e++) { - if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || - (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) - arr->eorl[e] = 1 - arr->eorl[e]; - if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || - (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) - arr->eoud[e] = 1 - arr->eoud[e]; - } - - ret = arrays_to_cube(arr, pf_all); - free_cubearray(arr, pf_all); - - return ret; -} - -static bool -allowed_next(Move move, DfsData *dd) -{ - if (!possible_next[dd->last2][dd->last1][move]) - return false; - - if (commute[dd->last1][move]) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -} - -static 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; -} - -static 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 Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static int -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -/* -static int -cphtr_cp(int cp) -{ - int i, a[8]; - - index_to_perm(cp, 8, a); - - for (i = 0; i < 8; i++) - if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) - a[i] = 0; - else - a[i] = 1; - - swap(&a[1], &a[5]); - swap(&a[3], &a[7]); - - return subset_to_index(a, 8, 4); -} -*/ - -static void -dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - if (dfs_stop(c, s, opts, dd)) - return; - - if (dfs_check_solved(opts, dd)) - return; - - dfs_branch(c, s, opts, dd); - - if (opts->can_niss && !dd->niss) - dfs_niss(c, s, opts, dd); -} - -static void -dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; - - int i, maxnsol = opts->max_solutions; - - for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { - m = moves[i]; - if (allowed_next(m, dd)) { - dd->last2 = dd->last1; - dd->last1 = m; - append_move(dd->current_alg, m, dd->niss); - - dfs(apply_move(m, c), s, opts, dd); - - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } -} - -static bool -dfs_check_solved(SolveOptions *opts, DfsData *dd) -{ - if (dd->lb != 0) - return false; - - if (dd->current_alg->len == dd->d) { - append_alg(dd->sols, dd->current_alg); - - if (opts->feedback) - print_alg(dd->current_alg, false); - } - - return true; -} - -static void -dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move l1 = dd->last1, l2 = dd->last2; - CubeTarget ct; - - ct.cube = apply_move(inverse_move(l1), (Cube){0}); - ct.target = 1; - - if (dd->current_alg->len == 0 || s.estimate(ct)) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - - dfs(inverse_cube(c), s, opts, dd); - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = false; - } -} - -static bool -dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - CubeTarget ct = { - .cube = c, - .target = dd->d - dd->current_alg->len - }; - - if (dd->sols->len >= opts->max_solutions) - return true; - - dd->lb = s.estimate(ct); - if (opts->can_niss && !dd->niss) - dd->lb = MIN(1, dd->lb); - - if (dd->current_alg->len + dd->lb > dd->d) - return true; - - return false; -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent_pos(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 0) - ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; - - swap(&ep8[1], &ep8[4]); - swap(&ep8[3], &ep8[6]); - - return subset_to_index(ep8, 8, 4); -} - -static int -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(int epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -genptable_dfs(Cube c, PruneData *pd, DfsData *dd) -{ - int oldval = ptableval(pd, c); - - if (oldval < dd->m || ptable_has_reached(pd, c) || - pd->n == pd->coord->max || (dd->m != 0 && pd->coord->check(c)) ) - return; - - /*ptable_set_reached(pd, c);*/ - - if (dd->m == dd->d) { - if (dd->m < oldval) - ptable_update(pd, c, dd->m); - return; - } - - genptable_dfs_branch(c, pd, dd); -} - -static void -genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) -{ - Move i, move, l1 = dd->last1, l2 = dd->last2; - - dd->m++; - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (allowed_next(move, dd)) { - dd->last2 = dd->last1; - dd->last1 = move; - - genptable_dfs(apply_move(move, c), pd, dd); - - dd->last2 = l2; - dd->last1 = l1; - } - } - - dd->m--; -} - -static void -gensym(SymData *sd) -{ - uint64_t i, in, nreps = 0; - int j; - Cube c, d; - - if (sd->generated) - return; - - sd->class = malloc(sd->coord->max * sizeof(uint64_t)); - sd->rep = malloc(sd->coord->max * sizeof(Cube)); - sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); - - if (read_symdata_file(sd)) { - sd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); - - for (i = 0; i < sd->coord->max; i++) - sd->class[i] = sd->coord->max + 1; - - for (i = 0; i < sd->coord->max; i++) { - if (sd->class[i] == sd->coord->max + 1) { - c = sd->coord->cube(i); - sd->rep[nreps] = c; - for (j = 0; j < sd->ntrans; j++) { - d = apply_trans(sd->trans[j], c); - in = sd->coord->index(d); - - if (sd->class[in] == sd->coord->max + 1) { - sd->class[in] = nreps; - sd->transtorep[in] = - inverse_trans(sd->trans[j]); - } - } - nreps++; - } - } - - sd->sym_coord->max = nreps; - sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); - sd->generated = true; - - fprintf(stderr, "Found %lu classes\n", nreps); - - if (!write_symdata_file(sd)) - fprintf(stderr, "Error writing SymData file\n"); - - return; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -static void -moveset_to_list(Moveset ms, Estimator f, Move *r) -{ - CubeTarget ct = { .target = 1 }; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - ct.cube = apply_move(i, (Cube){0}); - if (f != NULL && f(ct)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static bool -ptable_has_reached(PruneData *pd, Cube cube) -{ - uint64_t ind = pd->coord->index(cube); - - return (ind % 2) ? pd->reached[ind/2] / 16 : pd->reached[ind/2] % 16; -} - -static void -ptable_set_reached(PruneData *pd, Cube cube) -{ - uint64_t ind = pd->coord->index(cube); - uint8_t oldval2 = pd->reached[ind/2]; - int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; - - pd->reached[ind/2] = (ind % 2) ? 16 + other : 16*other + 1; -} - -static void -ptable_update(PruneData *pd, Cube cube, int n) -{ - uint64_t ind = pd->coord->index(cube); - uint8_t oldval2 = pd->ptable[ind/2]; - int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; - pd->n++; -} - -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; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return r == ptablesize(pd); -} - -static bool -read_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(int); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); - Cube ret = {0}; - - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - ret = apply_alg_generic(inv, ret, f, true); - - ret = compose_filtered(c, ret, f); - - ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - - free_alg(inv); - return ret; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return written == ptablesize(pd); -} - -static bool -write_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(int); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - CubeArray *arr; - uint64_t ui, uj; - int i, j, k, auxarr[12]; - bool cij, p1, p2; - - for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { - k = (ui / POW2TO11) * 24; - c1 = admissible_ep((Cube){ .epose = k }, pf_e); - c1.eofb = ui % POW2TO11; - c1 = admissible_eos_from_eofbepos(c1); - admissible_ee_aux[ui] = c1; - } - - for (ui = 0; ui < FACTORIAL6; ui++) { - arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); - for (i = 0; i < 6; i++) { - what_center_at_aux[ui][i] = arr->cpos[i]; - where_is_center_aux[ui][arr->cpos[i]] = i; - } - free_cubearray(arr, pf_cpos); - } - - for (ui = 0; ui < FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.cp = ui}, pf_cp); - for (i = 0; i < 8; i++) { - what_corner_at_aux[ui][i] = arr->cp[i]; - where_is_corner_aux[ui][arr->cp[i]] = i; - } - free_cubearray(arr, pf_cp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.epose = ui}, pf_e); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 0) - where_is_edge_aux[0][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_e); - - arr = new_cubearray((Cube){.eposs = ui}, pf_s); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 1) - where_is_edge_aux[1][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_s); - - arr = new_cubearray((Cube){.eposm = ui}, pf_m); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 2) - where_is_edge_aux[2][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_m); - } - - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, auxarr); - what_orientation_last_corner_aux[ui] = auxarr[7]; - } - - for (ui = 0; ui < POW2TO11; ui++) { - int_to_sum_zero_array(ui, 2, 12, auxarr); - what_orientation_last_edge_aux[ui] = auxarr[11]; - } - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2) && i && j; - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[uf_mirror] = uf_mirror; - inverse_trans_aux[ur_mirror] = ur_mirror; - inverse_trans_aux[ul_mirror] = ul_mirror; - inverse_trans_aux[ub_mirror] = ub_mirror; - - inverse_trans_aux[df_mirror] = df_mirror; - inverse_trans_aux[dr_mirror] = dl_mirror; - inverse_trans_aux[dl_mirror] = dr_mirror; - inverse_trans_aux[db_mirror] = db_mirror; - - inverse_trans_aux[rf_mirror] = rf_mirror; - inverse_trans_aux[rd_mirror] = br_mirror; - inverse_trans_aux[rb_mirror] = lb_mirror; - inverse_trans_aux[ru_mirror] = fl_mirror; - - inverse_trans_aux[lf_mirror] = lf_mirror; - inverse_trans_aux[ld_mirror] = bl_mirror; - inverse_trans_aux[lb_mirror] = rb_mirror; - inverse_trans_aux[lu_mirror] = fr_mirror; - - inverse_trans_aux[fu_mirror] = fu_mirror; - inverse_trans_aux[fr_mirror] = lu_mirror; - inverse_trans_aux[fd_mirror] = bu_mirror; - inverse_trans_aux[fl_mirror] = ru_mirror; - - inverse_trans_aux[bu_mirror] = fd_mirror; - inverse_trans_aux[br_mirror] = rd_mirror; - inverse_trans_aux[bd_mirror] = bd_mirror; - inverse_trans_aux[bl_mirror] = ld_mirror; -} - -/* - * There is certainly a bette way to do this, but for now I just use - * a "graph coloring" algorithm to compute the left cosets, and I compose - * with every possible cp to get the right cosets (it is possible that I am - * mixing up left and right). - * - * For doing it better "Mathematically", we need 3 things: - * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other - * This is easy and it is done in the commented function cphtr_cp(). - * - Check that there is no ep/cp parity - * - Check that we are not in the "3c" case; this is the part I don't - * know how to do. - */ -static void -init_cphtr_cosets() -{ - unsigned int i; - int c = 0, d = 0; - - for (i = 0; i < FACTORIAL8; i++) { - cphtr_left_cosets[i] = -1; - cphtr_right_cosets[i] = -1; - } - - /* First we compute left cosets with a bfs */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_left_cosets[i] == -1) - init_cphtr_left_cosets_bfs(i, c++); - - /* Then we compute right cosets using compose() */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_right_cosets[i] == -1) - init_cphtr_right_cosets_color(i, d++); -} - -static void -init_cphtr_left_cosets_bfs(int i, int c) -{ - int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; - Move moves[6] = {U2, D2, R2, L2, F2, B2}; - - n = 1; - next[0] = i; - cphtr_left_cosets[i] = c; - - while (n != 0) { - for (j = 0, n2 = 0; j < n; j++) { - for (k = 0; k < 6; k++) { - jj = cp_mtable[moves[k]][next[j]]; - if (cphtr_left_cosets[jj] == -1) { - cphtr_left_cosets[jj] = c; - next2[n2++] = jj; - } - } - } - - for (j = 0; j < n2; j++) - next[j] = next2[j]; - n = n2; - } -} - -static void -init_cphtr_right_cosets_color(int i, int d) -{ - int cp; - unsigned int j; - - cphtr_right_rep[d] = i; - for (j = 0; j < FACTORIAL8; j++) { - if (cphtr_left_cosets[j] == 0) { - /* TODO: use antindexer, it's nicer */ - cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; - cphtr_right_cosets[cp] = d; - } - } -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - unsigned int ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray) { - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_symdata() -{ - int i; - - for (i = 0; i < n_all_symdata; i++) - gensym(all_sd[i]); -} - -static void -init_trans() { - Cube aux, cube, mirr, c[3]; - CubeArray epcp; - int i, eparr[12], eoarr[12], cparr[8], coarr[8]; - unsigned int ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); - - epose_source[i] = edge_slice(what_edge_at(cube, FR)); - eposs_source[i] = edge_slice(what_edge_at(cube, UR)); - eposm_source[i] = edge_slice(what_edge_at(cube, UF)); - eofb_source[i] = what_center_at(cube, F_center)/2; - eorl_source[i] = what_center_at(cube, R_center)/2; - eoud_source[i] = what_center_at(cube, U_center)/2; - coud_source[i] = what_center_at(cube, U_center)/2; - cofb_source[i] = what_center_at(cube, F_center)/2; - corl_source[i] = what_center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - if (m >= NROTATIONS) { - apply_permutation(ep_mirror, eparr, 12); - apply_permutation(cp_mirror, cparr, 8); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m >= NROTATIONS) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - aux = apply_trans(m, apply_move(mi, (Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move(inverse_move_aux[move], aux); - mirr = apply_trans(uf_mirror, cube); - if (is_solved(cube, false) || - is_solved(mirr, false)) - moves_ttable[m][mi] = move; - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - rotation_algs[uf] = new_alg(""); - rotation_algs[ur] = new_alg("y"); - rotation_algs[ub] = new_alg("y2"); - rotation_algs[ul] = new_alg("y3"); - - rotation_algs[df] = new_alg("z2"); - rotation_algs[dr] = new_alg("y z2"); - rotation_algs[db] = new_alg("x2"); - rotation_algs[dl] = new_alg("y3 z2"); - - rotation_algs[rf] = new_alg("z3"); - rotation_algs[rd] = new_alg("z3 y"); - rotation_algs[rb] = new_alg("z3 y2"); - rotation_algs[ru] = new_alg("z3 y3"); - - rotation_algs[lf] = new_alg("z"); - rotation_algs[ld] = new_alg("z y3"); - rotation_algs[lb] = new_alg("z y2"); - rotation_algs[lu] = new_alg("z y"); - - rotation_algs[fu] = new_alg("x y2"); - rotation_algs[fr] = new_alg("x y"); - rotation_algs[fd] = new_alg("x"); - rotation_algs[fl] = new_alg("x y3"); - - rotation_algs[bu] = new_alg("x3"); - rotation_algs[br] = new_alg("x3 y"); - rotation_algs[bd] = new_alg("x3 y2"); - rotation_algs[bl] = new_alg("x3 y3"); -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - return (Cube) { - .epose = epose_mtable[m][cube.epose], - .eposs = eposs_mtable[m][cube.eposs], - .eposm = eposm_mtable[m][cube.eposm], - .eofb = eofb_mtable[m][cube.eofb], - .eorl = eorl_mtable[m][cube.eorl], - .eoud = eoud_mtable[m][cube.eoud], - .coud = coud_mtable[m][cube.coud], - .cofb = cofb_mtable[m][cube.cofb], - .corl = corl_mtable[m][cube.corl], - .cp = cp_mtable[m][cube.cp], - .cpos = cpos_mtable[m][cube.cpos] - }; -} - - -Cube -apply_trans(Trans t, Cube cube) -{ - int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - return (Cube) { - .epose = epose_ttable[t][aux_epos[epose_source[t]]], - .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], - .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], - .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], - .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], - .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], - .coud = co_ttable[t][aux_co[coud_source[t]]], - .corl = co_ttable[t][aux_co[corl_source[t]]], - .cofb = co_ttable[t][aux_co[cofb_source[t]]], - .cp = cp_ttable[t][cube.cp], - .cpos = cpos_ttable[t][cube.cpos] - }; -} - -Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -/*TODO maybe move the next two */ -uint64_t -cphtr(Cube cube) -{ - return cphtr_right_cosets[cube.cp]; -} - -Cube -anti_cphtr(uint64_t ind) -{ - return (Cube) { .cp = cphtr_right_rep[ind] }; -} - -uint64_t -epos_dependent(Cube c) -{ - return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -void -genptable(PruneData *pd) -{ - Cube cube; - uint64_t j, oldn = 0; - DfsData dd = { - .m = 0, - .last1 = NULLMOVE, - .last2 = NULLMOVE - }; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->coord->max; j++) - ptable_update(pd, pd->coord->cube(j), 15); - - moveset_to_list(pd->moveset, NULL, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - pd->reached = malloc(ptablesize(pd) * sizeof(uint8_t)); - for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->coord->max; dd.d++) { - memset(pd->reached, 0, ptablesize(pd)*sizeof(uint8_t)); - for (j = 0; j < pd->coord->max; j++) { - cube = pd->coord->cube(j); - if (pd->coord->check(cube)) - genptable_dfs(cube, pd, &dd); - } - fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", - dd.d, pd->n-oldn, pd->n, pd->coord->max); - oldn = pd->n; - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; - free(pd->reached); -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - int i; - - if (reorient) { - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(rotation_algs[i], cube),false)) - return true; - return false; - } else { - return equal(cube, (Cube){0}); - } -} - -bool -is_solved_block(Cube cube, Block block) -{ - int i; - - for (i = 0; i < 12; i++) - if (block.edge[i] && !is_solved_edge(cube, i)) - return false; - for (i = 0; i < 8; i++) - if (block.corner[i] && !is_solved_corner(cube, i)) - return false; - for (i = 0; i < 6; i++) - if (block.center[i] && !is_solved_center(cube, i)) - return false; - - return true; -} - -bool -is_solved_center(Cube cube, Center c) -{ - return what_center_at(cube, c) == c; -} - -bool -is_solved_corner(Cube cube, Corner c) -{ - return what_corner_at(cube, c) == c && - what_orientation_corner(cube.coud, c); -} - -bool -is_solved_edge(Cube cube, Edge e) -{ - return what_edge_at(cube, e) == e && - what_orientation_edge(cube.eofb, e); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b, x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ -/* - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -*/ - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[what_edge_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %d ", what_orientation_edge(cube.eofb, i)); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[what_corner_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %d ", what_orientation_corner(cube.coud, i)); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[what_center_at(cube, i)]); - printf("\n"); - -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -/* TODO: clean pre_trans or put it back */ -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - /*AlgListNode *node;*/ - AlgList *sols = new_alglist(); - /*Cube c = apply_trans(opts->pre_trans, cube);*/ - DfsData dd = { - .m = 0, - .niss = false, - .lb = -1, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && !step.ready(cube)) { - fprintf(stderr, "Cube not ready for solving step\n"); - return sols; - } - - moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = opts->min_moves; - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - if (opts->feedback) - fprintf(stderr, - "Found %d solutions, searching depth %d...\n", - sols->len, dd.d); - dfs(cube, step, opts, &dd); - } - -/* - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans(opts->pre_trans), node->alg); -*/ - - free_alg(dd.current_alg); - return sols; -} - -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; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - /* TODO: make it possible to print to stdout or to string */ - /* Maybe just return a string */ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - for (i = 0; i < 16; i++) - a[i] = 0; - - if (!pd->generated) - genptable(pd); - - for (i = 0; i < pd->coord->max; i++) - a[ptableval(pd, pd->coord->cube(i))]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -uint64_t -ptablesize(PruneData *pd) -{ - return (pd->coord->max + 1) / 2; -} - -int -ptableval(PruneData *pd, Cube cube) -{ - uint64_t ind = pd->coord->index(cube); - - return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; -} - - -Alg * -rotation_alg(Trans i) -{ - return rotation_algs[i % NROTATIONS]; -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} - -Center -what_center_at(Cube cube, Center c) -{ - return what_center_at_aux[cube.cpos][c]; -} - -Corner -what_corner_at(Cube cube, Corner c) -{ - return what_corner_at_aux[cube.cp][c]; -} - -Edge -what_edge_at(Cube cube, Edge e) -{ - Edge ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - - free_cubearray(arr, pf_ep); - return ret; -} - -int -what_orientation_corner(int co, Corner c) -{ - if (c < 7) - return (co / powint(3, c)) % 3; - else - return what_orientation_last_corner_aux[co]; -} - -int -what_orientation_edge(int eo, Edge e) -{ - if (e < 11) - return (eo & (1 << e)) ? 1 : 0; - else - return what_orientation_last_edge_aux[eo]; -} - -Center -where_is_center(Cube cube, Center c) -{ - return where_is_center_aux[cube.cpos][c]; -} - -Corner -where_is_corner(Cube cube, Corner c) -{ - return where_is_corner_aux[cube.cp][c]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_cphtr_cosets(); - init_trans_aux(); - init_trans(); - init_symdata(); -} - diff --git a/old/2021-06-30-reached/cube.h b/old/2021-06-30-reached/cube.h @@ -1,90 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> - -#include "macros.h" -#include "cubetypes.h" - -extern Coordinate coord_eofb; -extern Coordinate coord_eofbepos; -extern Coordinate coord_coud; -extern Coordinate coord_corners; -extern Coordinate coord_cornershtr; -extern Coordinate coord_drud; -extern Coordinate coord_coud_sym16; -extern Coordinate coord_eofbepos_sym16; -extern Coordinate coord_drud_sym16; -extern Coordinate coord_khuge; - -Cube apply_alg(Alg *alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ -Cube anti_cphtr(uint64_t ind); /*TODO also this */ -uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_admissible(Cube cube); -bool is_solved(Cube cube, bool reorient); -bool is_solved_center(Cube cube, Center c); -bool is_solved_corner(Cube cube, Corner c); -bool is_solved_edge(Cube cube, Edge e); -void print_cube(Cube cube); -Cube random_cube(); -AlgList * solve(Cube cube, Step step, SolveOptions *opts); -Center what_center_at(Cube cube, Center c); -Corner what_corner_at(Cube cube, Corner c); -Edge what_edge_at(Cube cube, Edge e); -int what_orientation_corner(int co, Corner c); -int what_orientation_edge(int eo, Edge e); -Center where_is_center(Cube cube, Center c); -Corner where_is_corner(Cube cube, Corner c); -Edge where_is_edge(Cube cube, Edge e); - -bool check_centers(Cube cube); -bool check_corners(Cube cube); -bool check_cornershtr(Cube cube); -bool check_coud(Cube cube); -bool check_drud(Cube cube); -bool check_eofb(Cube cube); -bool check_eofbepos(Cube cube); -bool check_epose(Cube cube); -bool check_ep(Cube cube); -bool check_khuge(Cube cube); -bool check_nothing(Cube cube); - -bool moveset_HTM(Move m); -bool moveset_URF(Move m); - -Move base_move(Move m); -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Alg * new_alg(char *str); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); -Alg * rotation_alg(Trans i); -void transform_alg(Trans t, Alg *alg); - -void genptable(PruneData *pd); -void print_ptable(PruneData *pd); -uint64_t ptablesize(PruneData *pd); -int ptableval(PruneData *pd, Cube cube); - -void init(); - -#endif - diff --git a/old/2021-06-30-reached/cubetypes.h b/old/2021-06-30-reached/cubetypes.h @@ -1,251 +0,0 @@ -#ifndef CUBETYPES_H -#define CUBETYPES_H - -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct block Block; -typedef struct coordinate Coordinate; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct cubetarget CubeTarget; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; -typedef struct symdata SymData; - -typedef Cube (*AntiIndexer) (uint64_t); -typedef bool (*Checker) (Cube); -typedef int (*Estimator) (CubeTarget); -typedef uint64_t (*Indexer) (Cube); -typedef bool (*Moveset) (Move); - - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, - rf_mirror, rd_mirror, rb_mirror, ru_mirror, - lf_mirror, ld_mirror, lb_mirror, lu_mirror, - fu_mirror, fr_mirror, fd_mirror, fl_mirror, - bu_mirror, br_mirror, bd_mirror, bl_mirror, -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - Move * move; - bool * inv; - int len; - int allocated; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -coordinate -{ - Indexer index; - AntiIndexer cube; - Checker check; - uint64_t max; -}; - -struct -cube -{ - int epose; - int eposs; - int eposm; - int eofb; - int eorl; - int eoud; - int cp; - int coud; - int cofb; - int corl; - int cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -cubetarget -{ - Cube cube; - int target; -}; - -struct -dfsdata -{ - int d; - int m; - int lb; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[NMOVES]; - int move_position[NMOVES]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - uint8_t * reached; - bool generated; - uint64_t n; - Coordinate * coord; - Moveset moveset; -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; -}; - -struct -step -{ - Estimator estimate; - Checker ready; - Moveset moveset; -}; - -struct -symdata -{ - char * filename; - bool generated; - Coordinate * coord; - Coordinate * sym_coord; - int ntrans; - Trans * trans; - uint64_t * class; - Cube * rep; - Trans * transtorep; -}; - -#endif diff --git a/old/2021-06-30-reached/macros.h b/old/2021-06-30-reached/macros.h @@ -1,23 +0,0 @@ -#ifndef MACROS_H -#define MACROS_H - -#define POW2TO6 64ULL -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL7 5040ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define NMOVES (z3+1) -#define NTRANS 48 -#define NROTATIONS 24 - -#endif diff --git a/old/2021-06-30-reached/main.c b/old/2021-06-30-reached/main.c @@ -1,80 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "steps.h" - -int main() { - Alg *algo; - AlgList *sols; - Cube cube; - SolveOptions opts; - char line[1000]; - int i, ns = 2; -/* Move m;*/ -/* int nrand = 10000, sum1, sum2, sum3;*/ - - Step *stps[20] = {&drud_HTM, &optimal_HTM}; - char sss[30][30] = {"DR on UD", "Optimal solve"}; - - opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 20, - .optimal_only = true, - .max_solutions = 1, - .can_niss = false, - .feedback = true, - }; - - init(); - -/* - srand(time(NULL)); - sum1 = 0; - sum2 = 0; - sum3 = 0; - for (i = 0; i < nrand; i++) { - cube = random_cube(); - sum1 += drud_HTM.check(cube, 20); - sum2 += optimal_HTM.check(cube, 20); - sum3 += cornershtreofb_HTM.check(cube, 20); - } - printf("Average drud pruning: %lf\n", ((double)sum1) / ((double) nrand)); - printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); - printf("Average corners htr + eofb pruning: %lf\n", ((double)sum3) / ((double) nrand)); -*/ - -/* - for (m = U; m <= B3; m++) { - printf("Class eofbepos after %d: ", m); - printf("%lu\n", coord_khuge.index(apply_move(m,(Cube){0}))); - } -*/ - - printf("Welcome to nissy 2.0! Insert a scramble:\n"); - - if (fgets(line, 1000, stdin) != NULL) { - algo = new_alg(line); - cube = apply_alg(algo, (Cube){0}); - - print_alg(inverse_alg(algo), false); -/* - printf("After rb_mirror:\n"); - cube = apply_trans(rb_mirror, cube); - print_cube(cube); - printf("Going back:\n"); - cube = apply_trans(inverse_trans(rb_mirror), cube); -*/ - - print_cube(cube); - - for (i = 0; i < ns; i++) { - sols = solve(cube, *stps[i], &opts); - printf("%s: %d solutions found:\n", sss[i], sols->len); - print_alglist(sols, true); - free_alglist(sols); - } - free_alg(algo); - } - - return 0; -} - diff --git a/old/2021-06-30-reached/steps.c b/old/2021-06-30-reached/steps.c @@ -1,307 +0,0 @@ -#include "steps.h" - -/* Standard checkers (return lower bound) ************************************/ - -static int estimate_eofb_HTM(CubeTarget ct); -static int estimate_coud_HTM(CubeTarget ct); -static int estimate_coud_URF(CubeTarget ct); -static int estimate_corners_HTM(CubeTarget ct); -static int estimate_cornershtr_HTM(CubeTarget ct); -static int estimate_corners_URF(CubeTarget ct); -static int estimate_cornershtr_URF(CubeTarget ct); -static int estimate_drud_HTM(CubeTarget ct); -static int estimate_optimal_HTM(CubeTarget ct); - -/* Steps *********************************************************************/ - -Step -eofb_HTM = { - .estimate = estimate_eofb_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_HTM = { - .estimate = estimate_coud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_URF = { - .estimate = estimate_coud_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_HTM = { - .estimate = estimate_corners_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_HTM = { - .estimate = estimate_cornershtr_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_URF = { - .estimate = estimate_cornershtr_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_URF = { - .estimate = estimate_corners_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -drud_HTM = { - .estimate = estimate_drud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -optimal_HTM = { - .estimate = estimate_optimal_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - - -/* Pruning tables ************************************************************/ - -PruneData -pd_eofb_HTM = { - .filename = "ptable_eofb_HTM", - .coord = &coord_eofb, - .moveset = moveset_HTM -}; - -PruneData -pd_coud_HTM = { - .filename = "ptable_coud_HTM", - .coord = &coord_coud, - .moveset = moveset_HTM -}; - -PruneData -pd_cornershtr_HTM = { - .filename = "ptable_cornershtr_withcosets_HTM", - .coord = &coord_cornershtr, - .moveset = moveset_HTM -}; - -PruneData -pd_corners_HTM = { - .filename = "ptable_corners_HTM", - .coord = &coord_corners, - .moveset = moveset_HTM -}; - -PruneData -pd_drud_HTM = { - .filename = "ptable_drud_HTM", - .coord = &coord_drud, - .moveset = moveset_HTM -}; - -PruneData -pd_drud_sym16_HTM = { - .filename = "pd_drud_sym16_HTM", - .coord = &coord_drud_sym16, - .moveset = moveset_HTM, -}; - -PruneData -pd_khuge_HTM = { - .filename = "pd_khuge_HTM", - .coord = &coord_khuge, - .moveset = moveset_HTM -}; - - -/* Standard checkers (return lower bound) ************************************/ - -static int -estimate_eofb_HTM(CubeTarget ct) -{ - if (!pd_eofb_HTM.generated) - genptable(&pd_eofb_HTM); - - return ptableval(&pd_eofb_HTM, ct.cube); -} - -static int -estimate_coud_HTM(CubeTarget ct) -{ - if (!pd_coud_HTM.generated) - genptable(&pd_coud_HTM); - - return ptableval(&pd_coud_HTM, ct.cube); -} - -static int -estimate_coud_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; - CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; - - int ud = estimate_coud_HTM(ct); - int rl = estimate_coud_HTM(ct2); - int fb = estimate_coud_HTM(ct3); - - return MIN(ud, MIN(rl, fb)); -} - -static int -estimate_corners_HTM(CubeTarget ct) -{ - if (!pd_corners_HTM.generated) - genptable(&pd_corners_HTM); - - return ptableval(&pd_corners_HTM, ct.cube); -} - -static int -estimate_cornershtr_HTM(CubeTarget ct) -{ - if (!pd_cornershtr_HTM.generated) - genptable(&pd_cornershtr_HTM); - - return ptableval(&pd_cornershtr_HTM, ct.cube); -} - -static int -estimate_cornershtr_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_cornershtr_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_corners_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_corners_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_drud_HTM(CubeTarget ct) -{ -/* - if (!pd_drud_HTM.generated) - genptable(&pd_drud_HTM); - - return ptableval(&pd_drud_HTM, ct.cube); -*/ - - if (!pd_drud_sym16_HTM.generated) - genptable(&pd_drud_sym16_HTM); - - return ptableval(&pd_drud_sym16_HTM, ct.cube); -} - -/* TODO: if lucky, remove this */ -/* -static int -estimate_optimal_HTM(CubeTarget ct) -{ - static Trans t1 = { .rot = rf, .mirror = false }; - static Trans t2 = { .rot = bd, .mirror = false }; - int dr1, dr2, dr3, cor, ret; - Cube cube = ct.cube; - - dr1 = estimate_drud_HTM(ct); - cor = estimate_corners_HTM(ct); - ret = MAX(dr1, cor); - - if (ret > ct.target) - return ret; - - ct.cube = apply_trans(t1, cube); - dr2 = estimate_drud_HTM(ct); - ret = MAX(ret, dr2); - - if (ret > ct.target) - return ret; - - ct.cube = apply_trans(t2, cube); - dr3 = estimate_drud_HTM(ct); - - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - dr3++; - - ret = MAX(ret, dr3); - - if (ret == 0) - return check_ep(cube) ? 0 : 6; - - return ret; -} -*/ - -static int -estimate_optimal_HTM(CubeTarget ct) -{ - static Trans t2 = rf, t3 = bd; - - int dr1, dr2, dr3, cor, ret; - Cube cube = ct.cube; - - if (!pd_khuge_HTM.generated) - genptable(&pd_khuge_HTM); - - dr1 = ptableval(&pd_khuge_HTM, cube); - cor = estimate_corners_HTM(ct); - ret = MAX(dr1, cor); - - if (ret > ct.target) - return ret; - - cube = apply_trans(t2, ct.cube); - dr2 = ptableval(&pd_khuge_HTM, cube); - ret = MAX(ret, dr2); - - if (ret > ct.target) - return ret; - - cube = apply_trans(t3, ct.cube); - dr3 = ptableval(&pd_khuge_HTM, cube); - - return MAX(ret, dr3); -} diff --git a/old/2021-06-30-reached/steps.h b/old/2021-06-30-reached/steps.h @@ -1,24 +0,0 @@ -#ifndef STEPS_H -#define STEPS_H - -#include "cube.h" - -extern Step eofb_HTM; -extern Step coud_HTM; -extern Step coud_URF; -extern Step corners_HTM; -extern Step cornershtr_HTM; -extern Step corners_URF; -extern Step cornershtr_URF; -extern Step drud_HTM; -extern Step optimal_HTM; - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_cornershtr_HTM; -extern PruneData pd_cornershtreofb_HTM; -extern PruneData pd_drud_HTM; -extern PruneData pd_khuge_HTM; - -#endif diff --git a/old/2021-07-02-genptable-dfs/cube.c b/old/2021-07-02-genptable-dfs/cube.c @@ -1,3394 +0,0 @@ -#include "cube.h" - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static Cube admissible_eos_from_eofbepos(Cube cube); -static bool allowed_next(Move move, DfsData *dd); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static int array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); -static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent_pos(int pos1, int pos2); -static int epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(int epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); -static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); -static void gensym(SymData *sd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void init_auxtables(); -static void init_cphtr_cosets(); -static void init_cphtr_left_cosets_bfs(int i, int c); -static void init_cphtr_right_cosets_color(int i, int c); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_strings(); -static void init_symdata(); -static void init_trans(); -static void init_trans_aux(); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void movelist_to_position(Move *movelist, int *position); -static void moveset_to_list(Moveset ms, Estimator f, Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static void ptable_update(PruneData *pd, Cube cube, int m); -static void realloc_alg(Alg *alg, int n); -static bool read_mtables_file(); -static bool read_ptable_file(PruneData *pd); -static bool read_symdata_file(SymData *sd); -static bool read_ttables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_mtables_file(); -static bool write_ptable_file(PruneData *pd); -static bool write_symdata_file(SymData *sd); -static bool write_ttables_file(); - - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; -static int cphtr_left_cosets[FACTORIAL8]; -static int cphtr_right_cosets[FACTORIAL8]; -static int cphtr_right_rep[BINOM8ON4*6]; -static Center what_center_at_aux[FACTORIAL6][6]; -static Corner what_corner_at_aux[FACTORIAL8][8]; -static int what_orientation_last_corner_aux[POW3TO7]; -static int what_orientation_last_edge_aux[POW2TO11]; -static Center where_is_center_aux[FACTORIAL6][6]; -static Corner where_is_corner_aux[FACTORIAL8][8]; -static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; - -static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eo_ttable[NTRANS][POW2TO11]; -static int cp_ttable[NTRANS][FACTORIAL8]; -static int co_ttable[NTRANS][POW3TO7]; -static int cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eofb_mtable[NMOVES][POW2TO11]; -static int eorl_mtable[NMOVES][POW2TO11]; -static int eoud_mtable[NMOVES][POW2TO11]; -static int cp_mtable[NMOVES][FACTORIAL8]; -static int coud_mtable[NMOVES][POW3TO7]; -static int cofb_mtable[NMOVES][POW3TO7]; -static int corl_mtable[NMOVES][POW3TO7]; -static int cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * rotation_algs[NROTATIONS]; - - -/* Symmetry data for some coordinates ****************************************/ - -static Trans -trans_group_udfix[16] = { - uf, ur, ub, ul, - df, dr, db, dl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, -}; - -SymData -sd_coud_16 = { - .filename = "sd_coud_16", - .coord = &coord_coud, - .sym_coord = &coord_coud_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -SymData -sd_eofbepos_16 = { - .filename = "sd_eofbepos_16", - .coord = &coord_eofbepos, - .sym_coord = &coord_eofbepos_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static int n_all_symdata = 2; -static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; - -/* Coordinates and their implementation **************************************/ - -static uint64_t index_eofb(Cube cube); -static uint64_t index_eofbepos(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_cornershtr(Cube cube); -static uint64_t index_drud(Cube cube); -static uint64_t index_coud_sym16(Cube cube); -static uint64_t index_eofbepos_sym16(Cube cube); -static uint64_t index_drud_sym16(Cube cube); -static uint64_t index_khuge(Cube cube); - -static Cube antindex_eofb(uint64_t ind); -static Cube antindex_eofbepos(uint64_t ind); -static Cube antindex_coud(uint64_t ind); -static Cube antindex_corners(uint64_t ind); -static Cube antindex_cornershtr(uint64_t ind); -static Cube antindex_drud(uint64_t ind); -static Cube antindex_coud_sym16(uint64_t ind); -static Cube antindex_eofbepos_sym16(uint64_t ind); -static Cube antindex_drud_sym16(uint64_t ind); -static Cube antindex_khuge(uint64_t ind); - -Coordinate -coord_eofb = { - .index = index_eofb, - .cube = antindex_eofb, - .check = check_eofb, - .max = POW2TO11 -}; - -Coordinate -coord_eofbepos = { - .index = index_eofbepos, - .cube = antindex_eofbepos, - .check = check_eofbepos, - .max = POW2TO11 * BINOM12ON4 -}; - -Coordinate -coord_coud = { - .index = index_coud, - .cube = antindex_coud, - .check = check_coud, - .max = POW3TO7 -}; - -Coordinate -coord_corners = { - .index = index_corners, - .cube = antindex_corners, - .check = check_corners, - .max = POW3TO7 * FACTORIAL8 -}; - -Coordinate -coord_cornershtr = { - .index = index_cornershtr, - .cube = antindex_cornershtr, - .check = check_cornershtr, - .max = POW3TO7 * BINOM8ON4 * 6 -}; - -Coordinate -coord_drud = { - .index = index_drud, - .cube = antindex_drud, - .check = check_drud, - .max = POW2TO11 * POW3TO7 * BINOM12ON4 -}; - -Coordinate -coord_eofbepos_sym16 = { - .index = index_eofbepos_sym16, - .cube = antindex_eofbepos_sym16, - .check = check_eofbepos, -}; - -Coordinate -coord_coud_sym16 = { - .index = index_coud_sym16, - .cube = antindex_coud_sym16, - .check = check_coud, -}; - -Coordinate -coord_drud_sym16 = { - .index = index_drud_sym16, - .cube = antindex_drud_sym16, - .check = check_drud, - .max = POW3TO7 * 64430 -}; - -Coordinate -coord_khuge = { - .index = index_khuge, - .cube = antindex_khuge, - .check = check_khuge, - .max = POW3TO7 * FACTORIAL4 * 64430 -}; - - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_eofbepos(Cube cube) -{ - return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_cornershtr(Cube cube) -{ - return cube.coud * BINOM8ON4 * 6 + cphtr(cube); -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -static uint64_t -index_coud_sym16(Cube cube) -{ - return sd_coud_16.class[index_coud(cube)]; -} - -static uint64_t -index_drud_sym16(Cube cube) -{ - Trans t; - Cube c; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - - return index_eofbepos_sym16(c) * POW3TO7 + c.coud; -} - -static uint64_t -index_eofbepos_sym16(Cube cube) -{ - return sd_eofbepos_16.class[index_eofbepos(cube)]; -} - -static uint64_t -index_khuge(Cube cube) -{ - Trans t; - Cube c; - uint64_t a; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); - - return a * POW3TO7 + c.coud; -} - - -/* TODO: rename */ -static Cube -antindex_eofb(uint64_t ind) -{ - return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; -} - -static Cube -antindex_eofbepos(uint64_t ind) -{ - return admissible_ee_aux[ind]; -} - -/* TODO: rename */ -static Cube -antindex_coud(uint64_t ind) -{ - return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_corners(uint64_t ind) -{ - Cube c = {0}; - - c.coud = ind / FACTORIAL8; - c.cp = ind % FACTORIAL8; - - return c; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_cornershtr(uint64_t ind) -{ - Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); - - c.coud = ind / (BINOM8ON4 * 6); - - return c; -} - -/* TODO: admissible eos and cos */ -static Cube -antindex_drud(uint64_t ind) -{ - Cube c = {0}; - - c.eofb = ind % POW2TO11; - c.coud = (ind / POW2TO11) % POW3TO7; - c.epose = (ind % (POW2TO11 * POW3TO7)) * FACTORIAL4; - - return c; -} - -static Cube -antindex_coud_sym16(uint64_t ind) -{ - return sd_coud_16.rep[ind]; -} - -static Cube -antindex_eofbepos_sym16(uint64_t ind) -{ - return sd_eofbepos_16.rep[ind]; -} - -static Cube -antindex_drud_sym16(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/POW3TO7]; - c.coud = ind % POW3TO7; - c.cofb = c.coud; - c.corl = c.coud; - - return c; -} - -static Cube -antindex_khuge(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; - c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); - c.coud = ind % POW3TO7; - - return c; -} - - -/* Checkers ******************************************************************/ - -bool -check_centers(Cube cube) -{ - return cube.cpos == 0; -} - -bool -check_corners(Cube cube) -{ - return cube.cp == 0 && cube.coud == 0; -} - -bool -check_cornershtr(Cube cube) -{ - return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ -} - -bool -check_coud(Cube cube) -{ - return cube.coud == 0; -} - -bool -check_drud(Cube cube) -{ - return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; -} - -bool -check_eofb(Cube cube) -{ - return cube.eofb == 0; -} - -bool -check_eofbepos(Cube cube) -{ - return cube.eofb == 0 && cube.epose / 24 == 0; -} - -bool -check_epose(Cube cube) -{ - return cube.epose == 0; -} - -bool -check_ep(Cube cube) -{ - return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; -} - -bool -check_khuge(Cube cube) -{ - return check_drud(cube) && cube.epose % 24 == 0; -} - -bool -check_nothing(Cube cube) -{ - return is_admissible(cube); /*TODO: maybe change?*/ -} - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - - -/* Local functions implementation ********************************************/ - -/* TODO: this should be an anti index (maybe?) */ -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static Cube -admissible_eos_from_eofbepos(Cube cube) -{ - Edge e; - Cube ret; - CubeArray *arr = new_cubearray(cube, pf_all); - - memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); - memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); - - for (e = 0; e < 12; e++) { - if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || - (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) - arr->eorl[e] = 1 - arr->eorl[e]; - if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || - (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) - arr->eoud[e] = 1 - arr->eoud[e]; - } - - ret = arrays_to_cube(arr, pf_all); - free_cubearray(arr, pf_all); - - return ret; -} - -static bool -allowed_next(Move move, DfsData *dd) -{ - if (!possible_next[dd->last2][dd->last1][move]) - return false; - - if (commute[dd->last1][move]) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -} - -static 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; -} - -static 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 Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static int -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -/* -static int -cphtr_cp(int cp) -{ - int i, a[8]; - - index_to_perm(cp, 8, a); - - for (i = 0; i < 8; i++) - if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) - a[i] = 0; - else - a[i] = 1; - - swap(&a[1], &a[5]); - swap(&a[3], &a[7]); - - return subset_to_index(a, 8, 4); -} -*/ - -static void -dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - if (dfs_stop(c, s, opts, dd)) - return; - - if (dfs_check_solved(opts, dd)) - return; - - dfs_branch(c, s, opts, dd); - - if (opts->can_niss && !dd->niss) - dfs_niss(c, s, opts, dd); -} - -static void -dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; - - int i, maxnsol = opts->max_solutions; - - for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { - m = moves[i]; - if (allowed_next(m, dd)) { - dd->last2 = dd->last1; - dd->last1 = m; - append_move(dd->current_alg, m, dd->niss); - - dfs(apply_move(m, c), s, opts, dd); - - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } -} - -static bool -dfs_check_solved(SolveOptions *opts, DfsData *dd) -{ - if (dd->lb != 0) - return false; - - if (dd->current_alg->len == dd->d) { - append_alg(dd->sols, dd->current_alg); - - if (opts->feedback) - print_alg(dd->current_alg, false); - } - - return true; -} - -static void -dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move l1 = dd->last1, l2 = dd->last2; - CubeTarget ct; - - ct.cube = apply_move(inverse_move(l1), (Cube){0}); - ct.target = 1; - - if (dd->current_alg->len == 0 || s.estimate(ct)) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - - dfs(inverse_cube(c), s, opts, dd); - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = false; - } -} - -static bool -dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - CubeTarget ct = { - .cube = c, - .target = dd->d - dd->current_alg->len - }; - - if (dd->sols->len >= opts->max_solutions) - return true; - - dd->lb = s.estimate(ct); - if (opts->can_niss && !dd->niss) - dd->lb = MIN(1, dd->lb); - - if (dd->current_alg->len + dd->lb > dd->d) - return true; - - return false; -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent_pos(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 0) - ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; - - swap(&ep8[1], &ep8[4]); - swap(&ep8[3], &ep8[6]); - - return subset_to_index(ep8, 8, 4); -} - -static int -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(int epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -genptable_dfs(Cube c, PruneData *pd, DfsData *dd) -{ - int oldval = ptableval(pd, c); - - if (oldval < dd->m || pd->n == pd->coord->max || - (dd->m != 0 && pd->coord->check(c)) ) - return; - - if (dd->m == dd->d) { - if (dd->m < oldval) - ptable_update(pd, c, dd->m); - return; - } - - genptable_dfs_branch(c, pd, dd); -} - -static void -genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) -{ - Move i, move, l1 = dd->last1, l2 = dd->last2; - - dd->m++; - - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - move = dd->sorted_moves[i]; - if (allowed_next(move, dd)) { - dd->last2 = dd->last1; - dd->last1 = move; - - genptable_dfs(apply_move(move, c), pd, dd); - - dd->last2 = l2; - dd->last1 = l1; - } - } - - dd->m--; -} - -static void -gensym(SymData *sd) -{ - uint64_t i, in, nreps = 0; - int j; - Cube c, d; - - if (sd->generated) - return; - - sd->class = malloc(sd->coord->max * sizeof(uint64_t)); - sd->rep = malloc(sd->coord->max * sizeof(Cube)); - sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); - - if (read_symdata_file(sd)) { - sd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); - - for (i = 0; i < sd->coord->max; i++) - sd->class[i] = sd->coord->max + 1; - - for (i = 0; i < sd->coord->max; i++) { - if (sd->class[i] == sd->coord->max + 1) { - c = sd->coord->cube(i); - sd->rep[nreps] = c; - for (j = 0; j < sd->ntrans; j++) { - d = apply_trans(sd->trans[j], c); - in = sd->coord->index(d); - - if (sd->class[in] == sd->coord->max + 1) { - sd->class[in] = nreps; - sd->transtorep[in] = - inverse_trans(sd->trans[j]); - } - } - nreps++; - } - } - - sd->sym_coord->max = nreps; - sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); - sd->generated = true; - - fprintf(stderr, "Found %lu classes\n", nreps); - - if (!write_symdata_file(sd)) - fprintf(stderr, "Error writing SymData file\n"); - - return; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -static void -moveset_to_list(Moveset ms, Estimator f, Move *r) -{ - CubeTarget ct = { .target = 1 }; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - ct.cube = apply_move(i, (Cube){0}); - if (f != NULL && f(ct)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static void -ptable_update(PruneData *pd, Cube cube, int n) -{ - uint64_t ind = pd->coord->index(cube); - uint8_t oldval2 = pd->ptable[ind/2]; - int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; - pd->n++; -} - -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; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return r == ptablesize(pd); -} - -static bool -read_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(int); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); - Cube ret = {0}; - - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - ret = apply_alg_generic(inv, ret, f, true); - - ret = compose_filtered(c, ret, f); - - ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - - free_alg(inv); - return ret; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return written == ptablesize(pd); -} - -static bool -write_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(int); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - CubeArray *arr; - uint64_t ui, uj; - int i, j, k, auxarr[12]; - bool cij, p1, p2; - - for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { - k = (ui / POW2TO11) * 24; - c1 = admissible_ep((Cube){ .epose = k }, pf_e); - c1.eofb = ui % POW2TO11; - c1 = admissible_eos_from_eofbepos(c1); - admissible_ee_aux[ui] = c1; - } - - for (ui = 0; ui < FACTORIAL6; ui++) { - arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); - for (i = 0; i < 6; i++) { - what_center_at_aux[ui][i] = arr->cpos[i]; - where_is_center_aux[ui][arr->cpos[i]] = i; - } - free_cubearray(arr, pf_cpos); - } - - for (ui = 0; ui < FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.cp = ui}, pf_cp); - for (i = 0; i < 8; i++) { - what_corner_at_aux[ui][i] = arr->cp[i]; - where_is_corner_aux[ui][arr->cp[i]] = i; - } - free_cubearray(arr, pf_cp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.epose = ui}, pf_e); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 0) - where_is_edge_aux[0][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_e); - - arr = new_cubearray((Cube){.eposs = ui}, pf_s); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 1) - where_is_edge_aux[1][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_s); - - arr = new_cubearray((Cube){.eposm = ui}, pf_m); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 2) - where_is_edge_aux[2][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_m); - } - - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, auxarr); - what_orientation_last_corner_aux[ui] = auxarr[7]; - } - - for (ui = 0; ui < POW2TO11; ui++) { - int_to_sum_zero_array(ui, 2, 12, auxarr); - what_orientation_last_edge_aux[ui] = auxarr[11]; - } - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2) && i && j; - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[uf_mirror] = uf_mirror; - inverse_trans_aux[ur_mirror] = ur_mirror; - inverse_trans_aux[ul_mirror] = ul_mirror; - inverse_trans_aux[ub_mirror] = ub_mirror; - - inverse_trans_aux[df_mirror] = df_mirror; - inverse_trans_aux[dr_mirror] = dl_mirror; - inverse_trans_aux[dl_mirror] = dr_mirror; - inverse_trans_aux[db_mirror] = db_mirror; - - inverse_trans_aux[rf_mirror] = rf_mirror; - inverse_trans_aux[rd_mirror] = br_mirror; - inverse_trans_aux[rb_mirror] = lb_mirror; - inverse_trans_aux[ru_mirror] = fl_mirror; - - inverse_trans_aux[lf_mirror] = lf_mirror; - inverse_trans_aux[ld_mirror] = bl_mirror; - inverse_trans_aux[lb_mirror] = rb_mirror; - inverse_trans_aux[lu_mirror] = fr_mirror; - - inverse_trans_aux[fu_mirror] = fu_mirror; - inverse_trans_aux[fr_mirror] = lu_mirror; - inverse_trans_aux[fd_mirror] = bu_mirror; - inverse_trans_aux[fl_mirror] = ru_mirror; - - inverse_trans_aux[bu_mirror] = fd_mirror; - inverse_trans_aux[br_mirror] = rd_mirror; - inverse_trans_aux[bd_mirror] = bd_mirror; - inverse_trans_aux[bl_mirror] = ld_mirror; -} - -/* - * There is certainly a bette way to do this, but for now I just use - * a "graph coloring" algorithm to compute the left cosets, and I compose - * with every possible cp to get the right cosets (it is possible that I am - * mixing up left and right). - * - * For doing it better "Mathematically", we need 3 things: - * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other - * This is easy and it is done in the commented function cphtr_cp(). - * - Check that there is no ep/cp parity - * - Check that we are not in the "3c" case; this is the part I don't - * know how to do. - */ -static void -init_cphtr_cosets() -{ - unsigned int i; - int c = 0, d = 0; - - for (i = 0; i < FACTORIAL8; i++) { - cphtr_left_cosets[i] = -1; - cphtr_right_cosets[i] = -1; - } - - /* First we compute left cosets with a bfs */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_left_cosets[i] == -1) - init_cphtr_left_cosets_bfs(i, c++); - - /* Then we compute right cosets using compose() */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_right_cosets[i] == -1) - init_cphtr_right_cosets_color(i, d++); -} - -static void -init_cphtr_left_cosets_bfs(int i, int c) -{ - int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; - Move moves[6] = {U2, D2, R2, L2, F2, B2}; - - n = 1; - next[0] = i; - cphtr_left_cosets[i] = c; - - while (n != 0) { - for (j = 0, n2 = 0; j < n; j++) { - for (k = 0; k < 6; k++) { - jj = cp_mtable[moves[k]][next[j]]; - if (cphtr_left_cosets[jj] == -1) { - cphtr_left_cosets[jj] = c; - next2[n2++] = jj; - } - } - } - - for (j = 0; j < n2; j++) - next[j] = next2[j]; - n = n2; - } -} - -static void -init_cphtr_right_cosets_color(int i, int d) -{ - int cp; - unsigned int j; - - cphtr_right_rep[d] = i; - for (j = 0; j < FACTORIAL8; j++) { - if (cphtr_left_cosets[j] == 0) { - /* TODO: use antindexer, it's nicer */ - cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; - cphtr_right_cosets[cp] = d; - } - } -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - unsigned int ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray) { - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_symdata() -{ - int i; - - for (i = 0; i < n_all_symdata; i++) - gensym(all_sd[i]); -} - -static void -init_trans() { - Cube aux, cube, mirr, c[3]; - CubeArray epcp; - int i, eparr[12], eoarr[12], cparr[8], coarr[8]; - unsigned int ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); - - epose_source[i] = edge_slice(what_edge_at(cube, FR)); - eposs_source[i] = edge_slice(what_edge_at(cube, UR)); - eposm_source[i] = edge_slice(what_edge_at(cube, UF)); - eofb_source[i] = what_center_at(cube, F_center)/2; - eorl_source[i] = what_center_at(cube, R_center)/2; - eoud_source[i] = what_center_at(cube, U_center)/2; - coud_source[i] = what_center_at(cube, U_center)/2; - cofb_source[i] = what_center_at(cube, F_center)/2; - corl_source[i] = what_center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - if (m >= NROTATIONS) { - apply_permutation(ep_mirror, eparr, 12); - apply_permutation(cp_mirror, cparr, 8); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m >= NROTATIONS) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - aux = apply_trans(m, apply_move(mi, (Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move(inverse_move_aux[move], aux); - mirr = apply_trans(uf_mirror, cube); - if (is_solved(cube, false) || - is_solved(mirr, false)) - moves_ttable[m][mi] = move; - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - rotation_algs[uf] = new_alg(""); - rotation_algs[ur] = new_alg("y"); - rotation_algs[ub] = new_alg("y2"); - rotation_algs[ul] = new_alg("y3"); - - rotation_algs[df] = new_alg("z2"); - rotation_algs[dr] = new_alg("y z2"); - rotation_algs[db] = new_alg("x2"); - rotation_algs[dl] = new_alg("y3 z2"); - - rotation_algs[rf] = new_alg("z3"); - rotation_algs[rd] = new_alg("z3 y"); - rotation_algs[rb] = new_alg("z3 y2"); - rotation_algs[ru] = new_alg("z3 y3"); - - rotation_algs[lf] = new_alg("z"); - rotation_algs[ld] = new_alg("z y3"); - rotation_algs[lb] = new_alg("z y2"); - rotation_algs[lu] = new_alg("z y"); - - rotation_algs[fu] = new_alg("x y2"); - rotation_algs[fr] = new_alg("x y"); - rotation_algs[fd] = new_alg("x"); - rotation_algs[fl] = new_alg("x y3"); - - rotation_algs[bu] = new_alg("x3"); - rotation_algs[br] = new_alg("x3 y"); - rotation_algs[bd] = new_alg("x3 y2"); - rotation_algs[bl] = new_alg("x3 y3"); -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - return (Cube) { - .epose = epose_mtable[m][cube.epose], - .eposs = eposs_mtable[m][cube.eposs], - .eposm = eposm_mtable[m][cube.eposm], - .eofb = eofb_mtable[m][cube.eofb], - .eorl = eorl_mtable[m][cube.eorl], - .eoud = eoud_mtable[m][cube.eoud], - .coud = coud_mtable[m][cube.coud], - .cofb = cofb_mtable[m][cube.cofb], - .corl = corl_mtable[m][cube.corl], - .cp = cp_mtable[m][cube.cp], - .cpos = cpos_mtable[m][cube.cpos] - }; -} - - -Cube -apply_trans(Trans t, Cube cube) -{ - int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - return (Cube) { - .epose = epose_ttable[t][aux_epos[epose_source[t]]], - .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], - .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], - .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], - .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], - .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], - .coud = co_ttable[t][aux_co[coud_source[t]]], - .corl = co_ttable[t][aux_co[corl_source[t]]], - .cofb = co_ttable[t][aux_co[cofb_source[t]]], - .cp = cp_ttable[t][cube.cp], - .cpos = cpos_ttable[t][cube.cpos] - }; -} - -Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -/*TODO maybe move the next two */ -uint64_t -cphtr(Cube cube) -{ - return cphtr_right_cosets[cube.cp]; -} - -Cube -anti_cphtr(uint64_t ind) -{ - return (Cube) { .cp = cphtr_right_rep[ind] }; -} - -uint64_t -epos_dependent(Cube c) -{ - return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -void -genptable(PruneData *pd) -{ - Cube cube; - uint64_t j, oldn = 0; - DfsData dd = { - .m = 0, - .last1 = NULLMOVE, - .last2 = NULLMOVE - }; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->coord->max; j++) - ptable_update(pd, pd->coord->cube(j), 15); - - moveset_to_list(pd->moveset, NULL, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->coord->max; dd.d++) { - for (j = 0; j < pd->coord->max; j++) { - cube = pd->coord->cube(j); - if (pd->coord->check(cube)) - genptable_dfs(cube, pd, &dd); - } - fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", - dd.d, pd->n-oldn, pd->n, pd->coord->max); - oldn = pd->n; - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - int i; - - if (reorient) { - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(rotation_algs[i], cube),false)) - return true; - return false; - } else { - return equal(cube, (Cube){0}); - } -} - -bool -is_solved_block(Cube cube, Block block) -{ - int i; - - for (i = 0; i < 12; i++) - if (block.edge[i] && !is_solved_edge(cube, i)) - return false; - for (i = 0; i < 8; i++) - if (block.corner[i] && !is_solved_corner(cube, i)) - return false; - for (i = 0; i < 6; i++) - if (block.center[i] && !is_solved_center(cube, i)) - return false; - - return true; -} - -bool -is_solved_center(Cube cube, Center c) -{ - return what_center_at(cube, c) == c; -} - -bool -is_solved_corner(Cube cube, Corner c) -{ - return what_corner_at(cube, c) == c && - what_orientation_corner(cube.coud, c); -} - -bool -is_solved_edge(Cube cube, Edge e) -{ - return what_edge_at(cube, e) == e && - what_orientation_edge(cube.eofb, e); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b, x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ -/* - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -*/ - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[what_edge_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %d ", what_orientation_edge(cube.eofb, i)); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[what_corner_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %d ", what_orientation_corner(cube.coud, i)); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[what_center_at(cube, i)]); - printf("\n"); - -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -/* TODO: clean pre_trans or put it back */ -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - /*AlgListNode *node;*/ - AlgList *sols = new_alglist(); - /*Cube c = apply_trans(opts->pre_trans, cube);*/ - DfsData dd = { - .m = 0, - .niss = false, - .lb = -1, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && !step.ready(cube)) { - fprintf(stderr, "Cube not ready for solving step\n"); - return sols; - } - - moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = opts->min_moves; - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - if (opts->feedback) - fprintf(stderr, - "Found %d solutions, searching depth %d...\n", - sols->len, dd.d); - dfs(cube, step, opts, &dd); - } - -/* - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans(opts->pre_trans), node->alg); -*/ - - free_alg(dd.current_alg); - return sols; -} - -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; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - /* TODO: make it possible to print to stdout or to string */ - /* Maybe just return a string */ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - for (i = 0; i < 16; i++) - a[i] = 0; - - if (!pd->generated) - genptable(pd); - - for (i = 0; i < pd->coord->max; i++) - a[ptableval(pd, pd->coord->cube(i))]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -uint64_t -ptablesize(PruneData *pd) -{ - return (pd->coord->max + 1) / 2; -} - -int -ptableval(PruneData *pd, Cube cube) -{ - uint64_t ind = pd->coord->index(cube); - - return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; -} - - -Alg * -rotation_alg(Trans i) -{ - return rotation_algs[i % NROTATIONS]; -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} - -Center -what_center_at(Cube cube, Center c) -{ - return what_center_at_aux[cube.cpos][c]; -} - -Corner -what_corner_at(Cube cube, Corner c) -{ - return what_corner_at_aux[cube.cp][c]; -} - -Edge -what_edge_at(Cube cube, Edge e) -{ - Edge ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - - free_cubearray(arr, pf_ep); - return ret; -} - -int -what_orientation_corner(int co, Corner c) -{ - if (c < 7) - return (co / powint(3, c)) % 3; - else - return what_orientation_last_corner_aux[co]; -} - -int -what_orientation_edge(int eo, Edge e) -{ - if (e < 11) - return (eo & (1 << e)) ? 1 : 0; - else - return what_orientation_last_edge_aux[eo]; -} - -Center -where_is_center(Cube cube, Center c) -{ - return where_is_center_aux[cube.cpos][c]; -} - -Corner -where_is_corner(Cube cube, Corner c) -{ - return where_is_corner_aux[cube.cp][c]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_cphtr_cosets(); - init_trans_aux(); - init_trans(); - init_symdata(); -} - diff --git a/old/2021-07-02-genptable-dfs/cube.h b/old/2021-07-02-genptable-dfs/cube.h @@ -1,90 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> - -#include "macros.h" -#include "cubetypes.h" - -extern Coordinate coord_eofb; -extern Coordinate coord_eofbepos; -extern Coordinate coord_coud; -extern Coordinate coord_corners; -extern Coordinate coord_cornershtr; -extern Coordinate coord_drud; -extern Coordinate coord_coud_sym16; -extern Coordinate coord_eofbepos_sym16; -extern Coordinate coord_drud_sym16; -extern Coordinate coord_khuge; - -Cube apply_alg(Alg *alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ -Cube anti_cphtr(uint64_t ind); /*TODO also this */ -uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_admissible(Cube cube); -bool is_solved(Cube cube, bool reorient); -bool is_solved_center(Cube cube, Center c); -bool is_solved_corner(Cube cube, Corner c); -bool is_solved_edge(Cube cube, Edge e); -void print_cube(Cube cube); -Cube random_cube(); -AlgList * solve(Cube cube, Step step, SolveOptions *opts); -Center what_center_at(Cube cube, Center c); -Corner what_corner_at(Cube cube, Corner c); -Edge what_edge_at(Cube cube, Edge e); -int what_orientation_corner(int co, Corner c); -int what_orientation_edge(int eo, Edge e); -Center where_is_center(Cube cube, Center c); -Corner where_is_corner(Cube cube, Corner c); -Edge where_is_edge(Cube cube, Edge e); - -bool check_centers(Cube cube); -bool check_corners(Cube cube); -bool check_cornershtr(Cube cube); -bool check_coud(Cube cube); -bool check_drud(Cube cube); -bool check_eofb(Cube cube); -bool check_eofbepos(Cube cube); -bool check_epose(Cube cube); -bool check_ep(Cube cube); -bool check_khuge(Cube cube); -bool check_nothing(Cube cube); - -bool moveset_HTM(Move m); -bool moveset_URF(Move m); - -Move base_move(Move m); -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Alg * new_alg(char *str); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); -Alg * rotation_alg(Trans i); -void transform_alg(Trans t, Alg *alg); - -void genptable(PruneData *pd); -void print_ptable(PruneData *pd); -uint64_t ptablesize(PruneData *pd); -int ptableval(PruneData *pd, Cube cube); - -void init(); - -#endif - diff --git a/old/2021-07-02-genptable-dfs/cubetypes.h b/old/2021-07-02-genptable-dfs/cubetypes.h @@ -1,250 +0,0 @@ -#ifndef CUBETYPES_H -#define CUBETYPES_H - -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct block Block; -typedef struct coordinate Coordinate; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct cubetarget CubeTarget; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; -typedef struct symdata SymData; - -typedef Cube (*AntiIndexer) (uint64_t); -typedef bool (*Checker) (Cube); -typedef int (*Estimator) (CubeTarget); -typedef uint64_t (*Indexer) (Cube); -typedef bool (*Moveset) (Move); - - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, - rf_mirror, rd_mirror, rb_mirror, ru_mirror, - lf_mirror, ld_mirror, lb_mirror, lu_mirror, - fu_mirror, fr_mirror, fd_mirror, fl_mirror, - bu_mirror, br_mirror, bd_mirror, bl_mirror, -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - Move * move; - bool * inv; - int len; - int allocated; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -coordinate -{ - Indexer index; - AntiIndexer cube; - Checker check; - uint64_t max; -}; - -struct -cube -{ - int epose; - int eposs; - int eposm; - int eofb; - int eorl; - int eoud; - int cp; - int coud; - int cofb; - int corl; - int cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -cubetarget -{ - Cube cube; - int target; -}; - -struct -dfsdata -{ - int d; - int m; - int lb; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[NMOVES]; - int move_position[NMOVES]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - bool generated; - uint64_t n; - Coordinate * coord; - Moveset moveset; -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; -}; - -struct -step -{ - Estimator estimate; - Checker ready; - Moveset moveset; -}; - -struct -symdata -{ - char * filename; - bool generated; - Coordinate * coord; - Coordinate * sym_coord; - int ntrans; - Trans * trans; - uint64_t * class; - Cube * rep; - Trans * transtorep; -}; - -#endif diff --git a/old/2021-07-02-genptable-dfs/macros.h b/old/2021-07-02-genptable-dfs/macros.h @@ -1,23 +0,0 @@ -#ifndef MACROS_H -#define MACROS_H - -#define POW2TO6 64ULL -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL7 5040ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define NMOVES (z3+1) -#define NTRANS 48 -#define NROTATIONS 24 - -#endif diff --git a/old/2021-07-02-genptable-dfs/main.c b/old/2021-07-02-genptable-dfs/main.c @@ -1,80 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "steps.h" - -int main() { - Alg *algo; - AlgList *sols; - Cube cube; - SolveOptions opts; - char line[1000]; - int i, ns = 2; -/* Move m;*/ -/* int nrand = 10000, sum1, sum2, sum3;*/ - - Step *stps[20] = {&drud_HTM, &optimal_HTM}; - char sss[30][30] = {"DR on UD", "Optimal solve"}; - - opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 20, - .optimal_only = true, - .max_solutions = 1, - .can_niss = false, - .feedback = true, - }; - - init(); - -/* - srand(time(NULL)); - sum1 = 0; - sum2 = 0; - sum3 = 0; - for (i = 0; i < nrand; i++) { - cube = random_cube(); - sum1 += drud_HTM.check(cube, 20); - sum2 += optimal_HTM.check(cube, 20); - sum3 += cornershtreofb_HTM.check(cube, 20); - } - printf("Average drud pruning: %lf\n", ((double)sum1) / ((double) nrand)); - printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); - printf("Average corners htr + eofb pruning: %lf\n", ((double)sum3) / ((double) nrand)); -*/ - -/* - for (m = U; m <= B3; m++) { - printf("Class eofbepos after %d: ", m); - printf("%lu\n", coord_khuge.index(apply_move(m,(Cube){0}))); - } -*/ - - printf("Welcome to nissy 2.0! Insert a scramble:\n"); - - if (fgets(line, 1000, stdin) != NULL) { - algo = new_alg(line); - cube = apply_alg(algo, (Cube){0}); - - print_alg(inverse_alg(algo), false); -/* - printf("After rb_mirror:\n"); - cube = apply_trans(rb_mirror, cube); - print_cube(cube); - printf("Going back:\n"); - cube = apply_trans(inverse_trans(rb_mirror), cube); -*/ - - print_cube(cube); - - for (i = 0; i < ns; i++) { - sols = solve(cube, *stps[i], &opts); - printf("%s: %d solutions found:\n", sss[i], sols->len); - print_alglist(sols, true); - free_alglist(sols); - } - free_alg(algo); - } - - return 0; -} - diff --git a/old/2021-07-02-genptable-dfs/steps.c b/old/2021-07-02-genptable-dfs/steps.c @@ -1,307 +0,0 @@ -#include "steps.h" - -/* Standard checkers (return lower bound) ************************************/ - -static int estimate_eofb_HTM(CubeTarget ct); -static int estimate_coud_HTM(CubeTarget ct); -static int estimate_coud_URF(CubeTarget ct); -static int estimate_corners_HTM(CubeTarget ct); -static int estimate_cornershtr_HTM(CubeTarget ct); -static int estimate_corners_URF(CubeTarget ct); -static int estimate_cornershtr_URF(CubeTarget ct); -static int estimate_drud_HTM(CubeTarget ct); -static int estimate_optimal_HTM(CubeTarget ct); - -/* Steps *********************************************************************/ - -Step -eofb_HTM = { - .estimate = estimate_eofb_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_HTM = { - .estimate = estimate_coud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_URF = { - .estimate = estimate_coud_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_HTM = { - .estimate = estimate_corners_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_HTM = { - .estimate = estimate_cornershtr_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_URF = { - .estimate = estimate_cornershtr_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_URF = { - .estimate = estimate_corners_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -drud_HTM = { - .estimate = estimate_drud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -optimal_HTM = { - .estimate = estimate_optimal_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - - -/* Pruning tables ************************************************************/ - -PruneData -pd_eofb_HTM = { - .filename = "ptable_eofb_HTM", - .coord = &coord_eofb, - .moveset = moveset_HTM -}; - -PruneData -pd_coud_HTM = { - .filename = "ptable_coud_HTM", - .coord = &coord_coud, - .moveset = moveset_HTM -}; - -PruneData -pd_cornershtr_HTM = { - .filename = "ptable_cornershtr_withcosets_HTM", - .coord = &coord_cornershtr, - .moveset = moveset_HTM -}; - -PruneData -pd_corners_HTM = { - .filename = "ptable_corners_HTM", - .coord = &coord_corners, - .moveset = moveset_HTM -}; - -PruneData -pd_drud_HTM = { - .filename = "ptable_drud_HTM", - .coord = &coord_drud, - .moveset = moveset_HTM -}; - -PruneData -pd_drud_sym16_HTM = { - .filename = "ptable_drud_sym16_HTM", - .coord = &coord_drud_sym16, - .moveset = moveset_HTM, -}; - -PruneData -pd_khuge_HTM = { - .filename = "ptable_khuge_HTM", - .coord = &coord_khuge, - .moveset = moveset_HTM -}; - - -/* Standard checkers (return lower bound) ************************************/ - -static int -estimate_eofb_HTM(CubeTarget ct) -{ - if (!pd_eofb_HTM.generated) - genptable(&pd_eofb_HTM); - - return ptableval(&pd_eofb_HTM, ct.cube); -} - -static int -estimate_coud_HTM(CubeTarget ct) -{ - if (!pd_coud_HTM.generated) - genptable(&pd_coud_HTM); - - return ptableval(&pd_coud_HTM, ct.cube); -} - -static int -estimate_coud_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; - CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; - - int ud = estimate_coud_HTM(ct); - int rl = estimate_coud_HTM(ct2); - int fb = estimate_coud_HTM(ct3); - - return MIN(ud, MIN(rl, fb)); -} - -static int -estimate_corners_HTM(CubeTarget ct) -{ - if (!pd_corners_HTM.generated) - genptable(&pd_corners_HTM); - - return ptableval(&pd_corners_HTM, ct.cube); -} - -static int -estimate_cornershtr_HTM(CubeTarget ct) -{ - if (!pd_cornershtr_HTM.generated) - genptable(&pd_cornershtr_HTM); - - return ptableval(&pd_cornershtr_HTM, ct.cube); -} - -static int -estimate_cornershtr_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_cornershtr_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_corners_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_corners_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_drud_HTM(CubeTarget ct) -{ -/* - if (!pd_drud_HTM.generated) - genptable(&pd_drud_HTM); - - return ptableval(&pd_drud_HTM, ct.cube); -*/ - - if (!pd_drud_sym16_HTM.generated) - genptable(&pd_drud_sym16_HTM); - - return ptableval(&pd_drud_sym16_HTM, ct.cube); -} - -/* TODO: if lucky, remove this */ -/* -static int -estimate_optimal_HTM(CubeTarget ct) -{ - static Trans t1 = { .rot = rf, .mirror = false }; - static Trans t2 = { .rot = bd, .mirror = false }; - int dr1, dr2, dr3, cor, ret; - Cube cube = ct.cube; - - dr1 = estimate_drud_HTM(ct); - cor = estimate_corners_HTM(ct); - ret = MAX(dr1, cor); - - if (ret > ct.target) - return ret; - - ct.cube = apply_trans(t1, cube); - dr2 = estimate_drud_HTM(ct); - ret = MAX(ret, dr2); - - if (ret > ct.target) - return ret; - - ct.cube = apply_trans(t2, cube); - dr3 = estimate_drud_HTM(ct); - - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - dr3++; - - ret = MAX(ret, dr3); - - if (ret == 0) - return check_ep(cube) ? 0 : 6; - - return ret; -} -*/ - -static int -estimate_optimal_HTM(CubeTarget ct) -{ - static Trans t2 = rf, t3 = bd; - - int dr1, dr2, dr3, cor, ret; - Cube cube = ct.cube; - - if (!pd_khuge_HTM.generated) - genptable(&pd_khuge_HTM); - - dr1 = ptableval(&pd_khuge_HTM, cube); - cor = estimate_corners_HTM(ct); - ret = MAX(dr1, cor); - - if (ret > ct.target) - return ret; - - cube = apply_trans(t2, ct.cube); - dr2 = ptableval(&pd_khuge_HTM, cube); - ret = MAX(ret, dr2); - - if (ret > ct.target) - return ret; - - cube = apply_trans(t3, ct.cube); - dr3 = ptableval(&pd_khuge_HTM, cube); - - return MAX(ret, dr3); -} diff --git a/old/2021-07-02-genptable-dfs/steps.h b/old/2021-07-02-genptable-dfs/steps.h @@ -1,24 +0,0 @@ -#ifndef STEPS_H -#define STEPS_H - -#include "cube.h" - -extern Step eofb_HTM; -extern Step coud_HTM; -extern Step coud_URF; -extern Step corners_HTM; -extern Step cornershtr_HTM; -extern Step corners_URF; -extern Step cornershtr_URF; -extern Step drud_HTM; -extern Step optimal_HTM; - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_cornershtr_HTM; -extern PruneData pd_cornershtreofb_HTM; -extern PruneData pd_drud_HTM; -extern PruneData pd_khuge_HTM; - -#endif diff --git a/old/2021-07-15-almostbeforerefactor/README b/old/2021-07-15-almostbeforerefactor/README @@ -1,3 +0,0 @@ -I started refactorig (splitting code into more files) before realizing I had no backup of -the fast version that works. -Take some stuff from alg.h back into cube.h, remove alg.* ad it should be ok. diff --git a/old/2021-07-15-almostbeforerefactor/alg.c b/old/2021-07-15-almostbeforerefactor/alg.c @@ -1,3388 +0,0 @@ -#include "alg.h" - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static Cube admissible_eos_from_eofbepos(Cube cube); -static bool allowed_next(Move move, DfsData *dd); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static int array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); -static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent_pos(int pos1, int pos2); -static int epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(int epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void genptable_bfs(PruneData *pd, int d, Move *ms); -static void genptable_branch(PruneData *pd, uint64_t i, int d, Move *m); -static void gensym(SymData *sd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void init_auxtables(); -static void init_cphtr_cosets(); -static void init_cphtr_left_cosets_bfs(int i, int c); -static void init_cphtr_right_cosets_color(int i, int c); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_strings(); -static void init_symdata(); -static void init_trans(); -static void init_trans_aux(); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void movelist_to_position(Move *movelist, int *position); -static void moveset_to_list(Moveset ms, Estimator f, Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static void ptable_update(PruneData *pd, Cube cube, int m); -static int ptableval_index(PruneData *pd, uint64_t ind); -static void realloc_alg(Alg *alg, int n); -static bool read_mtables_file(); -static bool read_ptable_file(PruneData *pd); -static bool read_symdata_file(SymData *sd); -static bool read_ttables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_mtables_file(); -static bool write_ptable_file(PruneData *pd); -static bool write_symdata_file(SymData *sd); -static bool write_ttables_file(); - - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; -static int cphtr_left_cosets[FACTORIAL8]; -static int cphtr_right_cosets[FACTORIAL8]; -static int cphtr_right_rep[BINOM8ON4*6]; -static Center what_center_at_aux[FACTORIAL6][6]; -static Corner what_corner_at_aux[FACTORIAL8][8]; -static int what_orientation_last_corner_aux[POW3TO7]; -static int what_orientation_last_edge_aux[POW2TO11]; -static Center where_is_center_aux[FACTORIAL6][6]; -static Corner where_is_corner_aux[FACTORIAL8][8]; -static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; - -static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eo_ttable[NTRANS][POW2TO11]; -static int cp_ttable[NTRANS][FACTORIAL8]; -static int co_ttable[NTRANS][POW3TO7]; -static int cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eofb_mtable[NMOVES][POW2TO11]; -static int eorl_mtable[NMOVES][POW2TO11]; -static int eoud_mtable[NMOVES][POW2TO11]; -static int cp_mtable[NMOVES][FACTORIAL8]; -static int coud_mtable[NMOVES][POW3TO7]; -static int cofb_mtable[NMOVES][POW3TO7]; -static int corl_mtable[NMOVES][POW3TO7]; -static int cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * rotation_algs[NROTATIONS]; - - -/* Symmetry data for some coordinates ****************************************/ - -Trans -trans_group_trivial[1] = { uf }; - -Trans -trans_group_udfix[16] = { - uf, ur, ub, ul, - df, dr, db, dl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, -}; - -SymData -sd_coud_16 = { - .filename = "sd_coud_16", - .coord = &coord_coud, - .sym_coord = &coord_coud_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -SymData -sd_eofbepos_16 = { - .filename = "sd_eofbepos_16", - .coord = &coord_eofbepos, - .sym_coord = &coord_eofbepos_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static int n_all_symdata = 2; -static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; - -/* Coordinates and their implementation **************************************/ - -static uint64_t index_eofb(Cube cube); -static uint64_t index_eofbepos(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_cornershtr(Cube cube); -static uint64_t index_drud(Cube cube); -static uint64_t index_coud_sym16(Cube cube); -static uint64_t index_eofbepos_sym16(Cube cube); -static uint64_t index_drud_sym16(Cube cube); -static uint64_t index_khuge(Cube cube); - -static Cube antindex_eofb(uint64_t ind); -static Cube antindex_eofbepos(uint64_t ind); -static Cube antindex_coud(uint64_t ind); -static Cube antindex_corners(uint64_t ind); -static Cube antindex_cornershtr(uint64_t ind); -static Cube antindex_drud(uint64_t ind); -static Cube antindex_coud_sym16(uint64_t ind); -static Cube antindex_eofbepos_sym16(uint64_t ind); -static Cube antindex_drud_sym16(uint64_t ind); -static Cube antindex_khuge(uint64_t ind); - -Coordinate -coord_eofb = { - .index = index_eofb, - .cube = antindex_eofb, - .check = check_eofb, - .max = POW2TO11 -}; - -Coordinate -coord_eofbepos = { - .index = index_eofbepos, - .cube = antindex_eofbepos, - .check = check_eofbepos, - .max = POW2TO11 * BINOM12ON4 -}; - -Coordinate -coord_coud = { - .index = index_coud, - .cube = antindex_coud, - .check = check_coud, - .max = POW3TO7 -}; - -Coordinate -coord_corners = { - .index = index_corners, - .cube = antindex_corners, - .check = check_corners, - .max = POW3TO7 * FACTORIAL8 -}; - -Coordinate -coord_cornershtr = { - .index = index_cornershtr, - .cube = antindex_cornershtr, - .check = check_cornershtr, - .max = POW3TO7 * BINOM8ON4 * 6 -}; - -Coordinate -coord_drud = { - .index = index_drud, - .cube = antindex_drud, - .check = check_drud, - .max = POW2TO11 * POW3TO7 * BINOM12ON4 -}; - -Coordinate -coord_eofbepos_sym16 = { - .index = index_eofbepos_sym16, - .cube = antindex_eofbepos_sym16, - .check = check_eofbepos, -}; - -Coordinate -coord_coud_sym16 = { - .index = index_coud_sym16, - .cube = antindex_coud_sym16, - .check = check_coud, -}; - -Coordinate -coord_drud_sym16 = { - .index = index_drud_sym16, - .cube = antindex_drud_sym16, - .check = check_drud, - .max = POW3TO7 * 64430 -}; - -Coordinate -coord_khuge = { - .index = index_khuge, - .cube = antindex_khuge, - .check = check_khuge, - .max = POW3TO7 * FACTORIAL4 * 64430 -}; - - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_eofbepos(Cube cube) -{ - return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_cornershtr(Cube cube) -{ - return cube.coud * BINOM8ON4 * 6 + cphtr(cube); -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -static uint64_t -index_coud_sym16(Cube cube) -{ - return sd_coud_16.class[index_coud(cube)]; -} - -static uint64_t -index_drud_sym16(Cube cube) -{ - Trans t; - Cube c; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - - return index_eofbepos_sym16(c) * POW3TO7 + c.coud; -} - -static uint64_t -index_eofbepos_sym16(Cube cube) -{ - return sd_eofbepos_16.class[index_eofbepos(cube)]; -} - -static uint64_t -index_khuge(Cube cube) -{ - Trans t; - Cube c; - uint64_t a; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); - - return a * POW3TO7 + c.coud; -} - - -/* TODO: rename */ -static Cube -antindex_eofb(uint64_t ind) -{ - return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; -} - -static Cube -antindex_eofbepos(uint64_t ind) -{ - return admissible_ee_aux[ind]; -} - -/* TODO: rename */ -static Cube -antindex_coud(uint64_t ind) -{ - return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_corners(uint64_t ind) -{ - Cube c = {0}; - - c.coud = ind / FACTORIAL8; - c.cp = ind % FACTORIAL8; - - return c; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_cornershtr(uint64_t ind) -{ - Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); - - c.coud = ind / (BINOM8ON4 * 6); - - return c; -} - -/* TODO: admissible eos and cos */ -/* DONE: temporary fix, make it better */ -static Cube -antindex_drud(uint64_t ind) -{ - uint64_t epos, eofb; - Cube c; - - eofb = ind % POW2TO11; - epos = ind / (POW2TO11 * POW3TO7); - c = admissible_ee_aux[eofb + POW2TO11 * epos]; - - c.coud = (ind / POW2TO11) % POW3TO7; - c.corl = c.coud; - c.cofb = c.coud; - - return c; -} - -static Cube -antindex_coud_sym16(uint64_t ind) -{ - return sd_coud_16.rep[ind]; -} - -static Cube -antindex_eofbepos_sym16(uint64_t ind) -{ - return sd_eofbepos_16.rep[ind]; -} - -static Cube -antindex_drud_sym16(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/POW3TO7]; - c.coud = ind % POW3TO7; - c.cofb = c.coud; - c.corl = c.coud; - - return c; -} - -static Cube -antindex_khuge(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; - c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); - c.coud = ind % POW3TO7; - - return c; -} - - -/* Checkers ******************************************************************/ - -bool -check_centers(Cube cube) -{ - return cube.cpos == 0; -} - -bool -check_corners(Cube cube) -{ - return cube.cp == 0 && cube.coud == 0; -} - -bool -check_cornershtr(Cube cube) -{ - return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ -} - -bool -check_coud(Cube cube) -{ - return cube.coud == 0; -} - -bool -check_drud(Cube cube) -{ - return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; -} - -bool -check_eofb(Cube cube) -{ - return cube.eofb == 0; -} - -bool -check_eofbepos(Cube cube) -{ - return cube.eofb == 0 && cube.epose / 24 == 0; -} - -bool -check_epose(Cube cube) -{ - return cube.epose == 0; -} - -bool -check_ep(Cube cube) -{ - return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; -} - -bool -check_khuge(Cube cube) -{ - return check_drud(cube) && cube.epose % 24 == 0; -} - -bool -check_nothing(Cube cube) -{ - return is_admissible(cube); /*TODO: maybe change?*/ -} - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - - -/* Local functions implementation ********************************************/ - -/* TODO: this should be an anti index (maybe?) */ -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static Cube -admissible_eos_from_eofbepos(Cube cube) -{ - Edge e; - Cube ret; - CubeArray *arr = new_cubearray(cube, pf_all); - - memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); - memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); - - for (e = 0; e < 12; e++) { - if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || - (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) - arr->eorl[e] = 1 - arr->eorl[e]; - if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || - (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) - arr->eoud[e] = 1 - arr->eoud[e]; - } - - ret = arrays_to_cube(arr, pf_all); - free_cubearray(arr, pf_all); - - return ret; -} - -static bool -allowed_next(Move move, DfsData *dd) -{ - if (!possible_next[dd->last2][dd->last1][move]) - return false; - - if (commute[dd->last1][move]) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -} - -static 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; -} - -static 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 Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static int -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -/* -static int -cphtr_cp(int cp) -{ - int i, a[8]; - - index_to_perm(cp, 8, a); - - for (i = 0; i < 8; i++) - if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) - a[i] = 0; - else - a[i] = 1; - - swap(&a[1], &a[5]); - swap(&a[3], &a[7]); - - return subset_to_index(a, 8, 4); -} -*/ - -static void -dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - if (dfs_stop(c, s, opts, dd)) - return; - - if (dfs_check_solved(opts, dd)) - return; - - dfs_branch(c, s, opts, dd); - - if (opts->can_niss && !dd->niss) - dfs_niss(c, s, opts, dd); -} - -static void -dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; - - int i, maxnsol = opts->max_solutions; - - for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { - m = moves[i]; - if (allowed_next(m, dd)) { - dd->last2 = dd->last1; - dd->last1 = m; - append_move(dd->current_alg, m, dd->niss); - - dfs(apply_move(m, c), s, opts, dd); - - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } -} - -static bool -dfs_check_solved(SolveOptions *opts, DfsData *dd) -{ - if (dd->lb != 0) - return false; - - if (dd->current_alg->len == dd->d) { - append_alg(dd->sols, dd->current_alg); - - if (opts->feedback) - print_alg(dd->current_alg, false); - } - - return true; -} - -static void -dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move l1 = dd->last1, l2 = dd->last2; - CubeTarget ct; - - ct.cube = apply_move(inverse_move(l1), (Cube){0}); - ct.target = 1; - - if (dd->current_alg->len == 0 || s.estimate(ct)) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - - dfs(inverse_cube(c), s, opts, dd); - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = false; - } -} - -static bool -dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - CubeTarget ct = { - .cube = c, - .target = dd->d - dd->current_alg->len - }; - - if (dd->sols->len >= opts->max_solutions) - return true; - - dd->lb = s.estimate(ct); - if (opts->can_niss && !dd->niss) - dd->lb = MIN(1, dd->lb); - - if (dd->current_alg->len + dd->lb > dd->d) - return true; - - return false; -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent_pos(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 0) - ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; - - swap(&ep8[1], &ep8[4]); - swap(&ep8[3], &ep8[6]); - - return subset_to_index(ep8, 8, 4); -} - -static int -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(int epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -genptable_bfs(PruneData *pd, int d, Move *ms) -{ - uint64_t i; - - for (i = 0; i < pd->coord->max; i++) - if (ptableval_index(pd, i) == d) - genptable_branch(pd, i, d, ms); -} - -static void -genptable_branch(PruneData *pd, uint64_t ind, int d, Move *ms) -{ - int i, j; - Cube cc, c; - - - for (i = 0; i < pd->ntrans; i++) { - c = apply_trans(pd->trans[i], pd->coord->cube(ind)); - for (j = 0; ms[j] != NULLMOVE; j++) { - cc = apply_move(ms[j], c); - if (ptableval(pd, cc) > d+1) - ptable_update(pd, cc, d+1); - } - } -} - -static void -gensym(SymData *sd) -{ - uint64_t i, in, nreps = 0; - int j; - Cube c, d; - - if (sd->generated) - return; - - sd->class = malloc(sd->coord->max * sizeof(uint64_t)); - sd->rep = malloc(sd->coord->max * sizeof(Cube)); - sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); - - if (read_symdata_file(sd)) { - sd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); - - for (i = 0; i < sd->coord->max; i++) - sd->class[i] = sd->coord->max + 1; - - for (i = 0; i < sd->coord->max; i++) { - if (sd->class[i] == sd->coord->max + 1) { - c = sd->coord->cube(i); - sd->rep[nreps] = c; - for (j = 0; j < sd->ntrans; j++) { - d = apply_trans(sd->trans[j], c); - in = sd->coord->index(d); - - if (sd->class[in] == sd->coord->max + 1) { - sd->class[in] = nreps; - sd->transtorep[in] = - inverse_trans(sd->trans[j]); - } - } - nreps++; - } - } - - sd->sym_coord->max = nreps; - sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); - sd->generated = true; - - fprintf(stderr, "Found %lu classes\n", nreps); - - if (!write_symdata_file(sd)) - fprintf(stderr, "Error writing SymData file\n"); - - return; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -static void -moveset_to_list(Moveset ms, Estimator f, Move *r) -{ - CubeTarget ct = { .target = 1 }; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - ct.cube = apply_move(i, (Cube){0}); - if (f != NULL && f(ct)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static void -ptable_update(PruneData *pd, Cube cube, int n) -{ - uint64_t ind = pd->coord->index(cube); - uint8_t oldval2 = pd->ptable[ind/2]; - int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; - pd->n++; -} - -static int -ptableval_index(PruneData *pd, uint64_t ind) -{ - return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; -} - -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; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return r == ptablesize(pd); -} - -static bool -read_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(int); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); - Cube ret = {0}; - - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - ret = apply_alg_generic(inv, ret, f, true); - - ret = compose_filtered(c, ret, f); - - ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - - free_alg(inv); - return ret; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return written == ptablesize(pd); -} - -static bool -write_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(int); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - CubeArray *arr; - uint64_t ui, uj; - int i, j, k, auxarr[12]; - bool cij, p1, p2; - - for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { - k = (ui / POW2TO11) * 24; - c1 = admissible_ep((Cube){ .epose = k }, pf_e); - c1.eofb = ui % POW2TO11; - c1 = admissible_eos_from_eofbepos(c1); - admissible_ee_aux[ui] = c1; - } - - for (ui = 0; ui < FACTORIAL6; ui++) { - arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); - for (i = 0; i < 6; i++) { - what_center_at_aux[ui][i] = arr->cpos[i]; - where_is_center_aux[ui][arr->cpos[i]] = i; - } - free_cubearray(arr, pf_cpos); - } - - for (ui = 0; ui < FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.cp = ui}, pf_cp); - for (i = 0; i < 8; i++) { - what_corner_at_aux[ui][i] = arr->cp[i]; - where_is_corner_aux[ui][arr->cp[i]] = i; - } - free_cubearray(arr, pf_cp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.epose = ui}, pf_e); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 0) - where_is_edge_aux[0][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_e); - - arr = new_cubearray((Cube){.eposs = ui}, pf_s); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 1) - where_is_edge_aux[1][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_s); - - arr = new_cubearray((Cube){.eposm = ui}, pf_m); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 2) - where_is_edge_aux[2][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_m); - } - - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, auxarr); - what_orientation_last_corner_aux[ui] = auxarr[7]; - } - - for (ui = 0; ui < POW2TO11; ui++) { - int_to_sum_zero_array(ui, 2, 12, auxarr); - what_orientation_last_edge_aux[ui] = auxarr[11]; - } - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2) && i && j; - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[uf_mirror] = uf_mirror; - inverse_trans_aux[ur_mirror] = ur_mirror; - inverse_trans_aux[ul_mirror] = ul_mirror; - inverse_trans_aux[ub_mirror] = ub_mirror; - - inverse_trans_aux[df_mirror] = df_mirror; - inverse_trans_aux[dr_mirror] = dl_mirror; - inverse_trans_aux[dl_mirror] = dr_mirror; - inverse_trans_aux[db_mirror] = db_mirror; - - inverse_trans_aux[rf_mirror] = rf_mirror; - inverse_trans_aux[rd_mirror] = br_mirror; - inverse_trans_aux[rb_mirror] = lb_mirror; - inverse_trans_aux[ru_mirror] = fl_mirror; - - inverse_trans_aux[lf_mirror] = lf_mirror; - inverse_trans_aux[ld_mirror] = bl_mirror; - inverse_trans_aux[lb_mirror] = rb_mirror; - inverse_trans_aux[lu_mirror] = fr_mirror; - - inverse_trans_aux[fu_mirror] = fu_mirror; - inverse_trans_aux[fr_mirror] = lu_mirror; - inverse_trans_aux[fd_mirror] = bu_mirror; - inverse_trans_aux[fl_mirror] = ru_mirror; - - inverse_trans_aux[bu_mirror] = fd_mirror; - inverse_trans_aux[br_mirror] = rd_mirror; - inverse_trans_aux[bd_mirror] = bd_mirror; - inverse_trans_aux[bl_mirror] = ld_mirror; -} - -/* - * There is certainly a bette way to do this, but for now I just use - * a "graph coloring" algorithm to compute the left cosets, and I compose - * with every possible cp to get the right cosets (it is possible that I am - * mixing up left and right). - * - * For doing it better "Mathematically", we need 3 things: - * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other - * This is easy and it is done in the commented function cphtr_cp(). - * - Check that there is no ep/cp parity - * - Check that we are not in the "3c" case; this is the part I don't - * know how to do. - */ -static void -init_cphtr_cosets() -{ - unsigned int i; - int c = 0, d = 0; - - for (i = 0; i < FACTORIAL8; i++) { - cphtr_left_cosets[i] = -1; - cphtr_right_cosets[i] = -1; - } - - /* First we compute left cosets with a bfs */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_left_cosets[i] == -1) - init_cphtr_left_cosets_bfs(i, c++); - - /* Then we compute right cosets using compose() */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_right_cosets[i] == -1) - init_cphtr_right_cosets_color(i, d++); -} - -static void -init_cphtr_left_cosets_bfs(int i, int c) -{ - int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; - Move moves[6] = {U2, D2, R2, L2, F2, B2}; - - n = 1; - next[0] = i; - cphtr_left_cosets[i] = c; - - while (n != 0) { - for (j = 0, n2 = 0; j < n; j++) { - for (k = 0; k < 6; k++) { - jj = cp_mtable[moves[k]][next[j]]; - if (cphtr_left_cosets[jj] == -1) { - cphtr_left_cosets[jj] = c; - next2[n2++] = jj; - } - } - } - - for (j = 0; j < n2; j++) - next[j] = next2[j]; - n = n2; - } -} - -static void -init_cphtr_right_cosets_color(int i, int d) -{ - int cp; - unsigned int j; - - cphtr_right_rep[d] = i; - for (j = 0; j < FACTORIAL8; j++) { - if (cphtr_left_cosets[j] == 0) { - /* TODO: use antindexer, it's nicer */ - cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; - cphtr_right_cosets[cp] = d; - } - } -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - unsigned int ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray) { - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_symdata() -{ - int i; - - for (i = 0; i < n_all_symdata; i++) - gensym(all_sd[i]); -} - -static void -init_trans() { - Cube aux, cube, mirr, c[3]; - CubeArray epcp; - int i, eparr[12], eoarr[12], cparr[8], coarr[8]; - unsigned int ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); - - epose_source[i] = edge_slice(what_edge_at(cube, FR)); - eposs_source[i] = edge_slice(what_edge_at(cube, UR)); - eposm_source[i] = edge_slice(what_edge_at(cube, UF)); - eofb_source[i] = what_center_at(cube, F_center)/2; - eorl_source[i] = what_center_at(cube, R_center)/2; - eoud_source[i] = what_center_at(cube, U_center)/2; - coud_source[i] = what_center_at(cube, U_center)/2; - cofb_source[i] = what_center_at(cube, F_center)/2; - corl_source[i] = what_center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - if (m >= NROTATIONS) { - apply_permutation(ep_mirror, eparr, 12); - apply_permutation(cp_mirror, cparr, 8); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m >= NROTATIONS) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - aux = apply_trans(m, apply_move(mi, (Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move(inverse_move_aux[move], aux); - mirr = apply_trans(uf_mirror, cube); - if (is_solved(cube, false) || - is_solved(mirr, false)) - moves_ttable[m][mi] = move; - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - rotation_algs[uf] = new_alg(""); - rotation_algs[ur] = new_alg("y"); - rotation_algs[ub] = new_alg("y2"); - rotation_algs[ul] = new_alg("y3"); - - rotation_algs[df] = new_alg("z2"); - rotation_algs[dr] = new_alg("y z2"); - rotation_algs[db] = new_alg("x2"); - rotation_algs[dl] = new_alg("y3 z2"); - - rotation_algs[rf] = new_alg("z3"); - rotation_algs[rd] = new_alg("z3 y"); - rotation_algs[rb] = new_alg("z3 y2"); - rotation_algs[ru] = new_alg("z3 y3"); - - rotation_algs[lf] = new_alg("z"); - rotation_algs[ld] = new_alg("z y3"); - rotation_algs[lb] = new_alg("z y2"); - rotation_algs[lu] = new_alg("z y"); - - rotation_algs[fu] = new_alg("x y2"); - rotation_algs[fr] = new_alg("x y"); - rotation_algs[fd] = new_alg("x"); - rotation_algs[fl] = new_alg("x y3"); - - rotation_algs[bu] = new_alg("x3"); - rotation_algs[br] = new_alg("x3 y"); - rotation_algs[bd] = new_alg("x3 y2"); - rotation_algs[bl] = new_alg("x3 y3"); -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - return (Cube) { - .epose = epose_mtable[m][cube.epose], - .eposs = eposs_mtable[m][cube.eposs], - .eposm = eposm_mtable[m][cube.eposm], - .eofb = eofb_mtable[m][cube.eofb], - .eorl = eorl_mtable[m][cube.eorl], - .eoud = eoud_mtable[m][cube.eoud], - .coud = coud_mtable[m][cube.coud], - .cofb = cofb_mtable[m][cube.cofb], - .corl = corl_mtable[m][cube.corl], - .cp = cp_mtable[m][cube.cp], - .cpos = cpos_mtable[m][cube.cpos] - }; -} - - -Cube -apply_trans(Trans t, Cube cube) -{ - int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - return (Cube) { - .epose = epose_ttable[t][aux_epos[epose_source[t]]], - .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], - .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], - .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], - .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], - .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], - .coud = co_ttable[t][aux_co[coud_source[t]]], - .corl = co_ttable[t][aux_co[corl_source[t]]], - .cofb = co_ttable[t][aux_co[cofb_source[t]]], - .cp = cp_ttable[t][cube.cp], - .cpos = cpos_ttable[t][cube.cpos] - }; -} - -Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -/*TODO maybe move the next two */ -uint64_t -cphtr(Cube cube) -{ - return cphtr_right_cosets[cube.cp]; -} - -Cube -anti_cphtr(uint64_t ind) -{ - return (Cube) { .cp = cphtr_right_rep[ind] }; -} - -uint64_t -epos_dependent(Cube c) -{ - return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -void -genptable(PruneData *pd) -{ - Move ms[NMOVES]; - int d; - uint64_t j, oldn = 0; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - moveset_to_list(pd->moveset, NULL, ms); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->coord->max; j++) - ptable_update(pd, pd->coord->cube(j), 15); - - /*TODO: change, set to 0 for every solved state (might be more than 1)*/ - ptable_update(pd, (Cube){0}, 0); - pd->n = 1; - - for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { - genptable_bfs(pd, d, ms); - fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", - d, pd->n - oldn, pd->n, pd->coord->max); - oldn = pd->n; - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - int i; - - if (reorient) { - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(rotation_algs[i], cube),false)) - return true; - return false; - } else { - return equal(cube, (Cube){0}); - } -} - -bool -is_solved_block(Cube cube, Block block) -{ - int i; - - for (i = 0; i < 12; i++) - if (block.edge[i] && !is_solved_edge(cube, i)) - return false; - for (i = 0; i < 8; i++) - if (block.corner[i] && !is_solved_corner(cube, i)) - return false; - for (i = 0; i < 6; i++) - if (block.center[i] && !is_solved_center(cube, i)) - return false; - - return true; -} - -bool -is_solved_center(Cube cube, Center c) -{ - return what_center_at(cube, c) == c; -} - -bool -is_solved_corner(Cube cube, Corner c) -{ - return what_corner_at(cube, c) == c && - what_orientation_corner(cube.coud, c); -} - -bool -is_solved_edge(Cube cube, Edge e) -{ - return what_edge_at(cube, e) == e && - what_orientation_edge(cube.eofb, e); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b, x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ -/* - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -*/ - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[what_edge_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %d ", what_orientation_edge(cube.eofb, i)); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[what_corner_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %d ", what_orientation_corner(cube.coud, i)); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[what_center_at(cube, i)]); - printf("\n"); - -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -/* TODO: clean pre_trans or put it back */ -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - /*AlgListNode *node;*/ - AlgList *sols = new_alglist(); - /*Cube c = apply_trans(opts->pre_trans, cube);*/ - DfsData dd = { - .m = 0, - .niss = false, - .lb = -1, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && !step.ready(cube)) { - fprintf(stderr, "Cube not ready for solving step\n"); - return sols; - } - - moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = opts->min_moves; - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - if (opts->feedback) - fprintf(stderr, - "Found %d solutions, searching depth %d...\n", - sols->len, dd.d); - dfs(cube, step, opts, &dd); - } - -/* - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans(opts->pre_trans), node->alg); -*/ - - free_alg(dd.current_alg); - return sols; -} - -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; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - /* TODO: make it possible to print to stdout or to string */ - /* Maybe just return a string */ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - for (i = 0; i < 16; i++) - a[i] = 0; - - if (!pd->generated) - genptable(pd); - - for (i = 0; i < pd->coord->max; i++) - a[ptableval(pd, pd->coord->cube(i))]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -uint64_t -ptablesize(PruneData *pd) -{ - return (pd->coord->max + 1) / 2; -} - -int -ptableval(PruneData *pd, Cube cube) -{ - return ptableval_index(pd, pd->coord->index(cube)); -} - -Alg * -rotation_alg(Trans i) -{ - return rotation_algs[i % NROTATIONS]; -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} - -Center -what_center_at(Cube cube, Center c) -{ - return what_center_at_aux[cube.cpos][c]; -} - -Corner -what_corner_at(Cube cube, Corner c) -{ - return what_corner_at_aux[cube.cp][c]; -} - -Edge -what_edge_at(Cube cube, Edge e) -{ - Edge ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - - free_cubearray(arr, pf_ep); - return ret; -} - -int -what_orientation_corner(int co, Corner c) -{ - if (c < 7) - return (co / powint(3, c)) % 3; - else - return what_orientation_last_corner_aux[co]; -} - -int -what_orientation_edge(int eo, Edge e) -{ - if (e < 11) - return (eo & (1 << e)) ? 1 : 0; - else - return what_orientation_last_edge_aux[eo]; -} - -Center -where_is_center(Cube cube, Center c) -{ - return where_is_center_aux[cube.cpos][c]; -} - -Corner -where_is_corner(Cube cube, Corner c) -{ - return where_is_corner_aux[cube.cp][c]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_cphtr_cosets(); - init_trans_aux(); - init_trans(); - init_symdata(); -} - diff --git a/old/2021-07-15-almostbeforerefactor/alg.h b/old/2021-07-15-almostbeforerefactor/alg.h @@ -1,27 +0,0 @@ -#ifndef ALG_H -#define ALG_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> - -#include "macros.h" -#include "cubetypes.h" - -Move base_move(Move m); -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Move inverse_move(Move m); -bool moveset_HTM(Move m); -bool moveset_URF(Move m); -Alg * new_alg(char *str); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); -Alg * rotation_alg(Trans i); -void transform_alg(Trans t, Alg *alg); - -#endif - diff --git a/old/2021-07-15-almostbeforerefactor/cube.c b/old/2021-07-15-almostbeforerefactor/cube.c @@ -1,3391 +0,0 @@ -#include "cube.h" - -/* TODO: remove! */ -#include "steps.h" - -/* Local functions **********************************************************/ - -static Cube admissible_ep(Cube cube, PieceFilter f); -static Cube admissible_eos_from_eofbepos(Cube cube); -static bool allowed_next(Move move, DfsData *dd); -static void append_alg(AlgList *l, Alg *alg); -static void append_move(Alg *alg, Move m, bool inverse); -static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); -static void apply_permutation(int *perm, int *set, int n); -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static int array_ep_to_epos(int *ep, int *eps_solved); -static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); -static int binomial(int n, int k); -static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); -static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); -static int digit_array_to_int(int *a, int n, int b); -static int edge_slice(Edge e); /* E=0, S=1, M=2 */ -static int epos_dependent_pos(int pos1, int pos2); -static int epos_from_arrays(int *epos, int *ep); -static void epos_to_partial_ep(int epos, int *ep, int *ss); -static int factorial(int n); -static void free_alglistnode(AlgListNode *aln); -static void free_cubearray(CubeArray *arr, PieceFilter f); -static void genptable_bfs(PruneData *pd, int d, Move *ms); -static void genptable_branch(PruneData *pd, uint64_t i, int d, Move *m); -static void gensym(SymData *sd); -static void index_to_perm(int p, int n, int *r); -static void index_to_subset(int s, int n, int k, int *r); -static void init_auxtables(); -static void init_cphtr_cosets(); -static void init_cphtr_left_cosets_bfs(int i, int c); -static void init_cphtr_right_cosets_color(int i, int c); -static void init_environment(); -static void init_moves(); -static void init_moves_aux(); -static void init_strings(); -static void init_symdata(); -static void init_trans(); -static void init_trans_aux(); -static void int_to_digit_array(int a, int b, int n, int *r); -static void int_to_sum_zero_array(int x, int b, int n, int *a); -static int invert_digits(int a, int b, int n); -static bool is_perm(int *a, int n); -static bool is_subset(int *a, int n, int k); -static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -static void movelist_to_position(Move *movelist, int *position); -static void moveset_to_list(Moveset ms, Estimator f, Move *r); -static AlgList * new_alglist(); -static CubeArray * new_cubearray(Cube cube, PieceFilter f); -static int perm_sign(int *a, int n); -static int perm_to_index(int *a, int n); -static int powint(int a, int b); -static void ptable_update(PruneData *pd, Cube cube, int m); -static int ptableval_index(PruneData *pd, uint64_t ind); -static void realloc_alg(Alg *alg, int n); -static bool read_mtables_file(); -static bool read_ptable_file(PruneData *pd); -static bool read_symdata_file(SymData *sd); -static bool read_ttables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static int subset_to_index(int *a, int n, int k); -static void sum_arrays_mod(int *src, int *dst, int n, int m); -static void swap(int *a, int *b); -static bool write_mtables_file(); -static bool write_ptable_file(PruneData *pd); -static bool write_symdata_file(SymData *sd); -static bool write_ttables_file(); - - -/* All sorts of useful costants and tables **********************************/ - -static char * tabledir; - -static PieceFilter pf_all; -static PieceFilter pf_4val; -static PieceFilter pf_epcp; -static PieceFilter pf_cpos; -static PieceFilter pf_cp; -static PieceFilter pf_ep; -static PieceFilter pf_e; -static PieceFilter pf_s; -static PieceFilter pf_m; -static PieceFilter pf_eo; -static PieceFilter pf_co; - -static int epe_solved[4]; -static int eps_solved[4]; -static int epm_solved[4]; - -static char move_string[NMOVES][7]; -static char edge_string[12][7]; -static char corner_string[8][7]; -static char center_string[6][7]; - -static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; -static bool commute[NMOVES][NMOVES]; -static bool possible_next[NMOVES][NMOVES][NMOVES]; -static Move inverse_move_aux[NMOVES]; -static Trans inverse_trans_aux[NTRANS]; -static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; -static int cphtr_left_cosets[FACTORIAL8]; -static int cphtr_right_cosets[FACTORIAL8]; -static int cphtr_right_rep[BINOM8ON4*6]; -static Center what_center_at_aux[FACTORIAL6][6]; -static Corner what_corner_at_aux[FACTORIAL8][8]; -static int what_orientation_last_corner_aux[POW3TO7]; -static int what_orientation_last_edge_aux[POW2TO11]; -static Center where_is_center_aux[FACTORIAL6][6]; -static Corner where_is_corner_aux[FACTORIAL8][8]; -static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; - -static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eo_ttable[NTRANS][POW2TO11]; -static int cp_ttable[NTRANS][FACTORIAL8]; -static int co_ttable[NTRANS][POW3TO7]; -static int cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eofb_mtable[NMOVES][POW2TO11]; -static int eorl_mtable[NMOVES][POW2TO11]; -static int eoud_mtable[NMOVES][POW2TO11]; -static int cp_mtable[NMOVES][FACTORIAL8]; -static int coud_mtable[NMOVES][POW3TO7]; -static int cofb_mtable[NMOVES][POW3TO7]; -static int corl_mtable[NMOVES][POW3TO7]; -static int cpos_mtable[NMOVES][FACTORIAL6]; - -static uint64_t me[12]; - -static int edge_cycle[NMOVES][12]; -static int corner_cycle[NMOVES][8]; -static int center_cycle[NMOVES][6]; -static int eofb_flipped[NMOVES][12]; -static int eorl_flipped[NMOVES][12]; -static int eoud_flipped[NMOVES][12]; -static int coud_flipped[NMOVES][8]; -static int corl_flipped[NMOVES][8]; -static int cofb_flipped[NMOVES][8]; -static Alg * equiv_alg[NMOVES]; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; -static int ep_mirror[12]; -static int cp_mirror[8]; -static int cpos_mirror[6]; -static Alg * rotation_algs[NROTATIONS]; - - -/* Symmetry data for some coordinates ****************************************/ - -Trans -trans_group_trivial[1] = { uf }; - -Trans -trans_group_udfix[16] = { - uf, ur, ub, ul, - df, dr, db, dl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, -}; - -SymData -sd_coud_16 = { - .filename = "sd_coud_16", - .coord = &coord_coud, - .sym_coord = &coord_coud_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -SymData -sd_eofbepos_16 = { - .filename = "sd_eofbepos_16", - .coord = &coord_eofbepos, - .sym_coord = &coord_eofbepos_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static int n_all_symdata = 2; -static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; - -/* Coordinates and their implementation **************************************/ - -static uint64_t index_eofb(Cube cube); -static uint64_t index_eofbepos(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_cornershtr(Cube cube); -static uint64_t index_drud(Cube cube); -static uint64_t index_coud_sym16(Cube cube); -static uint64_t index_eofbepos_sym16(Cube cube); -static uint64_t index_drud_sym16(Cube cube); -static uint64_t index_khuge(Cube cube); - -static Cube antindex_eofb(uint64_t ind); -static Cube antindex_eofbepos(uint64_t ind); -static Cube antindex_coud(uint64_t ind); -static Cube antindex_corners(uint64_t ind); -static Cube antindex_cornershtr(uint64_t ind); -static Cube antindex_drud(uint64_t ind); -static Cube antindex_coud_sym16(uint64_t ind); -static Cube antindex_eofbepos_sym16(uint64_t ind); -static Cube antindex_drud_sym16(uint64_t ind); -static Cube antindex_khuge(uint64_t ind); - -Coordinate -coord_eofb = { - .index = index_eofb, - .cube = antindex_eofb, - .check = check_eofb, - .max = POW2TO11 -}; - -Coordinate -coord_eofbepos = { - .index = index_eofbepos, - .cube = antindex_eofbepos, - .check = check_eofbepos, - .max = POW2TO11 * BINOM12ON4 -}; - -Coordinate -coord_coud = { - .index = index_coud, - .cube = antindex_coud, - .check = check_coud, - .max = POW3TO7 -}; - -Coordinate -coord_corners = { - .index = index_corners, - .cube = antindex_corners, - .check = check_corners, - .max = POW3TO7 * FACTORIAL8 -}; - -Coordinate -coord_cornershtr = { - .index = index_cornershtr, - .cube = antindex_cornershtr, - .check = check_cornershtr, - .max = POW3TO7 * BINOM8ON4 * 6 -}; - -Coordinate -coord_drud = { - .index = index_drud, - .cube = antindex_drud, - .check = check_drud, - .max = POW2TO11 * POW3TO7 * BINOM12ON4 -}; - -Coordinate -coord_eofbepos_sym16 = { - .index = index_eofbepos_sym16, - .cube = antindex_eofbepos_sym16, - .check = check_eofbepos, -}; - -Coordinate -coord_coud_sym16 = { - .index = index_coud_sym16, - .cube = antindex_coud_sym16, - .check = check_coud, -}; - -Coordinate -coord_drud_sym16 = { - .index = index_drud_sym16, - .cube = antindex_drud_sym16, - .check = check_drud, - .max = POW3TO7 * 64430 -}; - -Coordinate -coord_khuge = { - .index = index_khuge, - .cube = antindex_khuge, - .check = check_khuge, - .max = POW3TO7 * FACTORIAL4 * 64430 -}; - - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_eofbepos(Cube cube) -{ - return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_cornershtr(Cube cube) -{ - return cube.coud * BINOM8ON4 * 6 + cphtr(cube); -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -static uint64_t -index_coud_sym16(Cube cube) -{ - return sd_coud_16.class[index_coud(cube)]; -} - -static uint64_t -index_drud_sym16(Cube cube) -{ - Trans t; - Cube c; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - - return index_eofbepos_sym16(c) * POW3TO7 + c.coud; -} - -static uint64_t -index_eofbepos_sym16(Cube cube) -{ - return sd_eofbepos_16.class[index_eofbepos(cube)]; -} - -static uint64_t -index_khuge(Cube cube) -{ - Trans t; - Cube c; - uint64_t a; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); - - return a * POW3TO7 + c.coud; -} - - -/* TODO: rename */ -static Cube -antindex_eofb(uint64_t ind) -{ - return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; -} - -static Cube -antindex_eofbepos(uint64_t ind) -{ - return admissible_ee_aux[ind]; -} - -/* TODO: rename */ -static Cube -antindex_coud(uint64_t ind) -{ - return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_corners(uint64_t ind) -{ - Cube c = {0}; - - c.coud = ind / FACTORIAL8; - c.cp = ind % FACTORIAL8; - - return c; -} - -/* TODO: admissible co for other orientations */ -static Cube -antindex_cornershtr(uint64_t ind) -{ - Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); - - c.coud = ind / (BINOM8ON4 * 6); - - return c; -} - -/* TODO: admissible eos and cos */ -/* DONE: temporary fix, make it better */ -static Cube -antindex_drud(uint64_t ind) -{ - uint64_t epos, eofb; - Cube c; - - eofb = ind % POW2TO11; - epos = ind / (POW2TO11 * POW3TO7); - c = admissible_ee_aux[eofb + POW2TO11 * epos]; - - c.coud = (ind / POW2TO11) % POW3TO7; - c.corl = c.coud; - c.cofb = c.coud; - - return c; -} - -static Cube -antindex_coud_sym16(uint64_t ind) -{ - return sd_coud_16.rep[ind]; -} - -static Cube -antindex_eofbepos_sym16(uint64_t ind) -{ - return sd_eofbepos_16.rep[ind]; -} - -static Cube -antindex_drud_sym16(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/POW3TO7]; - c.coud = ind % POW3TO7; - c.cofb = c.coud; - c.corl = c.coud; - - return c; -} - -static Cube -antindex_khuge(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; - c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); - c.coud = ind % POW3TO7; - - return c; -} - - -/* Checkers ******************************************************************/ - -bool -check_centers(Cube cube) -{ - return cube.cpos == 0; -} - -bool -check_corners(Cube cube) -{ - return cube.cp == 0 && cube.coud == 0; -} - -bool -check_cornershtr(Cube cube) -{ - return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ -} - -bool -check_coud(Cube cube) -{ - return cube.coud == 0; -} - -bool -check_drud(Cube cube) -{ - return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; -} - -bool -check_eofb(Cube cube) -{ - return cube.eofb == 0; -} - -bool -check_eofbepos(Cube cube) -{ - return cube.eofb == 0 && cube.epose / 24 == 0; -} - -bool -check_epose(Cube cube) -{ - return cube.epose == 0; -} - -bool -check_ep(Cube cube) -{ - return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; -} - -bool -check_khuge(Cube cube) -{ - return check_drud(cube) && cube.epose % 24 == 0; -} - -bool -check_nothing(Cube cube) -{ - return is_admissible(cube); /*TODO: maybe change?*/ -} - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - - -/* Local functions implementation ********************************************/ - -/* TODO: this should be an anti index (maybe?) */ -static Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -static Cube -admissible_eos_from_eofbepos(Cube cube) -{ - Edge e; - Cube ret; - CubeArray *arr = new_cubearray(cube, pf_all); - - memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); - memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); - - for (e = 0; e < 12; e++) { - if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || - (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) - arr->eorl[e] = 1 - arr->eorl[e]; - if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || - (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) - arr->eoud[e] = 1 - arr->eoud[e]; - } - - ret = arrays_to_cube(arr, pf_all); - free_cubearray(arr, pf_all); - - return ret; -} - -static bool -allowed_next(Move move, DfsData *dd) -{ - if (!possible_next[dd->last2][dd->last1][move]) - return false; - - if (commute[dd->last1][move]) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -} - -static 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; -} - -static 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 Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -static void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -static int -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -static int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -static Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -static void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -/* -static int -cphtr_cp(int cp) -{ - int i, a[8]; - - index_to_perm(cp, 8, a); - - for (i = 0; i < 8; i++) - if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) - a[i] = 0; - else - a[i] = 1; - - swap(&a[1], &a[5]); - swap(&a[3], &a[7]); - - return subset_to_index(a, 8, 4); -} -*/ - -static void -dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - if (dfs_stop(c, s, opts, dd)) - return; - - if (dfs_check_solved(opts, dd)) - return; - - dfs_branch(c, s, opts, dd); - - if (opts->can_niss && !dd->niss) - dfs_niss(c, s, opts, dd); -} - -static void -dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; - - int i, maxnsol = opts->max_solutions; - - for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { - m = moves[i]; - if (allowed_next(m, dd)) { - dd->last2 = dd->last1; - dd->last1 = m; - append_move(dd->current_alg, m, dd->niss); - - dfs(apply_move(m, c), s, opts, dd); - - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } -} - -static bool -dfs_check_solved(SolveOptions *opts, DfsData *dd) -{ - if (dd->lb != 0) - return false; - - if (dd->current_alg->len == dd->d) { - append_alg(dd->sols, dd->current_alg); - - if (opts->feedback) - print_alg(dd->current_alg, false); - } - - return true; -} - -static void -dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - Move l1 = dd->last1, l2 = dd->last2; - CubeTarget ct; - - ct.cube = apply_move(inverse_move(l1), (Cube){0}); - ct.target = 1; - - if (dd->current_alg->len == 0 || s.estimate(ct)) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - - dfs(inverse_cube(c), s, opts, dd); - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = false; - } -} - -static bool -dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) -{ - CubeTarget ct = { - .cube = c, - .target = dd->d - dd->current_alg->len - }; - - if (dd->sols->len >= opts->max_solutions) - return true; - - dd->lb = s.estimate(ct); - if (opts->can_niss && !dd->niss) - dd->lb = MIN(1, dd->lb); - - if (dd->current_alg->len + dd->lb > dd->d) - return true; - - return false; -} - -static int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -static int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -static int -epos_dependent_pos(int poss, int pose) -{ - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 0) - ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; - - swap(&ep8[1], &ep8[4]); - swap(&ep8[3], &ep8[6]); - - return subset_to_index(ep8, 8, 4); -} - -static int -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -static void -epos_to_partial_ep(int epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -static int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -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); -} - -void -free_alglistnode(AlgListNode *aln) -{ - free_alg(aln->alg); - free(aln); -} - -static void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -static void -genptable_bfs(PruneData *pd, int d, Move *ms) -{ - uint64_t i; - - for (i = 0; i < pd->coord->max; i++) - if (ptableval_index(pd, i) == d) - genptable_branch(pd, i, d, ms); -} - -static void -genptable_branch(PruneData *pd, uint64_t ind, int d, Move *ms) -{ - int i, j; - Cube cc, c; - - - for (i = 0; i < pd->ntrans; i++) { - c = apply_trans(pd->trans[i], pd->coord->cube(ind)); - for (j = 0; ms[j] != NULLMOVE; j++) { - cc = apply_move(ms[j], c); - if (ptableval(pd, cc) > d+1) - ptable_update(pd, cc, d+1); - } - } -} - -static void -gensym(SymData *sd) -{ - uint64_t i, in, nreps = 0; - int j; - Cube c, d; - - if (sd->generated) - return; - - sd->class = malloc(sd->coord->max * sizeof(uint64_t)); - sd->rep = malloc(sd->coord->max * sizeof(Cube)); - sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); - - if (read_symdata_file(sd)) { - sd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); - - for (i = 0; i < sd->coord->max; i++) - sd->class[i] = sd->coord->max + 1; - - for (i = 0; i < sd->coord->max; i++) { - if (sd->class[i] == sd->coord->max + 1) { - c = sd->coord->cube(i); - sd->rep[nreps] = c; - for (j = 0; j < sd->ntrans; j++) { - d = apply_trans(sd->trans[j], c); - in = sd->coord->index(d); - - if (sd->class[in] == sd->coord->max + 1) { - sd->class[in] = nreps; - sd->transtorep[in] = - inverse_trans(sd->trans[j]); - } - } - nreps++; - } - } - - sd->sym_coord->max = nreps; - sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); - sd->generated = true; - - fprintf(stderr, "Found %lu classes\n", nreps); - - if (!write_symdata_file(sd)) - fprintf(stderr, "Error writing SymData file\n"); - - return; -} - -static void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -static void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -static void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -static void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -static int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -static bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -static bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -static Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -static void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -static void -moveset_to_list(Moveset ms, Estimator f, Move *r) -{ - CubeTarget ct = { .target = 1 }; - int b[NMOVES]; - int na = 0, nb = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) { - if (ms(i)) { - ct.cube = apply_move(i, (Cube){0}); - if (f != NULL && f(ct)) - r[na++] = i; - else - b[nb++] = i; - } - } - - memcpy(r + na, b, nb * sizeof(Move)); - r[na+nb] = NULLMOVE; -} - -static AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -static CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - -static int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -static int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -static int -powint(int a, int b) -{ - if (b < 0) - return 0; - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -static void -ptable_update(PruneData *pd, Cube cube, int n) -{ - uint64_t ind = pd->coord->index(cube); - uint8_t oldval2 = pd->ptable[ind/2]; - int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; - pd->n++; -} - -static int -ptableval_index(PruneData *pd, uint64_t ind) -{ - return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; -} - -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; -} - -static bool -read_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -read_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return r == ptablesize(pd); -} - -static bool -read_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -read_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(int); - bool r = true; - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fread(co_ttable[m], b, me[7], f) == me[7]; - r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); - Cube ret = {0}; - - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - ret = apply_alg_generic(inv, ret, f, true); - - ret = compose_filtered(c, ret, f); - - ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - - free_alg(inv); - return ret; -} - -static int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -static void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -static void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -static bool -write_mtables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_ptable_file(PruneData *pd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return written == ptablesize(pd); -} - -static bool -write_symdata_file(SymData *sd) -{ - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -write_ttables_file() -{ - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(int); - Move m; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; - r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; - r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; - } - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -static void -init_auxtables() -{ - Cube c1, c2; - CubeArray *arr; - uint64_t ui, uj; - int i, j, k, auxarr[12]; - bool cij, p1, p2; - - for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { - k = (ui / POW2TO11) * 24; - c1 = admissible_ep((Cube){ .epose = k }, pf_e); - c1.eofb = ui % POW2TO11; - c1 = admissible_eos_from_eofbepos(c1); - admissible_ee_aux[ui] = c1; - } - - for (ui = 0; ui < FACTORIAL6; ui++) { - arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); - for (i = 0; i < 6; i++) { - what_center_at_aux[ui][i] = arr->cpos[i]; - where_is_center_aux[ui][arr->cpos[i]] = i; - } - free_cubearray(arr, pf_cpos); - } - - for (ui = 0; ui < FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.cp = ui}, pf_cp); - for (i = 0; i < 8; i++) { - what_corner_at_aux[ui][i] = arr->cp[i]; - where_is_corner_aux[ui][arr->cp[i]] = i; - } - free_cubearray(arr, pf_cp); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.epose = ui}, pf_e); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 0) - where_is_edge_aux[0][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_e); - - arr = new_cubearray((Cube){.eposs = ui}, pf_s); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 1) - where_is_edge_aux[1][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_s); - - arr = new_cubearray((Cube){.eposm = ui}, pf_m); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 2) - where_is_edge_aux[2][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_m); - } - - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, auxarr); - what_orientation_last_corner_aux[ui] = auxarr[7]; - } - - for (ui = 0; ui < POW2TO11; ui++) { - int_to_sum_zero_array(ui, 2, 12, auxarr); - what_orientation_last_edge_aux[ui] = auxarr[11]; - } - - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2) && i && j; - } - } - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - possible_next[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - for (i = 0; i < NMOVES; i++) - inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; - - /* Is there a more elegant way? */ - inverse_trans_aux[uf] = uf; - inverse_trans_aux[ur] = ul; - inverse_trans_aux[ul] = ur; - inverse_trans_aux[ub] = ub; - - inverse_trans_aux[df] = df; - inverse_trans_aux[dr] = dr; - inverse_trans_aux[dl] = dl; - inverse_trans_aux[db] = db; - - inverse_trans_aux[rf] = lf; - inverse_trans_aux[rd] = bl; - inverse_trans_aux[rb] = rb; - inverse_trans_aux[ru] = fr; - - inverse_trans_aux[lf] = rf; - inverse_trans_aux[ld] = br; - inverse_trans_aux[lb] = lb; - inverse_trans_aux[lu] = fl; - - inverse_trans_aux[fu] = fu; - inverse_trans_aux[fr] = ru; - inverse_trans_aux[fd] = bu; - inverse_trans_aux[fl] = lu; - - inverse_trans_aux[bu] = fd; - inverse_trans_aux[br] = ld; - inverse_trans_aux[bd] = bd; - inverse_trans_aux[bl] = rd; - - inverse_trans_aux[uf_mirror] = uf_mirror; - inverse_trans_aux[ur_mirror] = ur_mirror; - inverse_trans_aux[ul_mirror] = ul_mirror; - inverse_trans_aux[ub_mirror] = ub_mirror; - - inverse_trans_aux[df_mirror] = df_mirror; - inverse_trans_aux[dr_mirror] = dl_mirror; - inverse_trans_aux[dl_mirror] = dr_mirror; - inverse_trans_aux[db_mirror] = db_mirror; - - inverse_trans_aux[rf_mirror] = rf_mirror; - inverse_trans_aux[rd_mirror] = br_mirror; - inverse_trans_aux[rb_mirror] = lb_mirror; - inverse_trans_aux[ru_mirror] = fl_mirror; - - inverse_trans_aux[lf_mirror] = lf_mirror; - inverse_trans_aux[ld_mirror] = bl_mirror; - inverse_trans_aux[lb_mirror] = rb_mirror; - inverse_trans_aux[lu_mirror] = fr_mirror; - - inverse_trans_aux[fu_mirror] = fu_mirror; - inverse_trans_aux[fr_mirror] = lu_mirror; - inverse_trans_aux[fd_mirror] = bu_mirror; - inverse_trans_aux[fl_mirror] = ru_mirror; - - inverse_trans_aux[bu_mirror] = fd_mirror; - inverse_trans_aux[br_mirror] = rd_mirror; - inverse_trans_aux[bd_mirror] = bd_mirror; - inverse_trans_aux[bl_mirror] = ld_mirror; -} - -/* - * There is certainly a bette way to do this, but for now I just use - * a "graph coloring" algorithm to compute the left cosets, and I compose - * with every possible cp to get the right cosets (it is possible that I am - * mixing up left and right). - * - * For doing it better "Mathematically", we need 3 things: - * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other - * This is easy and it is done in the commented function cphtr_cp(). - * - Check that there is no ep/cp parity - * - Check that we are not in the "3c" case; this is the part I don't - * know how to do. - */ -static void -init_cphtr_cosets() -{ - unsigned int i; - int c = 0, d = 0; - - for (i = 0; i < FACTORIAL8; i++) { - cphtr_left_cosets[i] = -1; - cphtr_right_cosets[i] = -1; - } - - /* First we compute left cosets with a bfs */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_left_cosets[i] == -1) - init_cphtr_left_cosets_bfs(i, c++); - - /* Then we compute right cosets using compose() */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_right_cosets[i] == -1) - init_cphtr_right_cosets_color(i, d++); -} - -static void -init_cphtr_left_cosets_bfs(int i, int c) -{ - int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; - Move moves[6] = {U2, D2, R2, L2, F2, B2}; - - n = 1; - next[0] = i; - cphtr_left_cosets[i] = c; - - while (n != 0) { - for (j = 0, n2 = 0; j < n; j++) { - for (k = 0; k < 6; k++) { - jj = cp_mtable[moves[k]][next[j]]; - if (cphtr_left_cosets[jj] == -1) { - cphtr_left_cosets[jj] = c; - next2[n2++] = jj; - } - } - } - - for (j = 0; j < n2; j++) - next[j] = next2[j]; - n = n2; - } -} - -static void -init_cphtr_right_cosets_color(int i, int d) -{ - int cp; - unsigned int j; - - cphtr_right_rep[d] = i; - for (j = 0; j < FACTORIAL8; j++) { - if (cphtr_left_cosets[j] == 0) { - /* TODO: use antindexer, it's nicer */ - cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; - cphtr_right_cosets[cp] = d; - } - } -} - -static void -init_environment() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } -} - -static void -init_moves() { - Cube c; - CubeArray arrs; - int i; - unsigned int ui; - Move m; - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray) { - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); -} - -static void -init_moves_aux() -{ - /* Some standard PieceFilters */ - pf_all.epose = true; - pf_all.eposs = true; - pf_all.eposm = true; - pf_all.eofb = true; - pf_all.eorl = true; - pf_all.eoud = true; - pf_all.cp = true; - pf_all.cofb = true; - pf_all.corl = true; - pf_all.coud = true; - pf_all.cpos = true; - - pf_4val.epose = true; - pf_4val.eposs = true; - pf_4val.eposm = true; - pf_4val.eofb = true; - pf_4val.coud = true; - pf_4val.cp = true; - - pf_epcp.epose = true; - pf_epcp.eposs = true; - pf_epcp.eposm = true; - pf_epcp.cp = true; - - pf_cpos.cpos = true; - - pf_cp.cp = true; - - pf_ep.epose = true; - pf_ep.eposs = true; - pf_ep.eposm = true; - - pf_e.epose = true; - pf_s.eposs = true; - pf_m.eposm = true; - - pf_eo.eofb = true; - pf_eo.eorl = true; - pf_eo.eoud = true; - - pf_co.cofb = true; - pf_co.corl = true; - pf_co.coud = true; - - /* Used to convert to and from CubeArray */ - epe_solved[0] = FR; - epe_solved[1] = FL; - epe_solved[2] = BL; - epe_solved[3] = BR; - - eps_solved[0] = UL; - eps_solved[1] = UR; - eps_solved[2] = DL; - eps_solved[3] = DR; - - epm_solved[0] = UF; - epm_solved[1] = UB; - epm_solved[2] = DF; - epm_solved[3] = DB; - - /* Table sizes, used for reading and writing files */ - me[0] = FACTORIAL12/FACTORIAL8; - me[1] = FACTORIAL12/FACTORIAL8; - me[2] = FACTORIAL12/FACTORIAL8; - me[3] = POW2TO11; - me[4] = POW2TO11; - me[5] = POW2TO11; - me[6] = FACTORIAL8; - me[7] = POW3TO7; - me[8] = POW3TO7; - me[9] = POW3TO7; - me[10] = FACTORIAL6; - me[11] = NMOVES; - - /* Cycles *********************/ - edge_cycle[U][UF] = UR; - edge_cycle[U][UL] = UF; - edge_cycle[U][UB] = UL; - edge_cycle[U][UR] = UB; - edge_cycle[U][DF] = DF; - edge_cycle[U][DL] = DL; - edge_cycle[U][DB] = DB; - edge_cycle[U][DR] = DR; - edge_cycle[U][FR] = FR; - edge_cycle[U][FL] = FL; - edge_cycle[U][BL] = BL; - edge_cycle[U][BR] = BR; - - edge_cycle[x][UF] = DF; - edge_cycle[x][UL] = FL; - edge_cycle[x][UB] = UF; - edge_cycle[x][UR] = FR; - edge_cycle[x][DF] = DB; - edge_cycle[x][DL] = BL; - edge_cycle[x][DB] = UB; - edge_cycle[x][DR] = BR; - edge_cycle[x][FR] = DR; - edge_cycle[x][FL] = DL; - edge_cycle[x][BL] = UL; - edge_cycle[x][BR] = UR; - - edge_cycle[y][UF] = UR; - edge_cycle[y][UL] = UF; - edge_cycle[y][UB] = UL; - edge_cycle[y][UR] = UB; - edge_cycle[y][DF] = DR; - edge_cycle[y][DL] = DF; - edge_cycle[y][DB] = DL; - edge_cycle[y][DR] = DB; - edge_cycle[y][FR] = BR; - edge_cycle[y][FL] = FR; - edge_cycle[y][BL] = FL; - edge_cycle[y][BR] = BL; - - corner_cycle[U][UFR] = UBR; - corner_cycle[U][UFL] = UFR; - corner_cycle[U][UBL] = UFL; - corner_cycle[U][UBR] = UBL; - corner_cycle[U][DFR] = DFR; - corner_cycle[U][DFL] = DFL; - corner_cycle[U][DBL] = DBL; - corner_cycle[U][DBR] = DBR; - - corner_cycle[x][UFR] = DFR; - corner_cycle[x][UFL] = DFL; - corner_cycle[x][UBL] = UFL; - corner_cycle[x][UBR] = UFR; - corner_cycle[x][DFR] = DBR; - corner_cycle[x][DFL] = DBL; - corner_cycle[x][DBL] = UBL; - corner_cycle[x][DBR] = UBR; - - corner_cycle[y][UFR] = UBR; - corner_cycle[y][UFL] = UFR; - corner_cycle[y][UBL] = UFL; - corner_cycle[y][UBR] = UBL; - corner_cycle[y][DFR] = DBR; - corner_cycle[y][DFL] = DFR; - corner_cycle[y][DBL] = DFL; - corner_cycle[y][DBR] = DBL; - - center_cycle[U][U_center] = U_center; - center_cycle[U][D_center] = D_center; - center_cycle[U][R_center] = R_center; - center_cycle[U][L_center] = L_center; - center_cycle[U][F_center] = F_center; - center_cycle[U][B_center] = B_center; - - center_cycle[x][U_center] = F_center; - center_cycle[x][D_center] = B_center; - center_cycle[x][R_center] = R_center; - center_cycle[x][L_center] = L_center; - center_cycle[x][F_center] = D_center; - center_cycle[x][B_center] = U_center; - - center_cycle[y][U_center] = U_center; - center_cycle[y][D_center] = D_center; - center_cycle[y][R_center] = B_center; - center_cycle[y][L_center] = F_center; - center_cycle[y][F_center] = R_center; - center_cycle[y][B_center] = L_center; - - /* Flipped pieces *************/ - eofb_flipped[x][UF] = 1; - eofb_flipped[x][UB] = 1; - eofb_flipped[x][DF] = 1; - eofb_flipped[x][DB] = 1; - - eofb_flipped[y][FR] = 1; - eofb_flipped[y][FL] = 1; - eofb_flipped[y][BL] = 1; - eofb_flipped[y][BR] = 1; - - eorl_flipped[x][UF] = 1; - eorl_flipped[x][UL] = 1; - eorl_flipped[x][UB] = 1; - eorl_flipped[x][UR] = 1; - eorl_flipped[x][DF] = 1; - eorl_flipped[x][DL] = 1; - eorl_flipped[x][DB] = 1; - eorl_flipped[x][DR] = 1; - eorl_flipped[x][FR] = 1; - eorl_flipped[x][FL] = 1; - eorl_flipped[x][BL] = 1; - eorl_flipped[x][BR] = 1; - - eorl_flipped[y][FR] = 1; - eorl_flipped[y][FL] = 1; - eorl_flipped[y][BL] = 1; - eorl_flipped[y][BR] = 1; - - eoud_flipped[U][UF] = 1; - eoud_flipped[U][UL] = 1; - eoud_flipped[U][UB] = 1; - eoud_flipped[U][UR] = 1; - - eoud_flipped[x][UF] = 1; - eoud_flipped[x][UB] = 1; - eoud_flipped[x][DF] = 1; - eoud_flipped[x][DB] = 1; - - eoud_flipped[y][UF] = 1; - eoud_flipped[y][UL] = 1; - eoud_flipped[y][UB] = 1; - eoud_flipped[y][UR] = 1; - eoud_flipped[y][DF] = 1; - eoud_flipped[y][DL] = 1; - eoud_flipped[y][DB] = 1; - eoud_flipped[y][DR] = 1; - eoud_flipped[y][FR] = 1; - eoud_flipped[y][FL] = 1; - eoud_flipped[y][BL] = 1; - eoud_flipped[y][BR] = 1; - - coud_flipped[x][UFR] = 2; - coud_flipped[x][UFL] = 1; - coud_flipped[x][UBR] = 1; - coud_flipped[x][UBL] = 2; - coud_flipped[x][DFR] = 1; - coud_flipped[x][DFL] = 2; - coud_flipped[x][DBR] = 2; - coud_flipped[x][DBL] = 1; - - corl_flipped[U][UFR] = 1; - corl_flipped[U][UFL] = 2; - corl_flipped[U][UBL] = 1; - corl_flipped[U][UBR] = 2; - - corl_flipped[y][UFR] = 1; - corl_flipped[y][UFL] = 2; - corl_flipped[y][UBL] = 1; - corl_flipped[y][UBR] = 2; - corl_flipped[y][DFR] = 2; - corl_flipped[y][DFL] = 1; - corl_flipped[y][DBL] = 2; - corl_flipped[y][DBR] = 1; - - cofb_flipped[U][UFR] = 2; - cofb_flipped[U][UFL] = 1; - cofb_flipped[U][UBL] = 2; - cofb_flipped[U][UBR] = 1; - - cofb_flipped[x][UFR] = 1; - cofb_flipped[x][UFL] = 2; - cofb_flipped[x][UBL] = 1; - cofb_flipped[x][UBR] = 2; - cofb_flipped[x][DFR] = 2; - cofb_flipped[x][DFL] = 1; - cofb_flipped[x][DBL] = 2; - cofb_flipped[x][DBR] = 1; - - cofb_flipped[y][UFR] = 2; - cofb_flipped[y][UFL] = 1; - cofb_flipped[y][UBL] = 2; - cofb_flipped[y][UBR] = 1; - cofb_flipped[y][DFR] = 1; - cofb_flipped[y][DFL] = 2; - cofb_flipped[y][DBL] = 1; - cofb_flipped[y][DBR] = 2; - - /* Equivalent moves ***********/ - equiv_alg[NULLMOVE] = new_alg(""); - - equiv_alg[U] = new_alg(" U "); - equiv_alg[U2] = new_alg(" UU "); - equiv_alg[U3] = new_alg(" UUU "); - equiv_alg[D] = new_alg(" xx U xx "); - equiv_alg[D2] = new_alg(" xx UU xx "); - equiv_alg[D3] = new_alg(" xx UUU xx "); - equiv_alg[R] = new_alg(" yx U xxxyyy "); - equiv_alg[R2] = new_alg(" yx UU xxxyyy "); - equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); - equiv_alg[L] = new_alg(" yyyx U xxxy "); - equiv_alg[L2] = new_alg(" yyyx UU xxxy "); - equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); - equiv_alg[F] = new_alg(" x U xxx "); - equiv_alg[F2] = new_alg(" x UU xxx "); - equiv_alg[F3] = new_alg(" x UUU xxx "); - equiv_alg[B] = new_alg(" xxx U x "); - equiv_alg[B2] = new_alg(" xxx UU x "); - equiv_alg[B3] = new_alg(" xxx UUU x "); - - equiv_alg[Uw] = new_alg(" xx U xx y "); - equiv_alg[Uw2] = new_alg(" xx UU xx yy "); - equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); - equiv_alg[Dw] = new_alg(" U yyy "); - equiv_alg[Dw2] = new_alg(" UU yy "); - equiv_alg[Dw3] = new_alg(" UUU y "); - equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); - equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); - equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); - equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); - equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); - equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); - equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); - equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); - equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); - equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); - equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); - equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); - - equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); - equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); - equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); - equiv_alg[S] = new_alg(" x UUU xx U yyyx "); - equiv_alg[S2] = new_alg(" x UU xx UU yyx "); - equiv_alg[S3] = new_alg(" x U xx UUU yx "); - equiv_alg[E] = new_alg(" U xx UUU xxyyy "); - equiv_alg[E2] = new_alg(" UU xx UU xxyy "); - equiv_alg[E3] = new_alg(" UUU xx U xxy "); - - equiv_alg[x] = new_alg(" x "); - equiv_alg[x2] = new_alg(" xx "); - equiv_alg[x3] = new_alg(" xxx "); - equiv_alg[y] = new_alg(" y "); - equiv_alg[y2] = new_alg(" yy "); - equiv_alg[y3] = new_alg(" yyy "); - equiv_alg[z] = new_alg(" yyy x y "); - equiv_alg[z2] = new_alg(" yy xx "); - equiv_alg[z3] = new_alg(" y x yyy "); -} - -static void -init_strings() -{ - strcpy(move_string [NULLMOVE], "-" ); - strcpy(move_string [U], "U" ); - strcpy(move_string [U2], "U2" ); - strcpy(move_string [U3], "U\'" ); - strcpy(move_string [D], "D" ); - strcpy(move_string [D2], "D2" ); - strcpy(move_string [D3], "D\'" ); - strcpy(move_string [R], "R" ); - strcpy(move_string [R2], "R2" ); - strcpy(move_string [R3], "R\'" ); - strcpy(move_string [L], "L" ); - strcpy(move_string [L2], "L2" ); - strcpy(move_string [L3], "L\'" ); - strcpy(move_string [F], "F" ); - strcpy(move_string [F2], "F2" ); - strcpy(move_string [F3], "F\'" ); - strcpy(move_string [B], "B" ); - strcpy(move_string [B2], "B2" ); - strcpy(move_string [B3], "B\'" ); - strcpy(move_string [Uw], "Uw" ); - strcpy(move_string [Uw2], "Uw2" ); - strcpy(move_string [Uw3], "Uw\'" ); - strcpy(move_string [Dw], "Dw" ); - strcpy(move_string [Dw2], "Dw2" ); - strcpy(move_string [Dw3], "Dw\'" ); - strcpy(move_string [Rw], "Rw" ); - strcpy(move_string [Rw2], "Rw2" ); - strcpy(move_string [Rw3], "Rw\'" ); - strcpy(move_string [Lw], "Lw" ); - strcpy(move_string [Lw2], "Lw2" ); - strcpy(move_string [Lw3], "Lw\'" ); - strcpy(move_string [Fw], "Fw" ); - strcpy(move_string [Fw2], "Fw2" ); - strcpy(move_string [Fw3], "Fw\'" ); - strcpy(move_string [Bw], "Bw" ); - strcpy(move_string [Bw2], "Bw2" ); - strcpy(move_string [Bw3], "Bw\'" ); - strcpy(move_string [M], "M" ); - strcpy(move_string [M2], "M2" ); - strcpy(move_string [M3], "M\'" ); - strcpy(move_string [S], "S" ); - strcpy(move_string [S2], "S2" ); - strcpy(move_string [S3], "S\'" ); - strcpy(move_string [E], "E" ); - strcpy(move_string [E2], "E2" ); - strcpy(move_string [E3], "E\'" ); - strcpy(move_string [x], "x" ); - strcpy(move_string [x2], "x2" ); - strcpy(move_string [x3], "x\'" ); - strcpy(move_string [y], "y" ); - strcpy(move_string [y2], "y2" ); - strcpy(move_string [y3], "y\'" ); - strcpy(move_string [z], "z" ); - strcpy(move_string [z2], "z2" ); - strcpy(move_string [z3], "z\'" ); - - strcpy(edge_string [UF], "UF" ); - strcpy(edge_string [UL], "UL" ); - strcpy(edge_string [UB], "UB" ); - strcpy(edge_string [UR], "UR" ); - strcpy(edge_string [DF], "DF" ); - strcpy(edge_string [DL], "DL" ); - strcpy(edge_string [DB], "DB" ); - strcpy(edge_string [DR], "DR" ); - strcpy(edge_string [FR], "FR" ); - strcpy(edge_string [FL], "FL" ); - strcpy(edge_string [BL], "BL" ); - strcpy(edge_string [BR], "BR" ); - - strcpy(corner_string [UFR], "UFR" ); - strcpy(corner_string [UFL], "UFL" ); - strcpy(corner_string [UBL], "UBL" ); - strcpy(corner_string [UBR], "UBR" ); - strcpy(corner_string [DFR], "DFR" ); - strcpy(corner_string [DFL], "DFL" ); - strcpy(corner_string [DBL], "DBL" ); - strcpy(corner_string [DBR], "DBR" ); - - strcpy(center_string [U_center], "U" ); - strcpy(center_string [D_center], "D" ); - strcpy(center_string [R_center], "R" ); - strcpy(center_string [L_center], "L" ); - strcpy(center_string [F_center], "F" ); - strcpy(center_string [B_center], "B" ); -} - -static void -init_symdata() -{ - int i; - - for (i = 0; i < n_all_symdata; i++) - gensym(all_sd[i]); -} - -static void -init_trans() { - Cube aux, cube, mirr, c[3]; - CubeArray epcp; - int i, eparr[12], eoarr[12], cparr[8], coarr[8]; - unsigned int ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); - - epose_source[i] = edge_slice(what_edge_at(cube, FR)); - eposs_source[i] = edge_slice(what_edge_at(cube, UR)); - eposm_source[i] = edge_slice(what_edge_at(cube, UF)); - eofb_source[i] = what_center_at(cube, F_center)/2; - eorl_source[i] = what_center_at(cube, R_center)/2; - eoud_source[i] = what_center_at(cube, U_center)/2; - coud_source[i] = what_center_at(cube, U_center)/2; - cofb_source[i] = what_center_at(cube, F_center)/2; - corl_source[i] = what_center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - if (m >= NROTATIONS) { - apply_permutation(ep_mirror, eparr, 12); - apply_permutation(cp_mirror, cparr, 8); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m >= NROTATIONS) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - aux = apply_trans(m, apply_move(mi, (Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move(inverse_move_aux[move], aux); - mirr = apply_trans(uf_mirror, cube); - if (is_solved(cube, false) || - is_solved(mirr, false)) - moves_ttable[m][mi] = move; - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static void -init_trans_aux() -{ - ep_mirror[UF] = UF; - ep_mirror[UL] = UR; - ep_mirror[UB] = UB; - ep_mirror[UR] = UL; - ep_mirror[DF] = DF; - ep_mirror[DL] = DR; - ep_mirror[DB] = DB; - ep_mirror[DR] = DL; - ep_mirror[FR] = FL; - ep_mirror[FL] = FR; - ep_mirror[BR] = BL; - ep_mirror[BL] = BR; - - cp_mirror[UFR] = UFL; - cp_mirror[UFL] = UFR; - cp_mirror[UBL] = UBR; - cp_mirror[UBR] = UBL; - cp_mirror[DFR] = DFL; - cp_mirror[DFL] = DFR; - cp_mirror[DBL] = DBR; - cp_mirror[DBR] = DBL; - - cpos_mirror[U_center] = U_center; - cpos_mirror[D_center] = D_center; - cpos_mirror[R_center] = L_center; - cpos_mirror[L_center] = R_center; - cpos_mirror[F_center] = F_center; - cpos_mirror[B_center] = B_center; - - /* Is there a more elegant way? */ - rotation_algs[uf] = new_alg(""); - rotation_algs[ur] = new_alg("y"); - rotation_algs[ub] = new_alg("y2"); - rotation_algs[ul] = new_alg("y3"); - - rotation_algs[df] = new_alg("z2"); - rotation_algs[dr] = new_alg("y z2"); - rotation_algs[db] = new_alg("x2"); - rotation_algs[dl] = new_alg("y3 z2"); - - rotation_algs[rf] = new_alg("z3"); - rotation_algs[rd] = new_alg("z3 y"); - rotation_algs[rb] = new_alg("z3 y2"); - rotation_algs[ru] = new_alg("z3 y3"); - - rotation_algs[lf] = new_alg("z"); - rotation_algs[ld] = new_alg("z y3"); - rotation_algs[lb] = new_alg("z y2"); - rotation_algs[lu] = new_alg("z y"); - - rotation_algs[fu] = new_alg("x y2"); - rotation_algs[fr] = new_alg("x y"); - rotation_algs[fd] = new_alg("x"); - rotation_algs[fl] = new_alg("x y3"); - - rotation_algs[bu] = new_alg("x3"); - rotation_algs[br] = new_alg("x3 y"); - rotation_algs[bd] = new_alg("x3 y2"); - rotation_algs[bl] = new_alg("x3 y3"); -} - - -/* Public functions implementation *******************************************/ - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - return (Cube) { - .epose = epose_mtable[m][cube.epose], - .eposs = eposs_mtable[m][cube.eposs], - .eposm = eposm_mtable[m][cube.eposm], - .eofb = eofb_mtable[m][cube.eofb], - .eorl = eorl_mtable[m][cube.eorl], - .eoud = eoud_mtable[m][cube.eoud], - .coud = coud_mtable[m][cube.coud], - .cofb = cofb_mtable[m][cube.cofb], - .corl = corl_mtable[m][cube.corl], - .cp = cp_mtable[m][cube.cp], - .cpos = cpos_mtable[m][cube.cpos] - }; -} - - -Cube -apply_trans(Trans t, Cube cube) -{ - int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - return (Cube) { - .epose = epose_ttable[t][aux_epos[epose_source[t]]], - .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], - .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], - .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], - .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], - .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], - .coud = co_ttable[t][aux_co[coud_source[t]]], - .corl = co_ttable[t][aux_co[corl_source[t]]], - .cofb = co_ttable[t][aux_co[cofb_source[t]]], - .cp = cp_ttable[t][cube.cp], - .cpos = cpos_ttable[t][cube.cpos] - }; -} - -Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -/*TODO maybe move the next two */ -uint64_t -cphtr(Cube cube) -{ - return cphtr_right_cosets[cube.cp]; -} - -Cube -anti_cphtr(uint64_t ind) -{ - return (Cube) { .cp = cphtr_right_rep[ind] }; -} - -uint64_t -epos_dependent(Cube c) -{ - return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -void -genptable(PruneData *pd) -{ - Move ms[NMOVES]; - int d; - uint64_t j, oldn = 0; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ - pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - moveset_to_list(pd->moveset, NULL, ms); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->coord->max; j++) - ptable_update(pd, pd->coord->cube(j), 15); - - /*TODO: change, set to 0 for every solved state (might be more than 1)*/ - ptable_update(pd, (Cube){0}, 0); - pd->n = 1; - - for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { - genptable_bfs(pd, d, ms); - fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", - d, pd->n - oldn, pd->n, pd->coord->max); - oldn = pd->n; - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); - - pd->generated = true; -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -Move -inverse_move(Move m) -{ - return inverse_move_aux[m]; -} - -Trans -inverse_trans(Trans t) -{ - return inverse_trans_aux[t]; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube, bool reorient) -{ - int i; - - if (reorient) { - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(rotation_algs[i], cube),false)) - return true; - return false; - } else { - return equal(cube, (Cube){0}); - } -} - -bool -is_solved_block(Cube cube, Block block) -{ - int i; - - for (i = 0; i < 12; i++) - if (block.edge[i] && !is_solved_edge(cube, i)) - return false; - for (i = 0; i < 8; i++) - if (block.corner[i] && !is_solved_corner(cube, i)) - return false; - for (i = 0; i < 6; i++) - if (block.center[i] && !is_solved_center(cube, i)) - return false; - - return true; -} - -bool -is_solved_center(Cube cube, Center c) -{ - return what_center_at(cube, c) == c; -} - -bool -is_solved_corner(Cube cube, Corner c) -{ - return what_corner_at(cube, c) == c && - what_orientation_corner(cube.coud, c); -} - -bool -is_solved_edge(Cube cube, Edge e) -{ - return what_edge_at(cube, e) == e && - what_orientation_edge(cube.eofb, e); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b, x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ -/* - CubeArray *arr = new_cubearray(cube, pf_all); - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[arr->ep[i]]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %c ", arr->eofb[i] + '0'); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[arr->cp[i]]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %c ", arr->coud[i] + '0'); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[arr->cpos[i]]); - printf("\n"); - - free_cubearray(arr, pf_all); -*/ - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[what_edge_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %d ", what_orientation_edge(cube.eofb, i)); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[what_corner_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %d ", what_orientation_corner(cube.coud, i)); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[what_center_at(cube, i)]); - printf("\n"); - -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -/* TODO: clean pre_trans or put it back */ -AlgList * -solve(Cube cube, Step step, SolveOptions *opts) -{ - /*AlgListNode *node;*/ - AlgList *sols = new_alglist(); - /*Cube c = apply_trans(opts->pre_trans, cube);*/ - DfsData dd = { - .m = 0, - .niss = false, - .lb = -1, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step.ready != NULL && !step.ready(cube)) { - fprintf(stderr, "Cube not ready for solving step\n"); - return sols; - } - - moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = opts->min_moves; - dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); - dd.d++) { - if (opts->feedback) - fprintf(stderr, - "Found %d solutions, searching depth %d...\n", - sols->len, dd.d); - dfs(cube, step, opts, &dd); - } - -/* - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans(opts->pre_trans), node->alg); -*/ - - free_alg(dd.current_alg); - return sols; -} - -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; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - for (j = 0; j < NMOVES; j++) { - if (str[i] == move_string[j][0]) { - m = j; - 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') { - m += 2; - i++; - } - append_move(alg, m, niss); - break; - } - } - } - - return alg; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - /* TODO: make it possible to print to stdout or to string */ - /* Maybe just return a string */ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - for (i = 0; i < 16; i++) - a[i] = 0; - - if (!pd->generated) - genptable(pd); - - for (i = 0; i < pd->coord->max; i++) - a[ptableval(pd, pd->coord->cube(i))]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -uint64_t -ptablesize(PruneData *pd) -{ - return (pd->coord->max + 1) / 2; -} - -int -ptableval(PruneData *pd, Cube cube) -{ - return ptableval_index(pd, pd->coord->index(cube)); -} - -Alg * -rotation_alg(Trans i) -{ - return rotation_algs[i % NROTATIONS]; -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} - -Center -what_center_at(Cube cube, Center c) -{ - return what_center_at_aux[cube.cpos][c]; -} - -Corner -what_corner_at(Cube cube, Corner c) -{ - return what_corner_at_aux[cube.cp][c]; -} - -Edge -what_edge_at(Cube cube, Edge e) -{ - Edge ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - - free_cubearray(arr, pf_ep); - return ret; -} - -int -what_orientation_corner(int co, Corner c) -{ - if (c < 7) - return (co / powint(3, c)) % 3; - else - return what_orientation_last_corner_aux[co]; -} - -int -what_orientation_edge(int eo, Edge e) -{ - if (e < 11) - return (eo & (1 << e)) ? 1 : 0; - else - return what_orientation_last_edge_aux[eo]; -} - -Center -where_is_center(Cube cube, Center c) -{ - return where_is_center_aux[cube.cpos][c]; -} - -Corner -where_is_corner(Cube cube, Corner c) -{ - return where_is_corner_aux[cube.cp][c]; -} - - -void -init() -{ - /* Order is important! */ - init_environment(); - init_strings(); - init_moves_aux(); - init_moves(); - init_auxtables(); - init_cphtr_cosets(); - init_trans_aux(); - init_trans(); - init_symdata(); -} - diff --git a/old/2021-07-15-almostbeforerefactor/cube.h b/old/2021-07-15-almostbeforerefactor/cube.h @@ -1,79 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <sys/stat.h> - -#include "macros.h" -#include "cubetypes.h" - -extern Coordinate coord_eofb; -extern Coordinate coord_eofbepos; -extern Coordinate coord_coud; -extern Coordinate coord_corners; -extern Coordinate coord_cornershtr; -extern Coordinate coord_drud; -extern Coordinate coord_coud_sym16; -extern Coordinate coord_eofbepos_sym16; -extern Coordinate coord_drud_sym16; -extern Coordinate coord_khuge; - -extern Trans trans_group_udfix[16]; -extern Trans trans_group_trivial[1]; - -Cube apply_alg(Alg *alg, Cube cube); -Cube apply_move(Move m, Cube cube); -Cube apply_trans(Trans t, Cube cube); -bool block_solved(Cube cube, Block); -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ -Cube anti_cphtr(uint64_t ind); /*TODO also this */ -uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -Move inverse_move(Move m); -Trans inverse_trans(Trans t); -bool is_admissible(Cube cube); -bool is_solved(Cube cube, bool reorient); -bool is_solved_center(Cube cube, Center c); -bool is_solved_corner(Cube cube, Corner c); -bool is_solved_edge(Cube cube, Edge e); -void print_cube(Cube cube); -Cube random_cube(); -AlgList * solve(Cube cube, Step step, SolveOptions *opts); -Center what_center_at(Cube cube, Center c); -Corner what_corner_at(Cube cube, Corner c); -Edge what_edge_at(Cube cube, Edge e); -int what_orientation_corner(int co, Corner c); -int what_orientation_edge(int eo, Edge e); -Center where_is_center(Cube cube, Center c); -Corner where_is_corner(Cube cube, Corner c); -Edge where_is_edge(Cube cube, Edge e); - -bool check_centers(Cube cube); -bool check_corners(Cube cube); -bool check_cornershtr(Cube cube); -bool check_coud(Cube cube); -bool check_drud(Cube cube); -bool check_eofb(Cube cube); -bool check_eofbepos(Cube cube); -bool check_epose(Cube cube); -bool check_ep(Cube cube); -bool check_khuge(Cube cube); -bool check_nothing(Cube cube); - -void genptable(PruneData *pd); -void print_ptable(PruneData *pd); -uint64_t ptablesize(PruneData *pd); -int ptableval(PruneData *pd, Cube cube); - -void init(); - -#endif - diff --git a/old/2021-07-15-almostbeforerefactor/cubetypes.h b/old/2021-07-15-almostbeforerefactor/cubetypes.h @@ -1,252 +0,0 @@ -#ifndef CUBETYPES_H -#define CUBETYPES_H - -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct block Block; -typedef struct coordinate Coordinate; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct cubetarget CubeTarget; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; -typedef struct symdata SymData; - -typedef Cube (*AntiIndexer) (uint64_t); -typedef bool (*Checker) (Cube); -typedef int (*Estimator) (CubeTarget); -typedef uint64_t (*Indexer) (Cube); -typedef bool (*Moveset) (Move); - - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, - rf_mirror, rd_mirror, rb_mirror, ru_mirror, - lf_mirror, ld_mirror, lb_mirror, lu_mirror, - fu_mirror, fr_mirror, fd_mirror, fl_mirror, - bu_mirror, br_mirror, bd_mirror, bl_mirror, -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - Move * move; - bool * inv; - int len; - int allocated; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -coordinate -{ - Indexer index; - AntiIndexer cube; - Checker check; - uint64_t max; -}; - -struct -cube -{ - int epose; - int eposs; - int eposm; - int eofb; - int eorl; - int eoud; - int cp; - int coud; - int cofb; - int corl; - int cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -cubetarget -{ - Cube cube; - int target; -}; - -struct -dfsdata -{ - int d; - int m; - int lb; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[NMOVES]; - int move_position[NMOVES]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - bool generated; - uint64_t n; - Coordinate * coord; - Moveset moveset; - int ntrans; - Trans * trans; -}; - -struct -solveoptions -{ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; -}; - -struct -step -{ - Estimator estimate; - Checker ready; - Moveset moveset; -}; - -struct -symdata -{ - char * filename; - bool generated; - Coordinate * coord; - Coordinate * sym_coord; - int ntrans; - Trans * trans; - uint64_t * class; - Cube * rep; - Trans * transtorep; -}; - -#endif diff --git a/old/2021-07-15-almostbeforerefactor/macros.h b/old/2021-07-15-almostbeforerefactor/macros.h @@ -1,23 +0,0 @@ -#ifndef MACROS_H -#define MACROS_H - -#define POW2TO6 64ULL -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL7 5040ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -#define NMOVES (z3+1) -#define NTRANS 48 -#define NROTATIONS 24 - -#endif diff --git a/old/2021-07-15-almostbeforerefactor/main.c b/old/2021-07-15-almostbeforerefactor/main.c @@ -1,60 +0,0 @@ -#include <stdio.h> -#include "cube.h" -#include "steps.h" - -int main() { - Alg *algo; - AlgList *sols; - Cube cube; - SolveOptions opts; - char line[1000]; - int i, ns = 1; -/* Move m;*/ -/* int nrand = 10000, sum1, sum2;*/ - - Step *stps[20] = {&optimal_HTM}; - char sss[30][30] = {"Optimal solve"}; - - opts = (SolveOptions) { - .min_moves = 0, - .max_moves = 20, - .optimal_only = true, - .max_solutions = 1, - .can_niss = false, - .feedback = true, - }; - - init(); - -/* - srand(time(NULL)); - sum1 = 0; - sum2 = 0; - for (i = 0; i < nrand; i++) { - cube = random_cube(); - sum1 += drud_HTM.estimate((CubeTarget){.cube = cube, .target = 20}); - sum2 += optimal_HTM.estimate((CubeTarget){.cube = cube, .target = 20}); - } - printf("Average drud pruning: %lf\n", ((double)sum1) / ((double) nrand)); - printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); -*/ - - - printf("Welcome to nissy 2.0! Insert a scramble:\n"); - - if (fgets(line, 1000, stdin) != NULL) { - algo = new_alg(line); - cube = apply_alg(algo, (Cube){0}); - - for (i = 0; i < ns; i++) { - sols = solve(cube, *stps[i], &opts); - printf("%s: %d solutions found:\n", sss[i], sols->len); - print_alglist(sols, true); - free_alglist(sols); - } - free_alg(algo); - } - - return 0; -} - diff --git a/old/2021-07-15-almostbeforerefactor/nissy b/old/2021-07-15-almostbeforerefactor/nissy Binary files differ. diff --git a/old/2021-07-15-almostbeforerefactor/steps.c b/old/2021-07-15-almostbeforerefactor/steps.c @@ -1,284 +0,0 @@ -#include "steps.h" - -/* Standard checkers (return lower bound) ************************************/ - -static int estimate_eofb_HTM(CubeTarget ct); -static int estimate_coud_HTM(CubeTarget ct); -static int estimate_coud_URF(CubeTarget ct); -static int estimate_corners_HTM(CubeTarget ct); -static int estimate_cornershtr_HTM(CubeTarget ct); -static int estimate_corners_URF(CubeTarget ct); -static int estimate_cornershtr_URF(CubeTarget ct); -static int estimate_drud_HTM(CubeTarget ct); -static int estimate_optimal_HTM(CubeTarget ct); - -/* Steps *********************************************************************/ - -Step -eofb_HTM = { - .estimate = estimate_eofb_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_HTM = { - .estimate = estimate_coud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -coud_URF = { - .estimate = estimate_coud_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_HTM = { - .estimate = estimate_corners_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_HTM = { - .estimate = estimate_cornershtr_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -cornershtr_URF = { - .estimate = estimate_cornershtr_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -corners_URF = { - .estimate = estimate_corners_URF, - .ready = check_nothing, - .moveset = moveset_URF -}; - -Step -drud_HTM = { - .estimate = estimate_drud_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - -Step -optimal_HTM = { - .estimate = estimate_optimal_HTM, - .ready = check_centers, - .moveset = moveset_HTM -}; - - -/* Pruning tables ************************************************************/ - -PruneData -pd_eofb_HTM = { - .filename = "ptable_eofb_HTM", - .coord = &coord_eofb, - .moveset = moveset_HTM, - .ntrans = 1, - .trans = trans_group_trivial -}; - -PruneData -pd_coud_HTM = { - .filename = "ptable_coud_HTM", - .coord = &coord_coud, - .moveset = moveset_HTM, - .ntrans = 1, - .trans = trans_group_trivial -}; - -PruneData -pd_cornershtr_HTM = { - .filename = "ptable_cornershtr_withcosets_HTM", - .coord = &coord_cornershtr, - .moveset = moveset_HTM, - .ntrans = 1, - .trans = trans_group_trivial -}; - -PruneData -pd_corners_HTM = { - .filename = "ptable_corners_HTM", - .coord = &coord_corners, - .moveset = moveset_HTM, - .ntrans = 1, - .trans = trans_group_trivial -}; - -PruneData -pd_drud_HTM = { - .filename = "ptable_drud_HTM", - .coord = &coord_drud, - .moveset = moveset_HTM, - .ntrans = 1, - .trans = trans_group_trivial -}; - -PruneData -pd_drud_sym16_HTM = { - .filename = "ptable_drud_sym16_HTM", - .coord = &coord_drud_sym16, - .moveset = moveset_HTM, - .ntrans = 16, - .trans = trans_group_udfix -}; - -PruneData -pd_khuge_HTM = { - .filename = "ptable_khuge_HTM", - .coord = &coord_khuge, - .moveset = moveset_HTM, - .ntrans = 16, - .trans = trans_group_udfix -}; - - -/* Standard checkers (return lower bound) ************************************/ - -static int -estimate_eofb_HTM(CubeTarget ct) -{ - if (!pd_eofb_HTM.generated) - genptable(&pd_eofb_HTM); - - return ptableval(&pd_eofb_HTM, ct.cube); -} - -static int -estimate_coud_HTM(CubeTarget ct) -{ - if (!pd_coud_HTM.generated) - genptable(&pd_coud_HTM); - - return ptableval(&pd_coud_HTM, ct.cube); -} - -static int -estimate_coud_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; - CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; - - int ud = estimate_coud_HTM(ct); - int rl = estimate_coud_HTM(ct2); - int fb = estimate_coud_HTM(ct3); - - return MIN(ud, MIN(rl, fb)); -} - -static int -estimate_corners_HTM(CubeTarget ct) -{ - if (!pd_corners_HTM.generated) - genptable(&pd_corners_HTM); - - return ptableval(&pd_corners_HTM, ct.cube); -} - -static int -estimate_cornershtr_HTM(CubeTarget ct) -{ - if (!pd_cornershtr_HTM.generated) - genptable(&pd_cornershtr_HTM); - - return ptableval(&pd_cornershtr_HTM, ct.cube); -} - -static int -estimate_cornershtr_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_cornershtr_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_corners_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_corners_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_drud_HTM(CubeTarget ct) -{ -/* - if (!pd_drud_HTM.generated) - genptable(&pd_drud_HTM); - - return ptableval(&pd_drud_HTM, ct.cube); -*/ - - if (!pd_drud_sym16_HTM.generated) - genptable(&pd_drud_sym16_HTM); - - return ptableval(&pd_drud_sym16_HTM, ct.cube); -} - -static int -estimate_optimal_HTM(CubeTarget ct) -{ - int dr1, dr2, dr3, cor, ret; - Cube cube = ct.cube; - - if (!pd_khuge_HTM.generated) - genptable(&pd_khuge_HTM); - - dr1 = ptableval(&pd_khuge_HTM, cube); - cor = estimate_corners_HTM(ct); - ret = MAX(dr1, cor); - - if (ret > ct.target) - return ret; - - cube = apply_trans(rf, ct.cube); - dr2 = ptableval(&pd_khuge_HTM, cube); - ret = MAX(ret, dr2); - - if (ret > ct.target) - return ret; - - cube = apply_trans(fd, ct.cube); - dr3 = ptableval(&pd_khuge_HTM, cube); - - /* Michiel de Bondt's trick */ - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - dr3++; - - return MAX(ret, dr3); -} diff --git a/old/2021-07-15-almostbeforerefactor/steps.h b/old/2021-07-15-almostbeforerefactor/steps.h @@ -1,24 +0,0 @@ -#ifndef STEPS_H -#define STEPS_H - -#include "cube.h" - -extern Step eofb_HTM; -extern Step coud_HTM; -extern Step coud_URF; -extern Step corners_HTM; -extern Step cornershtr_HTM; -extern Step corners_URF; -extern Step cornershtr_URF; -extern Step drud_HTM; -extern Step optimal_HTM; - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_cornershtr_HTM; -extern PruneData pd_cornershtreofb_HTM; -extern PruneData pd_drud_HTM; -extern PruneData pd_khuge_HTM; - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/alg.c b/old/2021-11-10-beforeremovingchecker/alg.c @@ -1,366 +0,0 @@ -#include "alg.h" - -/* Local functions ***********************************************************/ - -static void free_alglistnode(AlgListNode *aln); -static void realloc_alg(Alg *alg, int n); - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - -bool -moveset_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 -moveset_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 -moveset_htr(Move m) -{ - Move b = base_move(m); - - return moveset_HTM(m) && m == b + 1; -} - - -/* Functions *****************************************************************/ - -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++; -} - -Move -base_move(Move m) -{ - if (m == NULLMOVE) - return NULLMOVE; - else - return m - (m-1)%3; -} - -void -compose_alg(Alg *alg1, Alg *alg2) -{ - int i; - - for (i = 0; i < alg2->len; i++) - append_move(alg1, alg2->move[i], alg2->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); -} - -char * -move_string(Move m) -{ - static char move_string_aux[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\'", - }; - - return move_string_aux[m]; -} - -void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -void -moveset_to_list(Moveset ms, Move *r) -{ - int n = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) - if (ms(i)) - r[n++] = i; - - r[n] = NULLMOVE; -} - -Alg * -new_alg(char *str) -{ - Alg *alg = malloc(sizeof(Alg)); - int i; - bool niss = false, move_read; - Move j, m; - - alg->move = malloc(30 * sizeof(Move)); - alg->inv = malloc(30 * sizeof(bool)); - alg->allocated = 30; - alg->len = 0; - - 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"); - return alg; - } - - if (str[i] == ')' && !niss) { - fprintf(stderr, "Error reading moves: unmatched )\n"); - return alg; - } - - if (str[i] == '(' || str[i] == ')') { - niss = !niss; - continue; - } - - move_read = false; - for (j = 0; 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) { - alg = new_alg(""); - return alg; - } - } - - return alg; -} - -AlgList * -new_alglist() -{ - AlgList *ret = malloc(sizeof(AlgList)); - - ret->len = 0; - ret->first = NULL; - ret->last = NULL; - - return ret; -} - -Alg * -on_inverse(Alg *alg) -{ - Alg *ret = new_alg(""); - int i; - - for (i = 0; i < alg->len; i++) - append_move(ret, alg->move[i], !alg->inv[i]); - - return ret; -} - -void -print_alg(Alg *alg, bool l) -{ - /* TODO: make it possible to print to stdout or to string */ - /* Maybe just return a string */ - 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(")"); - if (l) - printf(" (%d)", alg->len); - - printf("\n"); -} - -void -print_alglist(AlgList *al, bool l) -{ - AlgListNode *i; - - for (i = al->first; i != NULL; i = i->next) - print_alg(i->alg, l); -} - -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; -} - diff --git a/old/2021-11-10-beforeremovingchecker/alg.h b/old/2021-11-10-beforeremovingchecker/alg.h @@ -1,35 +0,0 @@ -#ifndef ALG_H -#define ALG_H - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "cubetypes.h" -#include "utils.h" - -bool moveset_HTM(Move m); -bool moveset_URF(Move m); -bool moveset_eofb(Move m); -bool moveset_drud(Move m); -bool moveset_htr(Move m); - -void append_alg(AlgList *l, Alg *alg); -void append_move(Alg *alg, Move m, bool inverse); -void compose_alg(Alg *alg1, Alg *alg2); -Move base_move(Move m); -void free_alg(Alg *alg); -void free_alglist(AlgList *l); -Alg * inverse_alg(Alg *alg); -Move inverse_move(Move m); -char * move_string(Move m); -void movelist_to_position(Move *ml, int *pos); -void moveset_to_list(Moveset ms, Move *lst); -Alg * new_alg(char *str); -AlgList * new_alglist(); -Alg * on_inverse(Alg *alg); -void print_alg(Alg *alg, bool l); -void print_alglist(AlgList *al, bool l); - -#endif - diff --git a/old/2021-11-10-beforeremovingchecker/commands.c b/old/2021-11-10-beforeremovingchecker/commands.c @@ -1,329 +0,0 @@ -#include "commands.h" - -/* Arg parsing functions *****************************************************/ - -CommandArgs * solvestep_parse_args(int c, char **v); -CommandArgs * help_parse_args(int c, char **v); -CommandArgs * print_parse_args(int c, char **v); -CommandArgs * parse_no_arg(int c, char **v); - -/* Exec functions ************************************************************/ - -static void solvestep_exec(CommandArgs *args); -static void steps_exec(CommandArgs *args); -static void commands_exec(CommandArgs *args); -static void print_exec(CommandArgs *args); -static void help_exec(CommandArgs *args); -static void quit_exec(CommandArgs *args); - -/* Local functions ***********************************************************/ - -static bool read_step(CommandArgs *args, char *str); -static bool read_scramble(int c, char **v, CommandArgs *args); - -/* Commands ******************************************************************/ - -Command -solvestep_cmd = { - .name = "solve", - .usage = "solve STEP [OPTIONS] SCRAMBLE", - .description = "Solve a step", - .parse_args = solvestep_parse_args, - .exec = solvestep_exec -}; - -Command -steps_cmd = { - .name = "steps", - .usage = "steps", - .description = "List available steps", - .parse_args = parse_no_arg, - .exec = steps_exec -}; - -Command -commands_cmd = { - .name = "commands", - .usage = "commands", - .description = "List available commands", - .parse_args = parse_no_arg, - .exec = commands_exec -}; - -Command -print_cmd = { - .name = "print", - .usage = "print SCRAMBLE", - .description = "Print written description of the cube", - .parse_args = print_parse_args, - .exec = print_exec, -}; - -Command -help_cmd = { - .name = "help", - .usage = "help [COMMAND]", - .description = "Display nissy manual page or help on specific command", - .parse_args = help_parse_args, - .exec = help_exec, -}; - -Command -quit_cmd = { - .name = "quit", - .usage = "quit", - .description = "Quit nissy", - .parse_args = parse_no_arg, - .exec = quit_exec, -}; - -Command *commands[NCOMMANDS] = { - &solvestep_cmd, - &steps_cmd, - &commands_cmd, - &help_cmd, - &print_cmd, - &quit_cmd -}; - -/* Arg parsing functions implementation **************************************/ - -CommandArgs * -solvestep_parse_args(int c, char **v) -{ - int i; - long val; - - CommandArgs *a = malloc(sizeof(CommandArgs)); - - a->success = false; - a->opts = malloc(sizeof(SolveOptions)); - a->step = steps[0]; - a->command = NULL; - a->scramble = NULL; - - a->opts->min_moves = 0; - a->opts->max_moves = 20; - a->opts->max_solutions = 1; - a->opts->optimal_only = false; - a->opts->can_niss = false; - a->opts->feedback = false; - a->opts->all = false; - a->opts->print_number = true; - - for (i = 0; i < c; i++) { - if (!strcmp(v[i], "-m")) { - val = strtol(v[++i], NULL, 10); - if (val < 0 || val > 100) { - fprintf(stderr, - "Invalid min number of moves.\n"); - return a; - } - a->opts->min_moves = val; - } else if (!strcmp(v[i], "-M")) { - val = strtol(v[++i], NULL, 10); - if (val < 0 || val > 100) { - fprintf(stderr, - "Invalid max number of moves.\n"); - return a; - } - a->opts->max_moves = val; - } else if (!strcmp(v[i], "-s")) { - val = strtol(v[++i], NULL, 10); - if (val < 1 || val > 1000000) { - fprintf(stderr, - "Invalid number of solutions.\n"); - return a; - } - a->opts->max_solutions = val; - } else if (!strcmp(v[i], "-o")) { - a->opts->optimal_only = true; - } else if (!strcmp(v[i], "-n")) { - a->opts->can_niss = true; - } else if (!strcmp(v[i], "-v")) { - a->opts->feedback = true; - } else if (!strcmp(v[i], "-a")) { - a->opts->all = true; - } else if (!strcmp(v[i], "-p")) { - a->opts->print_number = false; - } else if (!read_step(a, v[i])) { - break; - } - } - - a->success = read_scramble(c-i, &v[i], a); - return a; -} - -CommandArgs * -help_parse_args(int c, char **v) -{ - int i; - CommandArgs *a = malloc(sizeof(CommandArgs)); - - a->scramble = NULL; - a->opts = NULL; - a->step = NULL; - a->command = NULL; - - if (c == 1) { - for (i = 0; i < NCOMMANDS; i++) - if (commands[i] != NULL && - !strcmp(v[0], commands[i]->name)) - a->command = commands[i]; - if (a->command == NULL) - fprintf(stderr, "%s: command not found\n", v[0]); - } - - a->success = c == 0 || (c == 1 && a->command != NULL); - return a; -} - -CommandArgs * -parse_no_arg(int c, char **v) -{ - CommandArgs *a = malloc(sizeof(CommandArgs)); - - a->scramble = NULL; - a->opts = NULL; - a->step = NULL; - a->command = NULL; - - return a; -} - -CommandArgs * -print_parse_args(int c, char **v) -{ - CommandArgs *a = malloc(sizeof(CommandArgs)); - - a->opts = NULL; - a->step = NULL; - a->command = NULL; - - a->success = read_scramble(c-1, &v[1], a); - return a; -} - -/* Exec functions implementation *********************************************/ - -static void -solvestep_exec(CommandArgs *args) -{ - Cube c = apply_alg(args->scramble, (Cube){0}); - AlgList *sols = solve(c, args->step, args->opts); - print_alglist(sols, args->opts->print_number); - free_alglist(sols); -} - -static void -steps_exec(CommandArgs *args) -{ - int i; - - for (i = 0; i < NSTEPS && steps[i] != NULL; i++) - printf("%-15s %s\n", steps[i]->shortname, steps[i]->name); -} - -static void -commands_exec(CommandArgs *args) -{ - int i; - - for (i = 0; i < NCOMMANDS && commands[i] != NULL; i++) - printf("%s\n", commands[i]->usage); - -} - -static void -print_exec(CommandArgs *args) -{ - print_cube(apply_alg(args->scramble, (Cube){0})); -} - -static void -help_exec(CommandArgs *args) -{ - /* TODO: print full nissy manpage */ - if (args->command == NULL) { - printf("Type help COMMAND for information on a "); - printf("specific command.\n"); - printf("A more complete manual page is work in progress.\n"); - } else { - printf("Command %s: %s\nusage: %s\n", args->command->name, - args->command->description, args->command->usage); - } -} - -static void -quit_exec(CommandArgs *args) -{ - exit(0); -} - -/* Local functions implementation ********************************************/ - -static bool -read_step(CommandArgs *args, char *str) -{ - int i; - - for (i = 0; i < NSTEPS; i++) { - if (steps[i] != NULL && !strcmp(steps[i]->shortname, str)) { - args->step = steps[i]; - return true; - } - } - - return false; -} - -static bool -read_scramble(int c, char **v, CommandArgs *args) -{ - int i, k, n; - unsigned int j; - char *algstr; - - if (new_alg(v[0])->len == 0) { - fprintf(stderr, "%s: moves or option unrecognized\n", v[0]); - return false; - } - - n = 0; - for(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; - - args->scramble = new_alg(algstr); - free(algstr); - - if (args->scramble->len == 0) - fprintf(stderr, "Error reading scramble\n"); - - return args->scramble->len > 0; -} - -/* Public functions implementation *******************************************/ - -void -free_args(CommandArgs *args) -{ - if (args == NULL) - return; - - if (args->scramble != NULL) - free_alg(args->scramble); - if (args->opts != NULL) - free(args->opts); - - /* step and command must not be freed, they are static! */ - - free(args); -} diff --git a/old/2021-11-10-beforeremovingchecker/commands.h b/old/2021-11-10-beforeremovingchecker/commands.h @@ -1,13 +0,0 @@ -#ifndef COMMANDS_H -#define COMMANDS_H - -#include "solve.h" -#include "steps.h" - -#define NCOMMANDS 10 - -void free_args(CommandArgs *args); - -extern Command * commands[NCOMMANDS]; - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/coord.c b/old/2021-11-10-beforeremovingchecker/coord.c @@ -1,629 +0,0 @@ -#include "coord.h" - -static Cube antindex_eofb(uint64_t ind); -static Cube antindex_eofbepos(uint64_t ind); -static Cube antindex_epud(uint64_t ind); -static Cube antindex_coud(uint64_t ind); -static Cube antindex_corners(uint64_t ind); -static Cube antindex_cp(uint64_t ind); -static Cube antindex_cphtr(uint64_t); -static Cube antindex_cornershtr(uint64_t ind); -static Cube antindex_cornershtrfin(uint64_t ind); -static Cube antindex_drud(uint64_t ind); -static Cube antindex_drud_eofb(uint64_t ind); -static Cube antindex_htr_drud(uint64_t ind); -static Cube antindex_htrfin(uint64_t ind); - -static uint64_t index_eofb(Cube cube); -static uint64_t index_eofbepos(Cube cube); -static uint64_t index_epud(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_cp(Cube cube); -static uint64_t index_cphtr(Cube cube); -static uint64_t index_cornershtr(Cube cube); -static uint64_t index_cornershtrfin(Cube cube); -static uint64_t index_drud(Cube cube); -static uint64_t index_drud_eofb(Cube cube); -static uint64_t index_htr_drud(Cube cube); -static uint64_t index_htrfin(Cube cube); - -static void init_cphtr_cosets(); -static void init_cphtr_left_cosets_bfs(int i, int c); -static void init_cphtr_right_cosets_color(int i, int c); -static void init_cornershtrfin(); - - -/* All sorts of useful costants and tables **********************************/ - -static int cphtr_left_cosets[FACTORIAL8]; -static int cphtr_right_cosets[FACTORIAL8]; -static int cphtr_right_rep[BINOM8ON4*6]; -static int cornershtrfin_ind[FACTORIAL8]; -static int cornershtrfin_ant[24*24/6]; - -/* Coordinates and their implementation **************************************/ - -Coordinate -coord_eofb = { - .index = index_eofb, - .cube = antindex_eofb, - .check = check_eofb, - .max = POW2TO11, - .ntrans = 1, -}; - -Coordinate -coord_eofbepos = { - .index = index_eofbepos, - .cube = antindex_eofbepos, - .check = check_eofbepos, - .max = POW2TO11 * BINOM12ON4, - .ntrans = 1, -}; - -Coordinate -coord_coud = { - .index = index_coud, - .cube = antindex_coud, - .check = check_coud, - .max = POW3TO7, - .ntrans = 1, -}; - -Coordinate -coord_corners = { - .index = index_corners, - .cube = antindex_corners, - .check = check_corners, - .max = POW3TO7 * FACTORIAL8, - .ntrans = 1, -}; - -Coordinate -coord_cp = { - .index = index_cp, - .cube = antindex_cp, - .check = check_cp, - .max = FACTORIAL8, - .ntrans = 1, -}; - -Coordinate -coord_cphtr = { - .index = index_cphtr, - .cube = antindex_cphtr, - .check = check_cphtr, - .max = BINOM8ON4 * 6, - .ntrans = 1, -}; - -Coordinate -coord_cornershtr = { - .index = index_cornershtr, - .cube = antindex_cornershtr, - .check = check_cornershtr, - .max = POW3TO7 * BINOM8ON4 * 6, - .ntrans = 1, -}; - -Coordinate -coord_cornershtrfin = { - .index = index_cornershtrfin, - .cube = antindex_cornershtrfin, - .check = check_cp, - .max = 24*24/6, - .ntrans = 1, -}; - -Coordinate -coord_epud = { - .index = index_epud, - .cube = antindex_epud, - .check = check_epud, - .max = FACTORIAL8, - .ntrans = 1, -}; - -Coordinate -coord_drud = { - .index = index_drud, - .cube = antindex_drud, - .check = check_drud, - .max = POW2TO11 * POW3TO7 * BINOM12ON4, - .ntrans = 1, -}; - -Coordinate -coord_htr_drud = { - .index = index_htr_drud, - .cube = antindex_htr_drud, - .check = check_drud, - .max = BINOM8ON4 * 6 * BINOM8ON4, - .ntrans = 1, -}; - -Coordinate -coord_htrfin = { - .index = index_htrfin, - .cube = antindex_htrfin, - .check = check_htr, - .max = 24 * 24 * 24 *24 * 24 / 6, /* should be /12 but it's ok */ - .ntrans = 1, -}; - -Coordinate -coord_drud_eofb = { - .index = index_drud_eofb, - .cube = antindex_drud_eofb, - .check = check_drud, - .max = POW3TO7 * BINOM12ON4, - .ntrans = 1, -}; - -/* Functions *****************************************************************/ - -static Cube -antindex_eofb(uint64_t ind) -{ - return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; -} - -static Cube -antindex_eofbepos(uint64_t ind) -{ - Cube ret = {0}; - - ret.eofb = ind % POW2TO11; - ret.epose = (ind / POW2TO11) * 24; - - return ret; -} - -static Cube -antindex_epud(uint64_t ind) -{ - static bool initialized = false; - static Cube epud_aux[FACTORIAL8]; - int a[12]; - uint64_t ui; - CubeArray arr; - - if (!initialized) { - a[FR] = FR; - a[FL] = FL; - a[BL] = BL; - a[BR] = BR; - for (ui = 0; ui < FACTORIAL8; ui++) { - index_to_perm(ui, 8, a); - arr.ep = a; - epud_aux[ui] = arrays_to_cube(&arr, pf_ep); - } - - initialized = true; - } - - return epud_aux[ind]; -} - -static Cube -antindex_coud(uint64_t ind) -{ - return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; -} - -static Cube -antindex_corners(uint64_t ind) -{ - Cube c = {0}; - - c.coud = ind / FACTORIAL8; - c.cp = ind % FACTORIAL8; - - return c; -} - -static Cube -antindex_cp(uint64_t ind) -{ - Cube c = {0}; - - c.cp = ind; - - return c; -} - -static Cube -antindex_cphtr(uint64_t ind) -{ - return (Cube) { .cp = cphtr_right_rep[ind] }; -} - -static Cube -antindex_cornershtr(uint64_t ind) -{ - Cube c = antindex_cphtr(ind % (BINOM8ON4 * 6)); - - c.coud = ind / (BINOM8ON4 * 6); - - return c; -} - -static Cube -antindex_cornershtrfin(uint64_t ind) -{ - return (Cube){ .cp = cornershtrfin_ant[ind] }; -} - -static Cube -antindex_drud(uint64_t ind) -{ - uint64_t epos, eofb; - Cube c; - - eofb = ind % POW2TO11; - epos = ind / (POW2TO11 * POW3TO7); - c = antindex_eofbepos(eofb + POW2TO11 * epos); - - c.coud = (ind / POW2TO11) % POW3TO7; - - return c; -} - -static Cube -antindex_drud_eofb(uint64_t ind) -{ - return antindex_drud(ind * POW2TO11); -} - -static Cube -antindex_htr_drud(uint64_t ind) -{ - Cube ret; - - ret = antindex_cphtr(ind / BINOM8ON4); - ret.eposs = (ind % BINOM8ON4) * FACTORIAL4; - - return ret; -} - -static Cube -antindex_htrfin(uint64_t ind) -{ - Cube ret; - - ret = antindex_cornershtrfin(ind/(24*24*24)); - - ret.eposm = ind % 24; - ind /= 24; - ret.eposs = ind % 24; - ind /= 24; - ret.epose = ind % 24; - - return ret; -} - -bool -check_centers(Cube cube) -{ - return cube.cpos == 0; -} - -bool -check_corners(Cube cube) -{ - return cube.cp == 0 && cube.coud == 0; -} - -bool -check_cp(Cube cube) -{ - return cube.cp == 0; -} - -bool -check_cphtr(Cube cube) -{ - return index_cphtr(cube) == 0; -} - -bool -check_cornershtr(Cube cube) -{ - return cube.coud == 0 && index_cphtr(cube) == 0; -} - -bool -check_coud(Cube cube) -{ - return cube.coud == 0; -} - -bool -check_drud(Cube cube) -{ - return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; -} - -bool -check_htr(Cube cube) -{ - return check_cornershtr(cube) && - cube.eofb == 0 && cube.eorl == 0 && cube.eoud == 0; -} - -bool -check_drudfin_noE(Cube cube) -{ - return cube.eposs == 0 && cube.eposm == 0 && cube.cp == 0; -} - -bool -check_eofb(Cube cube) -{ - return cube.eofb == 0; -} - -bool -check_eofbepos(Cube cube) -{ - return cube.eofb == 0 && cube.epose / 24 == 0; -} - -bool -check_epose(Cube cube) -{ - return cube.epose == 0; -} - -bool -check_epud(Cube cube) -{ - return cube.eposs == 0 && cube.eposm == 0; -} - -bool -check_ep(Cube cube) -{ - return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; -} - -bool -check_khuge(Cube cube) -{ - return check_drud(cube) && cube.epose % 24 == 0; -} - -bool -check_nothing(Cube cube) -{ - return is_admissible(cube); /*TODO: maybe change?*/ -} - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_eofbepos(Cube cube) -{ - return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; -} - -static uint64_t -index_epud(Cube cube) -{ - uint64_t ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = perm_to_index(arr->ep, 8); - free_cubearray(arr, pf_ep); - - return ret; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_cp(Cube cube) -{ - return cube.cp; -} - -static uint64_t -index_cphtr(Cube cube) -{ - return cphtr_right_cosets[cube.cp]; -} - -static uint64_t -index_cornershtr(Cube cube) -{ - return cube.coud * BINOM8ON4 * 6 + index_cphtr(cube); -} - -static uint64_t -index_cornershtrfin(Cube cube) -{ - return cornershtrfin_ind[cube.cp]; -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -static uint64_t -index_drud_eofb(Cube cube) -{ - return index_drud(cube) / POW2TO11; -} - -static uint64_t -index_htr_drud(Cube cube) -{ - return index_cphtr(cube) * BINOM8ON4 + - (cube.eposs / FACTORIAL4) % BINOM8ON4; -} - -static uint64_t -index_htrfin(Cube cube) -{ - uint64_t epe, eps, epm, cp, ep; - - epe = cube.epose % 24; - eps = cube.eposs % 24; - epm = cube.eposm % 24; - ep = (epe * 24 + eps) *24 + epm; - cp = index_cornershtrfin(cube); - - return cp * 24 * 24 * 24 + ep; -} - -/* Init functions implementation *********************************************/ - -/* - * There is certainly a better way to do this, but for now I just use - * a "graph coloring" algorithm to compute the left cosets, and I compose - * with every possible cp to get the right cosets (it is possible that I am - * mixing up left and right). - * - * For doing it better "Mathematically", we need 3 things: - * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other - * This is easy and it is done in the commented function cphtr_cp(). - * - Check that there is no ep/cp parity - * - Check that we are not in the "3c" case; this is the part I don't - * know how to do. - */ -static void -init_cphtr_cosets() -{ - unsigned int i; - int c = 0, d = 0; - - for (i = 0; i < FACTORIAL8; i++) { - cphtr_left_cosets[i] = -1; - cphtr_right_cosets[i] = -1; - } - - /* First we compute left cosets with a bfs */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_left_cosets[i] == -1) - init_cphtr_left_cosets_bfs(i, c++); - - /* Then we compute right cosets using compose() */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_right_cosets[i] == -1) - init_cphtr_right_cosets_color(i, d++); -} - -static void -init_cphtr_left_cosets_bfs(int i, int c) -{ - int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; - Move moves[6] = {U2, D2, R2, L2, F2, B2}; - - n = 1; - next[0] = i; - cphtr_left_cosets[i] = c; - - while (n != 0) { - for (j = 0, n2 = 0; j < n; j++) { - for (k = 0; k < 6; k++) { - /*jj = cp_mtable[moves[k]][next[j]];*/ - /* TODO fix formatting */ - jj = apply_move(moves[k], (Cube){.cp=next[j]}).cp; - if (cphtr_left_cosets[jj] == -1) { - cphtr_left_cosets[jj] = c; - next2[n2++] = jj; - } - } - } - - for (j = 0; j < n2; j++) - next[j] = next2[j]; - n = n2; - } -} - -static void -init_cphtr_right_cosets_color(int i, int d) -{ - int cp; - unsigned int j; - - cphtr_right_rep[d] = i; - for (j = 0; j < FACTORIAL8; j++) { - if (cphtr_left_cosets[j] == 0) { - /* TODO: use antindexer, it's nicer */ - cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; - cphtr_right_cosets[cp] = d; - } - } -} - -static void -init_cornershtrfin() -{ - unsigned int i, j; - int n, c; - Move m; - - for (i = 0; i < FACTORIAL8; i++) - cornershtrfin_ind[i] = -1; - cornershtrfin_ind[0] = 0; - - /* 10-pass, I think 5 is enough, but just in case */ - n = 1; - for (i = 0; i < 10; i++) { - for (j = 0; j < FACTORIAL8; j++) { - if (cornershtrfin_ind[j] == -1) - continue; - for (m = U; m < NMOVES; m++) { - if (moveset_htr(m)) { - c = apply_move(m, (Cube){.cp = j}).cp; - if (cornershtrfin_ind[c] == -1) { - cornershtrfin_ind[c] = n; - cornershtrfin_ant[n] = c; - n++; - } - } - } - } - } -} - -void -init_coord() -{ - static bool initialized = false; - if (initialized) - return; - initialized = true; - - init_cphtr_cosets(); - init_cornershtrfin(); -} - diff --git a/old/2021-11-10-beforeremovingchecker/coord.h b/old/2021-11-10-beforeremovingchecker/coord.h @@ -1,40 +0,0 @@ -#ifndef COORD_H -#define COORD_H - -#include "trans.h" - -extern Coordinate coord_eofb; -extern Coordinate coord_eofbepos; -extern Coordinate coord_coud; -extern Coordinate coord_cp; -extern Coordinate coord_cphtr; -extern Coordinate coord_corners; -extern Coordinate coord_cornershtr; -extern Coordinate coord_cornershtrfin; -extern Coordinate coord_epud; -extern Coordinate coord_drud; -extern Coordinate coord_drud_eofb; -extern Coordinate coord_htr_drud; -extern Coordinate coord_htrfin; - -bool check_centers(Cube cube); -bool check_corners(Cube cube); -bool check_cp(Cube cube); -bool check_cphtr(Cube cube); -bool check_cornershtr(Cube cube); -bool check_coud(Cube cube); -bool check_drud(Cube cube); -bool check_htr(Cube cube); -bool check_drudfin_noE(Cube cube); -bool check_eofb(Cube cube); -bool check_eofbepos(Cube cube); -bool check_epose(Cube cube); -bool check_ep(Cube cube); -bool check_epud(Cube cube); -bool check_khuge(Cube cube); -bool check_nothing(Cube cube); - -void init_coord(); - -#endif - diff --git a/old/2021-11-10-beforeremovingchecker/cube.c b/old/2021-11-10-beforeremovingchecker/cube.c @@ -1,716 +0,0 @@ -#include "cube.h" - -/* Local functions **********************************************************/ - -static int array_ep_to_epos(int *ep, int *eps_solved); -static int epos_from_arrays(int *epos, int *ep); - -/* Local functions implementation ********************************************/ - -static int -array_ep_to_epos(int *ep, int *ss) -{ - int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int eps[4]; - int i, j, is; - - for (i = 0, is = 0; i < 12; i++) { - for (j = 0; j < 4; j++) { - if (ep[i] == ss[j]) { - eps[is++] = j; - epos[i] = 1; - } - } - } - - for (i = 0; i < 4; i++) - swap(&epos[ss[i]], &epos[i+8]); - - return epos_from_arrays(epos, eps); -} - -static int -epos_from_arrays(int *epos, int *ep) -{ - return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); -} - -/* Public functions implementation *******************************************/ - -Cube -arrays_to_cube(CubeArray *arr, PieceFilter f) -{ - Cube ret = {0}; - - static int epe_solved[4] = {FR, FL, BL, BR}; - static int eps_solved[4] = {UL, UR, DL, DR}; - static int epm_solved[4] = {UF, UB, DF, DB}; - - if (f.epose) - ret.epose = array_ep_to_epos(arr->ep, epe_solved); - if (f.eposs) - ret.eposs = array_ep_to_epos(arr->ep, eps_solved); - if (f.eposm) - ret.eposm = array_ep_to_epos(arr->ep, epm_solved); - if (f.eofb) - ret.eofb = digit_array_to_int(arr->eofb, 11, 2); - if (f.eorl) - ret.eorl = digit_array_to_int(arr->eorl, 11, 2); - if (f.eoud) - ret.eoud = digit_array_to_int(arr->eoud, 11, 2); - if (f.cp) - ret.cp = perm_to_index(arr->cp, 8); - if (f.coud) - ret.coud = digit_array_to_int(arr->coud, 7, 3); - if (f.corl) - ret.corl = digit_array_to_int(arr->corl, 7, 3); - if (f.cofb) - ret.cofb = digit_array_to_int(arr->cofb, 7, 3); - if (f.cpos) - ret.cpos = perm_to_index(arr->cpos, 6); - - return ret; -} - -Cube -compose_filtered(Cube c2, Cube c1, PieceFilter f) -{ - CubeArray *arr = new_cubearray(c2, f); - Cube ret; - - ret = move_via_arrays(arr, c1, f); - free_cubearray(arr, f); - - return ret; -} - -void -cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) -{ - int i; - - static int epe_solved[4] = {FR, FL, BL, BR}; - static int eps_solved[4] = {UL, UR, DL, DR}; - static int epm_solved[4] = {UF, UB, DF, DB}; - - if (f.epose || f.eposs || f.eposm) - for (i = 0; i < 12; i++) - arr->ep[i] = -1; - - if (f.epose) - epos_to_partial_ep(cube.epose, arr->ep, epe_solved); - if (f.eposs) - epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); - if (f.eposm) - epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); - if (f.eofb) - int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); - if (f.eorl) - int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); - if (f.eoud) - int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); - if (f.cp) - index_to_perm(cube.cp, 8, arr->cp); - if (f.coud) - int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); - if (f.corl) - int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); - if (f.cofb) - int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); - if (f.cpos) - index_to_perm(cube.cpos, 6, arr->cpos); -} - -void -epos_to_partial_ep(int epos, int *ep, int *ss) -{ - int i, is, eposs[12], eps[4]; - - index_to_perm(epos % FACTORIAL4, 4, eps); - index_to_subset(epos / FACTORIAL4, 12, 4, eposs); - - for (i = 0; i < 4; i++) - swap(&eposs[ss[i]], &eposs[i+8]); - - for (i = 0, is = 0; i < 12; i++) - if (eposs[i]) - ep[i] = ss[eps[is++]]; -} - -void -free_cubearray(CubeArray *arr, PieceFilter f) -{ - if (f.epose || f.eposs || f.eposm) - free(arr->ep); - if (f.eofb) - free(arr->eofb); - if (f.eorl) - free(arr->eorl); - if (f.eoud) - free(arr->eoud); - if (f.cp) - free(arr->cp); - if (f.coud) - free(arr->coud); - if (f.corl) - free(arr->corl); - if (f.cofb) - free(arr->cofb); - if (f.cpos) - free(arr->cpos); - - free(arr); -} - -Cube -move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) -{ - CubeArray *arrc = new_cubearray(c, f); - Cube ret; - - if (f.epose || f.eposs || f.eposm) - apply_permutation(arr->ep, arrc->ep, 12); - - if (f.eofb) { - apply_permutation(arr->ep, arrc->eofb, 12); - sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); - } - - if (f.eorl) { - apply_permutation(arr->ep, arrc->eorl, 12); - sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); - } - - if (f.eoud) { - apply_permutation(arr->ep, arrc->eoud, 12); - sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); - } - - if (f.cp) - apply_permutation(arr->cp, arrc->cp, 8); - - if (f.coud) { - apply_permutation(arr->cp, arrc->coud, 8); - sum_arrays_mod(arr->coud, arrc->coud, 8, 3); - } - - if (f.corl) { - apply_permutation(arr->cp, arrc->corl, 8); - sum_arrays_mod(arr->corl, arrc->corl, 8, 3); - } - - if (f.cofb) { - apply_permutation(arr->cp, arrc->cofb, 8); - sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); - } - - if (f.cpos) - apply_permutation(arr->cpos, arrc->cpos, 6); - - ret = arrays_to_cube(arrc, f); - free_cubearray(arrc, f); - - return ret; -} - -CubeArray * -new_cubearray(Cube cube, PieceFilter f) -{ - CubeArray *arr = malloc(sizeof(CubeArray)); - - if (f.epose || f.eposs || f.eposm) - arr->ep = malloc(12 * sizeof(int)); - if (f.eofb) - arr->eofb = malloc(12 * sizeof(int)); - if (f.eorl) - arr->eorl = malloc(12 * sizeof(int)); - if (f.eoud) - arr->eoud = malloc(12 * sizeof(int)); - if (f.cp) - arr->cp = malloc(8 * sizeof(int)); - if (f.coud) - arr->coud = malloc(8 * sizeof(int)); - if (f.corl) - arr->corl = malloc(8 * sizeof(int)); - if (f.cofb) - arr->cofb = malloc(8 * sizeof(int)); - if (f.cpos) - arr->cpos = malloc(6 * sizeof(int)); - - cube_to_arrays(cube, arr, f); - - return arr; -} - - -/* TODO: consider if this is good here or better in coord.c - in any case it is used in transformation init at the moment */ -Cube -admissible_ep(Cube cube, PieceFilter f) -{ - CubeArray *arr = new_cubearray(cube, f); - Cube ret; - bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - for (i = 0; i < 12; i++) - if (arr->ep[i] != -1) - used[arr->ep[i]] = true; - - for (i = 0, j = 0; i < 12; i++) { - for ( ; j < 11 && used[j]; j++); - if (arr->ep[i] == -1) - arr->ep[i] = j++; - } - - ret = arrays_to_cube(arr, pf_ep); - free_cubearray(arr, f); - - return ret; -} - -Cube -compose(Cube c2, Cube c1) -{ - return compose_filtered(c2, c1, pf_all); -} - -int -edge_slice(Edge e) { - if (e < 0 || e > 11) - return -1; - - if (e == FR || e == FL || e == BL || e == BR) - return 0; - if (e == UR || e == UL || e == DR || e == DL) - return 1; - - return 2; -} - -bool -equal(Cube c1, Cube c2) -{ - return c1.eofb == c2.eofb && - c1.epose == c2.epose && - c1.eposs == c2.eposs && - c1.eposm == c2.eposm && - c1.coud == c2.coud && - c1.cp == c2.cp && - c1.cpos == c2.cpos; -} - -Cube -inverse_cube(Cube cube) -{ - CubeArray *arr = new_cubearray(cube, pf_all); - CubeArray *inv = new_cubearray((Cube){0}, pf_all); - Cube ret; - int i; - - for (i = 0; i < 12; i++) { - inv->ep[arr->ep[i]] = i; - inv->eofb[arr->ep[i]] = arr->eofb[i]; - inv->eorl[arr->ep[i]] = arr->eorl[i]; - inv->eoud[arr->ep[i]] = arr->eoud[i]; - } - - for (i = 0; i < 8; i++) { - inv->cp[arr->cp[i]] = i; - inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; - inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; - inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; - } - - for (int i = 0; i < 6; i++) - inv->cpos[arr->cpos[i]] = i; - - ret = arrays_to_cube(inv, pf_all); - free_cubearray(arr, pf_all); - free_cubearray(inv, pf_all); - - return ret; -} - -bool -is_admissible(Cube cube) -{ - /* TODO: this should check consistency of different orientations */ - /* TODO: check that centers are opposite and admissible */ - - CubeArray *a = new_cubearray(cube, pf_all); - int parity; - bool perm; - - perm = is_perm(a->ep, 12) && - is_perm(a->cp, 8) && - is_perm(a->cpos, 6); - parity = perm_sign(a->ep, 12) + - perm_sign(a->cp, 8) + - perm_sign(a->cpos, 6); - - return perm && parity % 2 == 0; -} - -bool -is_solved(Cube cube) -{ - /* TODO: move somewhere else, like in solve.c - int i; - if (reorient) { - for (i = 0; i < NROTATIONS; i++) - if (is_solved(apply_alg(rotation_algs[i], cube),false)) - return true; - return false; - } else { - return equal(cube, (Cube){0}); - } - */ - - return equal(cube, (Cube){0}); -} - -bool -is_solved_block(Cube cube, Block block) -{ - int i; - - for (i = 0; i < 12; i++) - if (block.edge[i] && !is_solved_edge(cube, i)) - return false; - for (i = 0; i < 8; i++) - if (block.corner[i] && !is_solved_corner(cube, i)) - return false; - for (i = 0; i < 6; i++) - if (block.center[i] && !is_solved_center(cube, i)) - return false; - - return true; -} - -bool -is_solved_center(Cube cube, Center c) -{ - return what_center_at(cube, c) == c; -} - -bool -is_solved_corner(Cube cube, Corner c) -{ - return what_corner_at(cube, c) == c && - what_orientation_corner(cube.coud, c); -} - -bool -is_solved_edge(Cube cube, Edge e) -{ - return what_edge_at(cube, e) == e && - what_orientation_edge(cube.eofb, e); -} - -int -piece_orientation(Cube cube, int piece, char *orientation) -{ - int arr[12], n, b, x; - - if (!strcmp(orientation, "eofb")) { - x = cube.eofb; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eorl")) { - x = cube.eorl; - n = 12; - b = 2; - } else if (!strcmp(orientation, "eoud")) { - x = cube.eoud; - n = 12; - b = 2; - } else if (!strcmp(orientation, "coud")) { - x = cube.coud; - n = 8; - b = 3; - } else if (!strcmp(orientation, "corl")) { - x = cube.corl; - n = 8; - b = 3; - } else if (!strcmp(orientation, "cofb")) { - x = cube.cofb; - n = 8; - b = 3; - } else { - return -1; - } - - int_to_sum_zero_array(x, b, n, arr); - if (piece < n) - return arr[piece]; - - return -1; -} - -void -print_cube(Cube cube) -{ - static char edge_string[12][7] = { - [UF] = "UF", [UL] = "UL", [UB] = "UB", [UR] = "UR", - [DF] = "DF", [DL] = "DL", [DB] = "DB", [DR] = "DR", - [FR] = "FR", [FL] = "FL", [BL] = "BL", [BR] = "BR" - }; - - static char corner_string[8][7] = { - [UFR] = "UFR", [UFL] = "UFL", [UBL] = "UBL", [UBR] = "UBR", - [DFR] = "DFR", [DFL] = "DFL", [DBL] = "DBL", [DBR] = "DBR" - }; - - static char center_string[6][7] = { - [U_center] = "U", [D_center] = "D", - [R_center] = "R", [L_center] = "L", - [F_center] = "F", [B_center] = "B" - }; - - for (int i = 0; i < 12; i++) - printf(" %s ", edge_string[what_edge_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 12; i++) - printf(" %d ", what_orientation_edge(cube.eofb, i)); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf("%s ", corner_string[what_corner_at(cube, i)]); - printf("\n"); - - for (int i = 0; i < 8; i++) - printf(" %d ", what_orientation_corner(cube.coud, i)); - printf("\n"); - - for (int i = 0; i < 6; i++) - printf(" %s ", center_string[what_center_at(cube, i)]); - printf("\n"); -} - -Cube -random_cube() -{ - CubeArray *arr = new_cubearray((Cube){0}, pf_4val); - Cube ret; - int ep, cp, eo, co; - - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - index_to_perm(ep, 12, arr->ep); - index_to_perm(cp, 8, arr->cp); - int_to_sum_zero_array(eo, 2, 12, arr->eofb); - int_to_sum_zero_array(co, 3, 8, arr->coud); - - if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) - swap(&(arr->ep[0]), &(arr->ep[1])); - - ret = arrays_to_cube(arr, pf_4val); - free_cubearray(arr, pf_4val); - - return ret; -} - -Center -what_center_at(Cube cube, Center c) -{ - static bool initialized = false; - static Center aux[FACTORIAL6][6]; - static int i; - static unsigned int ui; - static CubeArray *arr; - - if (!initialized) { - for (ui = 0; ui < FACTORIAL6; ui++) { - arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); - for (i = 0; i < 6; i++) - aux[ui][i] = arr->cpos[i]; - free_cubearray(arr, pf_cpos); - } - - initialized = true; - } - - return aux[cube.cpos][c]; -} - -Corner -what_corner_at(Cube cube, Corner c) -{ - static bool initialized = false; - static Corner aux[FACTORIAL8][8]; - static int i; - static unsigned int ui; - static CubeArray *arr; - - if (!initialized) { - for (ui = 0; ui < FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.cp = ui}, pf_cp); - for (i = 0; i < 8; i++) - aux[ui][i] = arr->cp[i]; - free_cubearray(arr, pf_cp); - } - - initialized = true; - } - - return aux[cube.cp][c]; -} - -Edge -what_edge_at(Cube cube, Edge e) -{ - Edge ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = arr->ep[e]; - - free_cubearray(arr, pf_ep); - return ret; -} - -int -what_orientation_corner(int co, Corner c) -{ - static bool initialized = false; - static int auxlast[POW3TO7]; - static int auxarr[8]; - static unsigned int ui; - - if (!initialized) { - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, auxarr); - auxlast[ui] = auxarr[7]; - } - - initialized = true; - } - - if (c < 7) - return (co / powint(3, c)) % 3; - else - return auxlast[co]; -} - -int -what_orientation_edge(int eo, Edge e) -{ - static bool initialized = false; - static int auxlast[POW2TO11]; - static int auxarr[12]; - static unsigned int ui; - - if (!initialized) { - for (ui = 0; ui < POW2TO11; ui++) { - int_to_sum_zero_array(ui, 2, 12, auxarr); - auxlast[ui] = auxarr[11]; - } - - initialized = true; - } - - if (e < 11) - return (eo & (1 << e)) ? 1 : 0; - else - return auxlast[eo]; -} - -Center -where_is_center(Cube cube, Center c) -{ - static bool initialized = false; - static Center aux[FACTORIAL6][6]; - static int i; - static unsigned int ui; - static CubeArray *arr; - - if (!initialized) { - for (ui = 0; ui < FACTORIAL6; ui++) { - arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); - for (i = 0; i < 6; i++) - aux[ui][arr->cpos[i]] = i; - free_cubearray(arr, pf_cpos); - } - - initialized = true; - } - - return aux[cube.cpos][c]; -} - -Corner -where_is_corner(Cube cube, Corner c) -{ - static bool initialized = false; - static Corner aux[FACTORIAL8][8]; - static int i; - static unsigned int ui; - static CubeArray *arr; - - if (!initialized) { - for (ui = 0; ui < FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.cp = ui}, pf_cp); - for (i = 0; i < 8; i++) - aux[ui][arr->cp[i]] = i; - free_cubearray(arr, pf_cp); - } - - initialized = true; - } - return aux[cube.cp][c]; -} - -Edge -where_is_edge(Cube cube, Edge e) -{ - /* TODO: when I wrote this code I forgot to add the final - part, and now I can't remember how it was supposed to - work (i.e. how to recover the location of the edge - from these tables. I think it is either very easy or - wrong, in any case it is not a priority now. - Future Seba can deal with it. - - static bool initialized = false; - static Edge aux[3][FACTORIAL12/FACTORIAL8][12]; - static int i; - static unsigned int ui; - static CubeArray *arr; - - if (!initialized) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - arr = new_cubearray((Cube){.epose = ui}, pf_e); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 0) - aux[0][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_e); - - arr = new_cubearray((Cube){.eposs = ui}, pf_s); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 1) - aux[1][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_s); - - arr = new_cubearray((Cube){.eposm = ui}, pf_m); - for (i = 0; i < 12; i++) - if (edge_slice(arr->ep[i]) == 2) - aux[2][ui][arr->ep[i]] = i; - free_cubearray(arr, pf_m); - } - - initialized = true; - } - */ - - int i; - CubeArray *arr = new_cubearray(cube, pf_ep); - - for (i = 0; i < 12; i++) - if ((Edge)arr->ep[i] == e) - return i; - - return -1; -} diff --git a/old/2021-11-10-beforeremovingchecker/cube.h b/old/2021-11-10-beforeremovingchecker/cube.h @@ -1,40 +0,0 @@ -#ifndef CUBE_H -#define CUBE_H - -#include <stdio.h> -#include <time.h> - -#include "pf.h" -#include "utils.h" - -Cube admissible_ep(Cube cube, PieceFilter f); /* TODO: move? */ -Cube arrays_to_cube(CubeArray *arr, PieceFilter f); /* TODO: remove */ -Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ -Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); -void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); -int edge_slice(Edge e); /* E=0, S=1, M=2 */ -bool equal(Cube c1, Cube c2); -Cube inverse_cube(Cube cube); -bool is_admissible(Cube cube); -bool is_solved(Cube cube); -bool block_solved(Cube cube, Block); /*TODO: rename to is_solved_block()*/ -bool is_solved_center(Cube cube, Center c); -bool is_solved_corner(Cube cube, Corner c); -bool is_solved_edge(Cube cube, Edge e); -void epos_to_partial_ep(int epos, int *ep, int *ss); -void free_cubearray(CubeArray *arr, PieceFilter f); /* TODO: remove */ -Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); -CubeArray * new_cubearray(Cube cube, PieceFilter f); /* TODO: remove */ -void print_cube(Cube cube); -Cube random_cube(); -Center what_center_at(Cube cube, Center c); -Corner what_corner_at(Cube cube, Corner c); -Edge what_edge_at(Cube cube, Edge e); -int what_orientation_corner(int co, Corner c); -int what_orientation_edge(int eo, Edge e); -Center where_is_center(Cube cube, Center c); -Corner where_is_corner(Cube cube, Corner c); -Edge where_is_edge(Cube cube, Edge e); - -#endif - diff --git a/old/2021-11-10-beforeremovingchecker/cubetypes.h b/old/2021-11-10-beforeremovingchecker/cubetypes.h @@ -1,298 +0,0 @@ -#ifndef CUBETYPES_H -#define CUBETYPES_H - -#include <stdbool.h> -#include <stdint.h> - -#define NMOVES 55 /* Actually 55, but one is NULLMOVE */ -#define NTRANS 48 -#define NROTATIONS 24 - - -/* Typedefs ******************************************************************/ - -typedef enum center Center; -typedef enum corner Corner; -typedef enum edge Edge; -typedef enum move Move; -typedef enum trans Trans; - -typedef struct alg Alg; -typedef struct alglist AlgList; -typedef struct alglistnode AlgListNode; -typedef struct block Block; -typedef struct command Command; -typedef struct commandargs CommandArgs; -typedef struct coordinate Coordinate; -typedef struct cube Cube; -typedef struct cubearray CubeArray; -typedef struct cubetarget CubeTarget; -typedef struct dfsdata DfsData; -typedef struct piecefilter PieceFilter; -typedef struct prunedata PruneData; -typedef struct solveoptions SolveOptions; -typedef struct step Step; -typedef struct symdata SymData; - -typedef Cube (*AntiIndexer) (uint64_t); -typedef bool (*Checker) (Cube); -typedef int (*Estimator) (CubeTarget); -typedef bool (*Validator) (Alg *); -typedef void (*Exec) (CommandArgs *); -typedef uint64_t (*Indexer) (Cube); -typedef bool (*Moveset) (Move); -typedef CommandArgs * (*ArgParser) (int, char **); -typedef Trans (*TransDetector) (Cube); - - -/* Enums *********************************************************************/ - -enum -center -{ - U_center, D_center, - R_center, L_center, - F_center, B_center -}; - -enum -corner -{ - UFR, UFL, UBL, UBR, - DFR, DFL, DBL, DBR -}; - -enum -edge -{ - UF, UL, UB, UR, - DF, DL, DB, DR, - FR, FL, BL, BR -}; - -enum -move -{ - NULLMOVE, - U, U2, U3, D, D2, D3, - R, R2, R3, L, L2, L3, - F, F2, F3, B, B2, B3, - Uw, Uw2, Uw3, Dw, Dw2, Dw3, - Rw, Rw2, Rw3, Lw, Lw2, Lw3, - Fw, Fw2, Fw3, Bw, Bw2, Bw3, - M, M2, M3, - S, S2, S3, - E, E2, E3, - x, x2, x3, - y, y2, y3, - z, z2, z3, -}; - -enum -trans -{ - uf, ur, ub, ul, - df, dr, db, dl, - rf, rd, rb, ru, - lf, ld, lb, lu, - fu, fr, fd, fl, - bu, br, bd, bl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, - rf_mirror, rd_mirror, rb_mirror, ru_mirror, - lf_mirror, ld_mirror, lb_mirror, lu_mirror, - fu_mirror, fr_mirror, fd_mirror, fl_mirror, - bu_mirror, br_mirror, bd_mirror, bl_mirror, -}; - - -/* Structs *******************************************************************/ - -struct -alg -{ - Move * move; - bool * inv; - int len; - int allocated; -}; - -struct -alglist -{ - AlgListNode * first; - AlgListNode * last; - int len; -}; - -struct -alglistnode -{ - Alg * alg; - AlgListNode * next; -}; - -struct -block -{ - bool edge[12]; - bool corner[8]; - bool center[6]; -}; - -struct -command -{ - /* TODO: more stuff to add? maybe complete help? */ - /* Maybe add list of options */ - char * name; - char * usage; - char * description; - ArgParser parse_args; - Exec exec; -}; - -struct -commandargs -{ - bool success; - Alg * scramble; - SolveOptions * opts; - Step * step; - Command * command; /* For help */ -}; - -struct -coordinate -{ - Indexer index; - AntiIndexer cube; - Checker check; - uint64_t max; - int ntrans; - Trans * trans; -}; - -struct -cube -{ - int epose; - int eposs; - int eposm; - int eofb; - int eorl; - int eoud; - int cp; - int coud; - int cofb; - int corl; - int cpos; -}; - -struct -cubearray -{ - int * ep; - int * eofb; - int * eorl; - int * eoud; - int * cp; - int * coud; - int * corl; - int * cofb; - int * cpos; -}; - -struct -cubetarget -{ - Cube cube; - int target; -}; - -struct -dfsdata -{ - int d; - int m; - int lb; - bool niss; - Move last1; - Move last2; - AlgList * sols; - Alg * current_alg; - Move sorted_moves[NMOVES]; - int move_position[NMOVES]; -}; - -struct -piecefilter -{ - bool epose; - bool eposs; - bool eposm; - bool eofb; - bool eorl; - bool eoud; - bool cp; - bool coud; - bool cofb; - bool corl; - bool cpos; -}; - -struct -prunedata -{ - char * filename; - uint8_t * ptable; - bool generated; - uint64_t n; - Coordinate * coord; - Moveset moveset; -}; - -struct -solveoptions -{ - /* TODO: add option to list *all* solutions satisfying other - constraints (min/max moves and optimality) */ - int min_moves; - int max_moves; - int max_solutions; - bool optimal_only; - bool can_niss; - bool feedback; /* TODO: rename with "verbose" */ - bool all; - bool print_number; -}; - -struct -step -{ - char * shortname; - char * name; - Estimator estimate; - Checker ready; - char * ready_msg; - Validator is_valid; - Moveset moveset; - Trans pre_trans; - TransDetector detect; -}; - -struct -symdata -{ - char * filename; - bool generated; - Coordinate * coord; - Coordinate * sym_coord; - int ntrans; - Trans * trans; - uint64_t * class; - Cube * rep; - Trans * transtorep; -}; - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/env.c b/old/2021-11-10-beforeremovingchecker/env.c @@ -1,45 +0,0 @@ -#include "env.h" - -bool initialized_env = false; -char *tabledir; - -void -init_env() -{ - char *nissydata = getenv("NISSYDATA"); - char *localdata = getenv("XDG_DATA_HOME"); - char *home = getenv("HOME"); - bool read, write; - - if (initialized_env) - return; - - if (nissydata != NULL) { - tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); - strcpy(tabledir, nissydata); - } else if (localdata != NULL) { - tabledir = malloc(strlen(localdata) * sizeof(char) + 20); - strcpy(tabledir, localdata); - strcat(tabledir, "/nissy"); - } else if (home != NULL) { - tabledir = malloc(strlen(home) * sizeof(char) + 20); - strcpy(tabledir, home); - strcat(tabledir, "/.nissy"); - } - - mkdir(tabledir, 0777); - strcat(tabledir, "/tables"); - mkdir(tabledir, 0777); - - read = !access(tabledir, R_OK); - write = !access(tabledir, W_OK); - - if (!read) { - fprintf(stderr, "Table files cannot be read.\n"); - } else if (!write) { - fprintf(stderr, "Data directory not writable: "); - fprintf(stderr, "tables can be loaded, but not saved.\n"); - } - - initialized_env = true; -} diff --git a/old/2021-11-10-beforeremovingchecker/env.h b/old/2021-11-10-beforeremovingchecker/env.h @@ -1,15 +0,0 @@ -#ifndef ENV_H -#define ENV_H - -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/stat.h> - -extern char *tabledir; - -void init_env(); - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/moves.c b/old/2021-11-10-beforeremovingchecker/moves.c @@ -1,474 +0,0 @@ -#include "moves.h" - -/* Local functions ***********************************************************/ - -static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); -static bool read_mtables_file(); -static bool write_mtables_file(); - -/* Tables and other data *****************************************************/ - -/* Every move is translated to a an <U, x, y> alg before filling the - transition tables, see init_moves() */ - -static int edge_cycle[NMOVES][12] = -{ - [U] = { UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR }, - [x] = { DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR }, - [y] = { UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL } -}; - -static int corner_cycle[NMOVES][8] = -{ - [U] = { UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR }, - [x] = { DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR }, - [y] = { UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL } -}; - -static int center_cycle[NMOVES][6] = -{ - [x] = { F_center, B_center, R_center, L_center, D_center, U_center }, - [y] = { U_center, D_center, B_center, F_center, R_center, L_center } -}; - -static int eofb_flipped[NMOVES][12] = { - [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } -}; - -static int eorl_flipped[NMOVES][12] = { - [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } -}; - -static int eoud_flipped[NMOVES][12] = { - [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, - [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, - [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } -}; - -static int coud_flipped[NMOVES][8] = { - [x] = { - [UFR] = 2, [UBR] = 1, [UFL] = 1, [UBL] = 2, - [DBR] = 2, [DFR] = 1, [DBL] = 1, [DFL] = 2 - } -}; - -static int corl_flipped[NMOVES][8] = { - [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, - [y] = { - [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, - [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 - } -}; - -static int cofb_flipped[NMOVES][8] = { - [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, - [x] = { - [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, - [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 - }, - [y] = { - [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1, - [DFR] = 1, [DBR] = 2, [DBL] = 1, [DFL] = 2 - } -}; - -static char equiv_alg_string[100][NMOVES] = { - [NULLMOVE] = "", - - [U] = " U ", - [U2] = " UU ", - [U3] = " UUU ", - [D] = " xx U xx ", - [D2] = " xx UU xx ", - [D3] = " xx UUU xx ", - [R] = " yx U xxxyyy ", - [R2] = " yx UU xxxyyy ", - [R3] = " yx UUU xxxyyy ", - [L] = " yyyx U xxxy ", - [L2] = " yyyx UU xxxy ", - [L3] = " yyyx UUU xxxy ", - [F] = " x U xxx ", - [F2] = " x UU xxx ", - [F3] = " x UUU xxx ", - [B] = " xxx U x ", - [B2] = " xxx UU x ", - [B3] = " xxx UUU x ", - - [Uw] = " xx U xx y ", - [Uw2] = " xx UU xx yy ", - [Uw3] = " xx UUU xx yyy ", - [Dw] = " U yyy ", - [Dw2] = " UU yy ", - [Dw3] = " UUU y ", - [Rw] = " yyyx U xxxy x ", - [Rw2] = " yyyx UU xxxy xx ", - [Rw3] = " yyyx UUU xxxy xxx ", - [Lw] = " yx U xxxyyy xxx ", - [Lw2] = " yx UU xxxyyy xx ", - [Lw3] = " yx UUU xxxyyy x ", - [Fw] = " xxx U x yxxxyyy ", - [Fw2] = " xxx UU x yxxyyy ", - [Fw3] = " xxx UUU x yxyyy ", - [Bw] = " x U xxx yxyyy ", - [Bw2] = " x UU xxx yxxyyy ", - [Bw3] = " x UUU xxx yxxxyyy ", - - [M] = " yx U xx UUU yxyyy ", - [M2] = " yx UU xx UU xxxy ", - [M3] = " yx UUU xx U yxxxy ", - [S] = " x UUU xx U yyyx ", - [S2] = " x UU xx UU yyx ", - [S3] = " x U xx UUU yx ", - [E] = " U xx UUU xxyyy ", - [E2] = " UU xx UU xxyy ", - [E3] = " UUU xx U xxy ", - - [x] = " x ", - [x2] = " xx ", - [x3] = " xxx ", - [y] = " y ", - [y2] = " yy ", - [y3] = " yyy ", - [z] = " yyy x y ", - [z2] = " yy xx ", - [z3] = " y x yyy " -}; - -/* Transition tables, to be loaded up at the beginning */ -static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; -static int eofb_mtable[NMOVES][POW2TO11]; -static int eorl_mtable[NMOVES][POW2TO11]; -static int eoud_mtable[NMOVES][POW2TO11]; -static int cp_mtable[NMOVES][FACTORIAL8]; -static int coud_mtable[NMOVES][POW3TO7]; -static int cofb_mtable[NMOVES][POW3TO7]; -static int corl_mtable[NMOVES][POW3TO7]; -static int cpos_mtable[NMOVES][FACTORIAL6]; - - -/* Local functions implementation ********************************************/ - -static Cube -apply_move_cubearray(Move m, Cube cube, PieceFilter f) -{ - /*init_moves();*/ - - CubeArray m_arr = { - edge_cycle[m], - eofb_flipped[m], - eorl_flipped[m], - eoud_flipped[m], - corner_cycle[m], - coud_flipped[m], - corl_flipped[m], - cofb_flipped[m], - center_cycle[m] - }; - - return move_via_arrays(&m_arr, cube, f); -} - -/* Public functions **********************************************************/ - -Cube -apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) -{ - Cube ret = {0}; - int i; - - for (i = 0; i < alg->len; i++) - if (alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - ret = compose_filtered(c, inverse_cube(ret), f); - - for (i = 0; i < alg->len; i++) - if (!alg->inv[i]) - ret = a ? apply_move(alg->move[i], ret) : - apply_move_cubearray(alg->move[i], ret, f); - - return ret; -} - -Cube -apply_alg(Alg *alg, Cube cube) -{ - return apply_alg_generic(alg, cube, pf_all, true); -} - -Cube -apply_move(Move m, Cube cube) -{ - /*init_moves();*/ - - return (Cube) { - .epose = epose_mtable[m][cube.epose], - .eposs = eposs_mtable[m][cube.eposs], - .eposm = eposm_mtable[m][cube.eposm], - .eofb = eofb_mtable[m][cube.eofb], - .eorl = eorl_mtable[m][cube.eorl], - .eoud = eoud_mtable[m][cube.eoud], - .coud = coud_mtable[m][cube.coud], - .cofb = cofb_mtable[m][cube.cofb], - .corl = corl_mtable[m][cube.corl], - .cp = cp_mtable[m][cube.cp], - .cpos = cpos_mtable[m][cube.cpos] - }; -} - -void -init_moves() { - static bool initialized = false; - if (initialized) - return; - initialized = true; - - Cube c; - CubeArray arrs; - int i; - unsigned int ui; - Move m; - Alg *equiv_alg[NMOVES]; - - for (i = 0; i < NMOVES; i++) - equiv_alg[i] = new_alg(equiv_alg_string[i]); - - /* Generate all move cycles and flips; I do this regardless */ - for (i = 0; i < NMOVES; i++) { - if (i == U || i == x || i == y) - continue; - - c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); - - arrs = (CubeArray) { - edge_cycle[i], - eofb_flipped[i], - eorl_flipped[i], - eoud_flipped[i], - corner_cycle[i], - coud_flipped[i], - corl_flipped[i], - cofb_flipped[i], - center_cycle[i] - }; - cube_to_arrays(c, &arrs, pf_all); - } - - if (read_mtables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); - - /* Initialize transition tables */ - for (m = 0; m < NMOVES; m++) { - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c = (Cube){ .epose = ui }; - c = apply_move_cubearray(m, c, pf_e); - epose_mtable[m][ui] = c.epose; - - c = (Cube){ .eposs = ui }; - c = apply_move_cubearray(m, c, pf_s); - eposs_mtable[m][ui] = c.eposs; - - c = (Cube){ .eposm = ui }; - c = apply_move_cubearray(m, c, pf_m); - eposm_mtable[m][ui] = c.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - c = (Cube){ .eofb = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eofb_mtable[m][ui] = c.eofb; - - c = (Cube){ .eorl = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eorl_mtable[m][ui] = c.eorl; - - c = (Cube){ .eoud = ui }; - c = apply_move_cubearray(m, c, pf_eo); - eoud_mtable[m][ui] = c.eoud; - } - for (ui = 0; ui < POW3TO7; ui++) { - c = (Cube){ .coud = ui }; - c = apply_move_cubearray(m, c, pf_co); - coud_mtable[m][ui] = c.coud; - - c = (Cube){ .corl = ui }; - c = apply_move_cubearray(m, c, pf_co); - corl_mtable[m][ui] = c.corl; - - c = (Cube){ .cofb = ui }; - c = apply_move_cubearray(m, c, pf_co); - cofb_mtable[m][ui] = c.cofb; - } - for (ui = 0; ui < FACTORIAL8; ui++) { - c = (Cube){ .cp = ui }; - c = apply_move_cubearray(m, c, pf_cp); - cp_mtable[m][ui] = c.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - c = (Cube){ .cpos = ui }; - c = apply_move_cubearray(m, c, pf_cpos); - cpos_mtable[m][ui] = c.cpos; - } - } - - if (!write_mtables_file()) - fprintf(stderr, "Error writing mtables\n"); - - for (i = 0; i < NMOVES; i++) - free_alg(equiv_alg[i]); -} - -static bool -read_mtables_file() -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - /* Table sizes, used for reading and writing files */ - uint64_t me[11] = { - [0] = FACTORIAL12/FACTORIAL8, - [1] = FACTORIAL12/FACTORIAL8, - [2] = FACTORIAL12/FACTORIAL8, - [3] = POW2TO11, - [4] = POW2TO11, - [5] = POW2TO11, - [6] = FACTORIAL8, - [7] = POW3TO7, - [8] = POW3TO7, - [9] = POW3TO7, - [10] = FACTORIAL6 - }; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -static bool -write_mtables_file() -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+20]; - int m, b = sizeof(int); - bool r = true; - - /* Table sizes, used for reading and writing files */ - uint64_t me[11] = { - [0] = FACTORIAL12/FACTORIAL8, - [1] = FACTORIAL12/FACTORIAL8, - [2] = FACTORIAL12/FACTORIAL8, - [3] = POW2TO11, - [4] = POW2TO11, - [5] = POW2TO11, - [6] = FACTORIAL8, - [7] = POW3TO7, - [8] = POW3TO7, - [9] = POW3TO7, - [10] = FACTORIAL6 - }; - - strcpy(fname, tabledir); - strcat(fname, "/mtables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NMOVES; m++) { - r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; - r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; - r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; - r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; - r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; - r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; - r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; - r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; - r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; - } - - fclose(f); - return r; -} - -bool -commute(Move m1, Move m2) -{ - static bool initialized = false; - static bool commute_aux[NMOVES][NMOVES]; - - if (!initialized) { - Cube c1, c2; - int i, j; - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute_aux[i][j] = equal(c1, c2) && i && j; - } - } - - initialized = true; - } - - return commute_aux[m1][m2]; -} - -bool -possible_next(Move m1, Move m2, Move m3) -{ - static bool initialized = false; - static bool paux[NMOVES][NMOVES][NMOVES]; - - if (!initialized) { - int i, j, k; - bool p, q, c; - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p = j && base_move(j) == base_move(k); - q = i && base_move(i) == base_move(k); - c = commute(i, j); - paux[i][j][k] = !(p || (c && q)); - } - } - } - - initialized = true; - } - - return paux[m1][m2][m3]; -} diff --git a/old/2021-11-10-beforeremovingchecker/moves.h b/old/2021-11-10-beforeremovingchecker/moves.h @@ -1,16 +0,0 @@ -#ifndef MOVES_H -#define MOVES_H - -#include "alg.h" -#include "cube.h" -#include "env.h" - -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); -bool commute(Move m1, Move m2); -bool possible_next(Move m1, Move m2, Move m3); - -void init_moves(); - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/pf.c b/old/2021-11-10-beforeremovingchecker/pf.c @@ -1,80 +0,0 @@ -#include "pf.h" - -PieceFilter -pf_all = { - .epose = true, - .eposs = true, - .eposm = true, - .eofb = true, - .eorl = true, - .eoud = true, - .cp = true, - .cofb = true, - .corl = true, - .coud = true, - .cpos = true -}; - -PieceFilter -pf_4val = { - .epose = true, - .eposs = true, - .eposm = true, - .eofb = true, - .coud = true, - .cp = true -}; - -PieceFilter -pf_epcp = { - .epose = true, - .eposs = true, - .eposm = true, - .cp = true -}; - -PieceFilter -pf_cpos = { - .cpos = true -}; - -PieceFilter -pf_cp = { - .cp = true -}; - -PieceFilter -pf_ep = { - .epose = true, - .eposs = true, - .eposm = true -}; - -PieceFilter -pf_e = { - .epose = true -}; - -PieceFilter -pf_s = { - .eposs = true -}; - -PieceFilter -pf_m = { - .eposm = true -}; - -PieceFilter -pf_eo = { - .eofb = true, - .eorl = true, - .eoud = true -}; - -PieceFilter -pf_co = { - .cofb = true, - .corl = true, - .coud = true -}; diff --git a/old/2021-11-10-beforeremovingchecker/pf.h b/old/2021-11-10-beforeremovingchecker/pf.h @@ -1,18 +0,0 @@ -#ifndef PF_H -#define PF_H - -#include "cubetypes.h" - -extern PieceFilter pf_all; -extern PieceFilter pf_4val; -extern PieceFilter pf_epcp; -extern PieceFilter pf_cpos; -extern PieceFilter pf_cp; -extern PieceFilter pf_ep; -extern PieceFilter pf_e; -extern PieceFilter pf_s; -extern PieceFilter pf_m; -extern PieceFilter pf_eo; -extern PieceFilter pf_co; - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/pruning.c b/old/2021-11-10-beforeremovingchecker/pruning.c @@ -1,272 +0,0 @@ -#include "pruning.h" - -static void genptable_bfs(PruneData *pd, int d, Move *ms); -static void genptable_branch(PruneData *pd, uint64_t i, int d, Move *m); -static void ptable_update(PruneData *pd, Cube cube, int m); -static void ptable_update_index(PruneData *pd, uint64_t ind, int m); -static int ptableval_index(PruneData *pd, uint64_t ind); -static bool read_ptable_file(PruneData *pd); -static bool write_ptable_file(PruneData *pd); - -PruneData -pd_eofb_HTM = { - .filename = "pt_eofb_HTM", - .coord = &coord_eofb, - .moveset = moveset_HTM, -}; - -PruneData -pd_coud_HTM = { - .filename = "pt_coud_HTM", - .coord = &coord_coud, - .moveset = moveset_HTM, -}; - -PruneData -pd_cornershtr_HTM = { - .filename = "pt_cornershtr_withcosets_HTM", - .coord = &coord_cornershtr, - .moveset = moveset_HTM, -}; - -PruneData -pd_corners_HTM = { - .filename = "pt_corners_HTM", - .coord = &coord_corners, - .moveset = moveset_HTM, -}; - -PruneData -pd_drud_sym16_HTM = { - .filename = "pt_drud_sym16_HTM", - .coord = &coord_drud_sym16, - .moveset = moveset_HTM, -}; - -PruneData -pd_drud_eofb = { - .filename = "pt_drud_eofb", - .coord = &coord_drud_eofb, - .moveset = moveset_eofb, -}; - -PruneData -pd_drudfin_noE_sym16_drud = { - .filename = "pt_drudfin_noE_sym16_drud", - .coord = &coord_drudfin_noE_sym16, - .moveset = moveset_drud, -}; - -PruneData -pd_htr_drud = { - .filename = "pt_htr_drud", - .coord = &coord_htr_drud, - .moveset = moveset_drud, -}; - -PruneData -pd_htrfin_htr = { - .filename = "pt_htrfin_htr", - .coord = &coord_htrfin, - .moveset = moveset_htr, -}; - -PruneData -pd_khuge_HTM = { - .filename = "pt_khuge_HTM", - .coord = &coord_khuge, - .moveset = moveset_HTM, -}; - -void -genptable(PruneData *pd) -{ - Move ms[NMOVES]; - int d; - uint64_t j, oldn; - - if (pd->generated) - return; - - /* TODO: check if memory is enough, otherwise maybe exit gracefully? */ - pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); - - if (read_ptable_file(pd)) { - pd->generated = true; - return; - } - pd->generated = true; - - fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); - - moveset_to_list(pd->moveset, ms); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->coord->max; j++) - ptable_update_index(pd, j, 15); - - for (j = 0; j < pd->coord->max; j++) - if (ptableval_index(pd, j) != 15) { - printf("Error, non-max value at index %lu!\n", j); - break; - } - printf("Table set, ready to start\n"); - - /*TODO: change, set to 0 for every solved state (might be more than 1)*/ - ptable_update(pd, (Cube){0}, 0); - pd->n = 1; - oldn = 0; - fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", - 0, pd->n - oldn, pd->n, pd->coord->max); - oldn = 1; - for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { - genptable_bfs(pd, d, ms); - fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", - d+1, pd->n - oldn, pd->n, pd->coord->max); - oldn = pd->n; - } - - if (!write_ptable_file(pd)) - fprintf(stderr, "Error writing ptable file\n"); -} - -static void -genptable_bfs(PruneData *pd, int d, Move *ms) -{ - uint64_t i; - - for (i = 0; i < pd->coord->max; i++) - if (ptableval_index(pd, i) == d) - genptable_branch(pd, i, d, ms); -} - -static void -genptable_branch(PruneData *pd, uint64_t ind, int d, Move *ms) -{ - int i, j; - Cube ci, cc, c; - - /* - * This is the only line of the whole program where we REALLY need an - * anti-indexer function. We could get rid of it if only we could save - * a cube object for each index value as we go, but then we would need - * an incredible amount of memory to generate each ptable: assuming - * fields in struct cube are 32 bit ints that would take 88 times the - * memory of the table to be generated, more than 120Gb for - * ptable_khuge for example! - */ - ci = pd->coord->cube(ind); - - for (i = 0; i < pd->coord->ntrans; i++) { - /* For simplicity trans[] is NULL when ntrans = 1 */ - c = i == 0 ? ci : - apply_trans(pd->coord->trans[i], ci); - for (j = 0; ms[j] != NULLMOVE; j++) { - cc = apply_move(ms[j], c); - if (ptableval(pd, cc) > d+1) - ptable_update(pd, cc, d+1); - } - } -} - -void -print_ptable(PruneData *pd) -{ - uint64_t i, a[16]; - - for (i = 0; i < 16; i++) - a[i] = 0; - - if (!pd->generated) - genptable(pd); - - for (i = 0; i < pd->coord->max; i++) - a[ptableval_index(pd, i)]++; - - fprintf(stderr, "Values for table %s\n", pd->filename); - for (i = 0; i < 16; i++) - printf("%2lu\t%10lu\n", i, a[i]); -} - -uint64_t -ptablesize(PruneData *pd) -{ - return (pd->coord->max + 1) / 2; -} - -static void -ptable_update(PruneData *pd, Cube cube, int n) -{ - uint64_t ind = pd->coord->index(cube); - ptable_update_index(pd, ind, n); -} - -static void -ptable_update_index(PruneData *pd, uint64_t ind, int n) -{ - uint8_t oldval2 = pd->ptable[ind/2]; - int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; - - pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; - pd->n++; -} - -int -ptableval(PruneData *pd, Cube cube) -{ - return ptableval_index(pd, pd->coord->index(cube)); -} - -static int -ptableval_index(PruneData *pd, uint64_t ind) -{ - if (!pd->generated) - genptable(pd); - - return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; -} - -static bool -read_ptable_file(PruneData *pd) -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t r; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return r == ptablesize(pd); -} - -static bool -write_ptable_file(PruneData *pd) -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t written; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, pd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); - fclose(f); - - return written == ptablesize(pd); -} - diff --git a/old/2021-11-10-beforeremovingchecker/pruning.h b/old/2021-11-10-beforeremovingchecker/pruning.h @@ -1,23 +0,0 @@ -#ifndef PRUNING_H -#define PRUNING_H - -#include "symcoord.h" - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_cornershtr_HTM; -extern PruneData pd_drud_sym16_HTM; -extern PruneData pd_drud_eofb; -extern PruneData pd_drudfin_noE_sym16_drud; -extern PruneData pd_htr_drud; -extern PruneData pd_htrfin_htr; -extern PruneData pd_khuge_HTM; - -void genptable(PruneData *pd); -void print_ptable(PruneData *pd); -uint64_t ptablesize(PruneData *pd); -int ptableval(PruneData *pd, Cube cube); - -#endif - diff --git a/old/2021-11-10-beforeremovingchecker/shell.c b/old/2021-11-10-beforeremovingchecker/shell.c @@ -1,99 +0,0 @@ -#include "shell.h" - -static void cleanwhitespaces(char *line); -static int parseline(char *line, char **v); - -static void -cleanwhitespaces(char *line) -{ - char *i; - - for (i = line; *i != 0; i++) - if (*i == '\t' || *i == '\n') - *i = ' '; -} - -/* This function assumes that **v is large enough */ -static int -parseline(char *line, char **v) -{ - char *t; - int n = 0; - - cleanwhitespaces(line); - - for (t = strtok(line, " "); t != NULL; t = strtok(NULL, " ")) - strcpy(v[n++], t); - - return n; -} - -void -exec_args(int c, char **v) -{ - int i; - Command *cmd = NULL; - CommandArgs *args; - - for (i = 0; i < NCOMMANDS; i++) - if (commands[i] != NULL && !strcmp(v[0], commands[i]->name)) - cmd = commands[i]; - - if (cmd == NULL) { - fprintf(stderr, "%s: command not found\n", v[0]); - return; - } - - args = cmd->parse_args(c-1, &v[1]); - if (!args->success) { - fprintf(stderr, "usage: %s\n", cmd->usage); - return; - } - - cmd->exec(args); - free_args(args); -} - -void -launch() -{ - int i, shell_argc; - char line[MAXLINELEN], **shell_argv; - - shell_argv = malloc(MAXNTOKENS * sizeof(char *)); - for (i = 0; i < MAXNTOKENS; i++) - shell_argv[i] = malloc((MAXTOKENLEN+1) * sizeof(char)); - - fprintf(stderr, "Welcome to Nissy 2.0 (demo version).\n"); - fprintf(stderr, "Limited commands available. "); - fprintf(stderr, "Type 'help' for a list.\n"); - - while (true) { - fprintf(stderr, "nissy-# "); - if (fgets(line, MAXLINELEN, stdin) == NULL) - break; - shell_argc = parseline(line, shell_argv); - exec_args(shell_argc, shell_argv); - } - - for (i = 0; i < MAXNTOKENS; i++) - free(shell_argv[i]); - free(shell_argv); -} - -/* We will have our main() here, for now */ -int -main(int argc, char *argv[]) -{ - init_moves(); - init_trans(); - init_coord(); - init_symcoord(); - - if (argc > 1) - exec_args(argc-1, &argv[1]); - else - launch(); - - return 0; -} diff --git a/old/2021-11-10-beforeremovingchecker/shell.h b/old/2021-11-10-beforeremovingchecker/shell.h @@ -1,13 +0,0 @@ -#ifndef SHELL_H -#define SHELL_H - -#include "commands.h" - -#define MAXLINELEN 10000 -#define MAXTOKENLEN 255 -#define MAXNTOKENS 255 - -void exec_args(int c, char **v); -void launch(); - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/solve.c b/old/2021-11-10-beforeremovingchecker/solve.c @@ -1,209 +0,0 @@ -#include "solve.h" - -/* Local functions ***********************************************************/ - -static bool allowed_next(Move move, DfsData *dd); -static void dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd); -static void dfs_branch(Cube c, Step *s, SolveOptions *os, DfsData *dd); -static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd); -static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd); -static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd); - -/* Local functions ***********************************************************/ - -static bool -allowed_next(Move move, DfsData *dd) -{ - -/* TODO: remove the commented part, was added to moves.c - static bool initialized = false; - static bool commute[NMOVES][NMOVES], pnext[NMOVES][NMOVES][NMOVES]; - - if (!initialized) { - Cube c1, c2; - int i, j, k; - bool p1, p2, cij; - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute[i][j] = equal(c1, c2) && i && j; - for (k = 0; k < NMOVES; k++) { - p1 = j && base_move(j) == base_move(k); - p2 = i && base_move(i) == base_move(k); - cij = commute[i][j]; - pnext[i][j][k] = !(p1 || (cij && p2)); - } - } - } - - initialized = true; - } - - if (!pnext[dd->last2][dd->last1][move]) - return false; - - if (commute[dd->last1][move]) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -*/ - - if (!possible_next(dd->last2, dd->last1, move)) - return false; - - if (commute(dd->last1, move)) - return dd->move_position[dd->last1] < dd->move_position[move]; - - return true; -} - -static void -dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd) -{ - if (dfs_stop(c, s, opts, dd)) - return; - - if (dfs_check_solved(s, opts, dd)) - return; - - dfs_branch(c, s, opts, dd); - - if (opts->can_niss && !dd->niss) - dfs_niss(c, s, opts, dd); -} - -static void -dfs_branch(Cube c, Step *s, SolveOptions *opts, DfsData *dd) -{ - Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; - - int i, maxnsol = opts->max_solutions; - - for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { - m = moves[i]; - if (allowed_next(m, dd)) { - dd->last2 = dd->last1; - dd->last1 = m; - append_move(dd->current_alg, m, dd->niss); - - dfs(apply_move(m, c), s, opts, dd); - - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - } - } -} - -static bool -dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd) -{ - if (dd->lb != 0) - return false; - - if (dd->current_alg->len == dd->d) { - if (s->is_valid(dd->current_alg) || opts->all) - append_alg(dd->sols, dd->current_alg); - - if (opts->feedback) - print_alg(dd->current_alg, false); - } - - return true; -} - -static void -dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd) -{ - Move l1 = dd->last1, l2 = dd->last2; - CubeTarget ct; - - ct.cube = apply_move(inverse_move(l1), (Cube){0}); - ct.target = 1; - - if (dd->current_alg->len == 0 || s->estimate(ct)) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; - - dfs(inverse_cube(c), s, opts, dd); - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = false; - } -} - -static bool -dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) -{ - CubeTarget ct = { - .cube = c, - .target = dd->d - dd->current_alg->len - }; - - if (dd->sols->len >= opts->max_solutions) - return true; - - dd->lb = s->estimate(ct); - if (opts->can_niss && !dd->niss) - dd->lb = MIN(1, dd->lb); - - if (dd->current_alg->len + dd->lb > dd->d) - return true; - - return false; -} - -/* Public functions **********************************************************/ - -AlgList * -solve(Cube cube, Step *step, SolveOptions *opts) -{ - AlgListNode *node; - AlgList *sols = new_alglist(); - Cube c; - - if (step->detect != NULL) - step->pre_trans = step->detect(cube); - c = apply_trans(step->pre_trans, cube); - - DfsData dd = { - .m = 0, - .niss = false, - .lb = -1, - .last1 = NULLMOVE, - .last2 = NULLMOVE, - .sols = sols, - .current_alg = new_alg("") - }; - - if (step->ready != NULL && !step->ready(c)) { - fprintf(stderr, "Cube not ready for solving step: "); - fprintf(stderr, "%s\n", step->ready_msg); - return sols; - } - - moveset_to_list(step->moveset, dd.sorted_moves); - movelist_to_position(dd.sorted_moves, dd.move_position); - - for (dd.d = opts->min_moves; - dd.d <= opts->max_moves && - !(sols->len && opts->optimal_only) && - sols->len < opts->max_solutions; - dd.d++) { - if (opts->feedback) - fprintf(stderr, - "Found %d solutions, searching depth %d...\n", - sols->len, dd.d); - dfs(c, step, opts, &dd); - } - - for (node = sols->first; node != NULL; node = node->next) - transform_alg(inverse_trans(step->pre_trans), node->alg); - - free_alg(dd.current_alg); - return sols; -} diff --git a/old/2021-11-10-beforeremovingchecker/solve.h b/old/2021-11-10-beforeremovingchecker/solve.h @@ -1,9 +0,0 @@ -#ifndef SOLVE_H -#define SOLVE_H - -#include "moves.h" -#include "trans.h" - -AlgList * solve(Cube cube, Step *step, SolveOptions *opts); - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/steps.c b/old/2021-11-10-beforeremovingchecker/steps.c @@ -1,916 +0,0 @@ -#include "steps.h" - -/* Standard checkers (return lower bound) ************************************/ - -static int estimate_eoany_HTM(CubeTarget ct); -static int estimate_eofb_HTM(CubeTarget ct); -static int estimate_coany_HTM(CubeTarget ct); -static int estimate_coud_HTM(CubeTarget ct); -static int estimate_coany_URF(CubeTarget ct); -static int estimate_coud_URF(CubeTarget ct); -static int estimate_corners_HTM(CubeTarget ct); -static int estimate_cornershtr_HTM(CubeTarget ct); -static int estimate_corners_URF(CubeTarget ct); -static int estimate_cornershtr_URF(CubeTarget ct); -static int estimate_drany_HTM(CubeTarget ct); -static int estimate_drud_HTM(CubeTarget ct); -static int estimate_drud_eofb(CubeTarget ct); -static int estimate_dr_eofb(CubeTarget ct); -static int estimate_drudfin_drud(CubeTarget ct); -static int estimate_htr_drud(CubeTarget ct); -static int estimate_htrfin_htr(CubeTarget ct); -static int estimate_optimal_HTM(CubeTarget ct); - -/* Validators ****************************************************************/ - -static bool always_valid(Alg *alg); -static bool validate_singlecw_ending(Alg *alg); - -/* Pre-transformation detectors **********************************************/ - -static Trans detect_pretrans_eofb(Cube cube); -static Trans detect_pretrans_drud(Cube cube); - -/* Messages for when cube is not ready ***************************************/ - -static char check_centers_msg[100] = "cube must be oriented (centers solved)"; -static char check_eo_msg[100] = "EO must be solved on given axis"; -static char check_dr_msg[100] = "DR must be solved on given axis"; -static char check_htr_msg[100] = "HTR must be solved"; -static char check_drany_msg[100] = "DR must be solved on at least one axis"; - -/* Steps *********************************************************************/ - -Step -optimal_HTM = { - .shortname = "optimal", - .name = "Optimal solve (in HTM)", - - .estimate = estimate_optimal_HTM, - .ready = check_centers, - .ready_msg = check_centers_msg, - .is_valid = always_valid, - .moveset = moveset_HTM, - - .pre_trans = uf, -}; - -/* EO steps **************************/ -Step -eoany_HTM = { - .shortname = "eo", - .name = "EO on any axis", - - .estimate = estimate_eoany_HTM, - .ready = check_centers, - .ready_msg = check_centers_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = uf, -}; - -Step -eofb_HTM = { - .shortname = "eofb", - .name = "EO on F/B", - - .estimate = estimate_eofb_HTM, - .ready = check_centers, - .ready_msg = check_centers_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = uf, -}; - -Step -eorl_HTM = { - .shortname = "eorl", - .name = "EO on R/L", - - .estimate = estimate_eofb_HTM, - .ready = check_centers, - .ready_msg = check_centers_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = ur, -}; - -Step -eoud_HTM = { - .shortname = "eoud", - .name = "EO on U/D", - - .estimate = estimate_eofb_HTM, - .ready = check_centers, - .ready_msg = check_centers_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = fd, -}; - -/* CO steps **************************/ -Step -coany_HTM = { - .shortname = "co", - .name = "CO on any axis", - - .estimate = estimate_coany_HTM, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = uf, -}; - -Step -coud_HTM = { - .shortname = "coud", - .name = "CO on U/D", - - .estimate = estimate_coud_HTM, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = uf, -}; - -Step -corl_HTM = { - .shortname = "corl", - .name = "CO on R/L", - - .estimate = estimate_coud_HTM, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = rf, -}; - -Step -cofb_HTM = { - .shortname = "cofb", - .name = "CO on F/B", - - .estimate = estimate_coud_HTM, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = fd, -}; - -Step -coany_URF = { - .shortname = "co-URF", - .name = "CO any axis (URF moveset)", - - .estimate = estimate_coany_URF, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, - - .pre_trans = uf, -}; - -Step -coud_URF = { - .shortname = "coud-URF", - .name = "CO on U/D (URF moveset)", - - .estimate = estimate_coud_URF, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, - - .pre_trans = uf, -}; - -Step -corl_URF = { - .shortname = "corl-URF", - .name = "CO on R/L (URF moveset)", - - .estimate = estimate_coud_URF, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, - - .pre_trans = rf, -}; - -Step -cofb_URF = { - .shortname = "cofb-URF", - .name = "CO on F/B (URF moveset)", - - .estimate = estimate_coud_URF, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, - - .pre_trans = fd, -}; - -/* Misc corner steps *****************/ -Step -cornershtr_HTM = { - .shortname = "chtr", - .name = "Solve corners to HTR state", - - .estimate = estimate_cornershtr_HTM, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = uf, -}; - -Step -cornershtr_URF = { - .shortname = "chtr-URF", - .name = "Solve corners to HTR state (URF moveset)", - - .estimate = estimate_cornershtr_URF, - .ready = NULL, - .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, - - .pre_trans = uf, -}; - -Step -corners_HTM = { - .shortname = "corners", - .name = "Solve corners", - - .estimate = estimate_corners_HTM, - .ready = NULL, - .is_valid = always_valid, - .moveset = moveset_HTM, - - .pre_trans = uf, -}; - -Step -corners_URF = { - .shortname = "corners-URF", - .name = "Solve corners (URF moveset)", - - .estimate = estimate_corners_URF, - .ready = NULL, - .is_valid = always_valid, - .moveset = moveset_URF, - - .pre_trans = uf, -}; - -/* DR steps **************************/ -Step -drany_HTM = { - .shortname = "dr", - .name = "DR on any axis", - - .estimate = estimate_drany_HTM, - .ready = check_centers, - .ready_msg = check_centers_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = uf, -}; - -Step -drud_HTM = { - .shortname = "drud", - .name = "DR on U/D", - - .estimate = estimate_drud_HTM, - .ready = check_centers, - .ready_msg = check_centers_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = uf, -}; - -Step -drrl_HTM = { - .shortname = "drrl", - .name = "DR on R/L", - - .estimate = estimate_drud_HTM, - .ready = check_centers, - .ready_msg = check_centers_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = rf, -}; - -Step -drfb_HTM = { - .shortname = "drfb", - .name = "DR on F/B", - - .estimate = estimate_drud_HTM, - .ready = check_centers, - .ready_msg = check_centers_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, - - .pre_trans = fd, -}; - -/* DR from EO */ -Step -dr_eo = { - .shortname = "dr-eo", - .name = "DR without breaking EO (automatically detected)", - - .estimate = estimate_dr_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .detect = detect_pretrans_eofb, -}; - -Step -dr_eofb = { - .shortname = "dr-eofb", - .name = "DR on U/D or R/L without breaking EO on F/B", - - .estimate = estimate_dr_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .pre_trans = uf, -}; - -Step -dr_eorl = { - .shortname = "dr-eorl", - .name = "DR on U/D or F/B without breaking EO on R/L", - - .estimate = estimate_dr_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .pre_trans = ur, -}; - -Step -dr_eoud = { - .shortname = "dr-eoud", - .name = "DR on R/L or F/B without breaking EO on U/R", - - .estimate = estimate_dr_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .pre_trans = fd, -}; - -Step -drud_eofb = { - .shortname = "drud-eofb", - .name = "DR on U/D without breaking EO on F/B", - - .estimate = estimate_drud_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .pre_trans = uf, -}; - -Step -drrl_eofb = { - .shortname = "drrl-eofb", - .name = "DR on R/L without breaking EO on F/B", - - .estimate = estimate_drud_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .pre_trans = rf, -}; - -Step -drud_eorl = { - .shortname = "drud-eorl", - .name = "DR on U/D without breaking EO on R/L", - - .estimate = estimate_drud_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .pre_trans = ur, -}; - -Step -drfb_eorl = { - .shortname = "drfb-eorl", - .name = "DR on F/B without breaking EO on R/L", - - .estimate = estimate_drud_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .pre_trans = fr, -}; - -Step -drfb_eoud = { - .shortname = "drfb-eoud", - .name = "DR on F/B without breaking EO on U/D", - - .estimate = estimate_drud_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .pre_trans = fd, -}; - -Step -drrl_eoud = { - .shortname = "drrl-eoud", - .name = "DR on R/L without breaking EO on U/D", - - .estimate = estimate_drud_eofb, - .ready = check_eofb, - .ready_msg = check_eo_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, - - .pre_trans = rd, -}; - -/* DR finish steps */ -Step -dranyfin_DR = { - .shortname = "drfin", - .name = "DR finish on any axis without breaking DR", - - .estimate = estimate_drudfin_drud, - .ready = check_drud, - .ready_msg = check_drany_msg, - .is_valid = always_valid, - .moveset = moveset_drud, - - .detect = detect_pretrans_drud, -}; - -Step -drudfin_drud = { - .shortname = "drudfin", - .name = "DR finish on U/D without breaking DR", - - .estimate = estimate_drudfin_drud, - .ready = check_drud, - .ready_msg = check_dr_msg, - .is_valid = always_valid, - .moveset = moveset_drud, - - .pre_trans = uf, -}; - -Step -drrlfin_drrl = { - .shortname = "drrlfin", - .name = "DR finish on R/L without breaking DR", - - .estimate = estimate_drudfin_drud, - .ready = check_drud, - .ready_msg = check_dr_msg, - .is_valid = always_valid, - .moveset = moveset_drud, - - .pre_trans = rf, -}; - -Step -drfbfin_drfb = { - .shortname = "drfbfin", - .name = "DR finish on F/B without breaking DR", - - .estimate = estimate_drudfin_drud, - .ready = check_drud, - .ready_msg = check_dr_msg, - .is_valid = always_valid, - .moveset = moveset_drud, - - .pre_trans = fd, -}; - -/* HTR from DR */ -Step -htr_any = { - .shortname = "htr", - .name = "HTR from DR", - - .estimate = estimate_htr_drud, - .ready = check_drud, - .ready_msg = check_drany_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_drud, - - .detect = detect_pretrans_drud, -}; - -Step -htr_drud = { - .shortname = "htr-drud", - .name = "HTR from DR on U/D", - - .estimate = estimate_htr_drud, - .ready = check_drud, - .ready_msg = check_dr_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_drud, - - .pre_trans = uf, -}; - -Step -htr_drrl = { - .shortname = "htr-drrl", - .name = "HTR from DR on R/L", - - .estimate = estimate_htr_drud, - .ready = check_drud, - .ready_msg = check_dr_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_drud, - - .pre_trans = rf, -}; - -Step -htr_drfb = { - .shortname = "htr-drfb", - .name = "HTR from DR on F/B", - - .estimate = estimate_htr_drud, - .ready = check_drud, - .ready_msg = check_dr_msg, - .is_valid = validate_singlecw_ending, - .moveset = moveset_drud, - - .pre_trans = fd, -}; - -/* HTR finish */ -Step -htrfin_htr = { - .shortname = "htrfin", - .name = "HTR finish without breaking HTR", - - .estimate = estimate_htrfin_htr, - .ready = check_htr, - .ready_msg = check_htr_msg, - .is_valid = always_valid, - .moveset = moveset_htr, - - .pre_trans = uf, -}; - -Step *steps[NSTEPS] = { - &optimal_HTM, /* first is default */ - - &eoany_HTM, - &eofb_HTM, - &eorl_HTM, - &eoud_HTM, - - &coany_HTM, - &coud_HTM, - &corl_HTM, - &cofb_HTM, - - &coany_URF, - &coud_URF, - &corl_URF, - &cofb_URF, - - &drany_HTM, - &drud_HTM, - &drrl_HTM, - &drfb_HTM, - - &dr_eo, - &dr_eofb, - &dr_eorl, - &dr_eoud, - &drud_eofb, - &drrl_eofb, - &drud_eorl, - &drfb_eorl, - &drfb_eoud, - &drrl_eoud, - - &dranyfin_DR, - &drudfin_drud, - &drrlfin_drrl, - &drfbfin_drfb, - - &htr_any, - &htr_drud, - &htr_drrl, - &htr_drfb, - - &htrfin_htr, - - &cornershtr_HTM, - &cornershtr_URF, - &corners_HTM, - &corners_URF, -}; - -/* Standard checkers (return lower bound) ************************************/ - -static int -estimate_eoany_HTM(CubeTarget ct) -{ - int r1, r2, r3; - - r1 = ptableval(&pd_eofb_HTM, ct.cube); - r2 = ptableval(&pd_eofb_HTM, apply_trans(ur, ct.cube)); - r3 = ptableval(&pd_eofb_HTM, apply_trans(fd, ct.cube)); - - return MIN(r1, MIN(r2, r3)); -} - -static int -estimate_eofb_HTM(CubeTarget ct) -{ - return ptableval(&pd_eofb_HTM, ct.cube); -} - -static int -estimate_coany_HTM(CubeTarget ct) -{ - int r1, r2, r3; - - r1 = ptableval(&pd_coud_HTM, ct.cube); - r2 = ptableval(&pd_coud_HTM, apply_trans(rf, ct.cube)); - r3 = ptableval(&pd_coud_HTM, apply_trans(fd, ct.cube)); - - return MIN(r1, MIN(r2, r3)); -} - -static int -estimate_coud_HTM(CubeTarget ct) -{ - return ptableval(&pd_coud_HTM, ct.cube); -} - -static int -estimate_coany_URF(CubeTarget ct) -{ - int r1, r2, r3; - CubeTarget ct2, ct3; - - ct2.cube = apply_trans(rf, ct.cube); - ct2.target = ct.target; - - ct3.cube = apply_trans(fd, ct.cube); - ct3.target = ct.target; - - r1 = estimate_coud_URF(ct); - r2 = estimate_coud_URF(ct2); - r3 = estimate_coud_URF(ct3); - - return MIN(r1, MIN(r2, r3)); -} - -static int -estimate_coud_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; - CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; - - int ud = estimate_coud_HTM(ct); - int rl = estimate_coud_HTM(ct2); - int fb = estimate_coud_HTM(ct3); - - return MIN(ud, MIN(rl, fb)); -} - -static int -estimate_corners_HTM(CubeTarget ct) -{ - return ptableval(&pd_corners_HTM, ct.cube); -} - -static int -estimate_cornershtr_HTM(CubeTarget ct) -{ - return ptableval(&pd_cornershtr_HTM, ct.cube); -} - -static int -estimate_cornershtr_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_cornershtr_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_corners_URF(CubeTarget ct) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int c, ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - ct.cube = apply_alg(rotation_alg(i), ct.cube); - c = estimate_corners_HTM(ct); - ret = MIN(ret, c); - } - - return ret; -} - -static int -estimate_drany_HTM(CubeTarget ct) -{ - int r1, r2, r3; - - r1 = ptableval(&pd_drud_sym16_HTM, ct.cube); - r2 = ptableval(&pd_drud_sym16_HTM, apply_trans(rf, ct.cube)); - r3 = ptableval(&pd_drud_sym16_HTM, apply_trans(fd, ct.cube)); - - return MIN(r1, MIN(r2, r3)); -} - -static int -estimate_drud_HTM(CubeTarget ct) -{ - return ptableval(&pd_drud_sym16_HTM, ct.cube); -} - -static int -estimate_drud_eofb(CubeTarget ct) -{ - return ptableval(&pd_drud_eofb, ct.cube); -} - -static int -estimate_dr_eofb(CubeTarget ct) -{ - int r1, r2; - - r1 = ptableval(&pd_drud_eofb, ct.cube); - r2 = ptableval(&pd_drud_eofb, apply_trans(rf, ct.cube)); - - return MIN(r1, r2); -} - -static int -estimate_drudfin_drud(CubeTarget ct) -{ - int val = ptableval(&pd_drudfin_noE_sym16_drud, ct.cube); - - if (val != 0) - return val; - - return ct.cube.epose % 24 == 0 ? 0 : 1; -} - -static int -estimate_htr_drud(CubeTarget ct) -{ - return ptableval(&pd_htr_drud, ct.cube); -} - -static int -estimate_htrfin_htr(CubeTarget ct) -{ - return ptableval(&pd_htrfin_htr, ct.cube); -} - -static int -estimate_optimal_HTM(CubeTarget ct) -{ - int dr1, dr2, dr3, cor, ret; - Cube cube = ct.cube; - - dr1 = ptableval(&pd_khuge_HTM, cube); - cor = estimate_corners_HTM(ct); - ret = MAX(dr1, cor); - - if (ret > ct.target) - return ret; - - cube = apply_trans(rf, ct.cube); - dr2 = ptableval(&pd_khuge_HTM, cube); - ret = MAX(ret, dr2); - - if (ret > ct.target) - return ret; - - cube = apply_trans(fd, ct.cube); - dr3 = ptableval(&pd_khuge_HTM, cube); - - /* Michiel de Bondt's trick */ - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - dr3++; - - return MAX(ret, dr3); -} - -/* Validators ****************************************************************/ - -static bool -always_valid(Alg *alg) -{ - return true; -} - -static bool -validate_singlecw_ending(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; -} - -/* Pre-transformation detectors **********************************************/ - -static Trans -detect_pretrans_eofb(Cube cube) -{ - Trans i; - - for (i = 0; i < NROTATIONS; i++) - if (check_eofb(apply_trans(i, cube))) - return i; - - return 0; -} - -static Trans -detect_pretrans_drud(Cube cube) -{ - Trans i; - - for (i = 0; i < NROTATIONS; i++) - if (check_drud(apply_trans(i, cube))) - return i; - - return 0; -} diff --git a/old/2021-11-10-beforeremovingchecker/steps.h b/old/2021-11-10-beforeremovingchecker/steps.h @@ -1,10 +0,0 @@ -#ifndef STEPS_H -#define STEPS_H - -#include "pruning.h" - -#define NSTEPS 50 - -extern Step * steps[NSTEPS]; - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/symcoord.c b/old/2021-11-10-beforeremovingchecker/symcoord.c @@ -1,359 +0,0 @@ -#include "symcoord.h" - -static Cube antindex_coud_sym16(uint64_t ind); -static Cube antindex_cp_sym16(uint64_t ind); -static Cube antindex_eofbepos_sym16(uint64_t ind); -static Cube antindex_drud_sym16(uint64_t ind); -static Cube antindex_drudfin_noE_sym16(uint64_t ind); -static Cube antindex_khuge(uint64_t ind); - -static uint64_t index_coud_sym16(Cube cube); -static uint64_t index_cp_sym16(Cube cube); -static uint64_t index_eofbepos_sym16(Cube cube); -static uint64_t index_drud_sym16(Cube cube); -static uint64_t index_drudfin_noE_sym16(Cube cube); -static uint64_t index_khuge(Cube cube); - -static void gensym(SymData *sd); -static bool read_symdata_file(SymData *sd); -static bool write_symdata_file(SymData *sd); - -/* Transformation groups and symmetry data ***********************************/ - -static Trans -trans_group_udfix[16] = { - uf, ur, ub, ul, - df, dr, db, dl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, -}; - -static SymData -sd_coud_16 = { - .filename = "sd_coud_16", - .coord = &coord_coud, - .sym_coord = &coord_coud_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static SymData -sd_cp_16 = { - .filename = "sd_cp_16", - .coord = &coord_cp, - .sym_coord = &coord_cp_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static SymData -sd_eofbepos_16 = { - .filename = "sd_eofbepos_16", - .coord = &coord_eofbepos, - .sym_coord = &coord_eofbepos_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static int nsymdata = 3; -static SymData * all_sd[] = { - &sd_coud_16, - &sd_cp_16, - &sd_eofbepos_16, -}; - - -/* Coordinates and their implementation **************************************/ - -Coordinate -coord_eofbepos_sym16 = { - .index = index_eofbepos_sym16, - .cube = antindex_eofbepos_sym16, - .check = check_eofbepos, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_coud_sym16 = { - .index = index_coud_sym16, - .cube = antindex_coud_sym16, - .check = check_coud, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_cp_sym16 = { - .index = index_cp_sym16, - .cube = antindex_cp_sym16, - .check = check_cp, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_drud_sym16 = { - .index = index_drud_sym16, - .cube = antindex_drud_sym16, - .check = check_drud, - .max = POW3TO7 * 64430, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_drudfin_noE_sym16 = { - .index = index_drudfin_noE_sym16, - .cube = antindex_drudfin_noE_sym16, - .check = check_drudfin_noE, - .max = FACTORIAL8 * 2768, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_khuge = { - .index = index_khuge, - .cube = antindex_khuge, - .check = check_khuge, - .max = POW3TO7 * FACTORIAL4 * 64430, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -/* Functions *****************************************************************/ - -static Cube -antindex_coud_sym16(uint64_t ind) -{ - return sd_coud_16.rep[ind]; -} - -static Cube -antindex_cp_sym16(uint64_t ind) -{ - return sd_cp_16.rep[ind]; -} - -static Cube -antindex_eofbepos_sym16(uint64_t ind) -{ - return sd_eofbepos_16.rep[ind]; -} - -static Cube -antindex_drud_sym16(uint64_t ind) -{ - Cube c; - - c = antindex_eofbepos_sym16(ind/POW3TO7); - c.coud = ind % POW3TO7; - c.cofb = c.coud; - c.corl = c.coud; - - return c; -} - -static Cube -antindex_drudfin_noE_sym16(uint64_t ind) -{ - Cube c1, c2; - - c1 = coord_epud.cube(ind % FACTORIAL8); - c2 = antindex_cp_sym16(ind/FACTORIAL8); - c1.cp = c2.cp; - - return c1; -} - -static Cube -antindex_khuge(uint64_t ind) -{ - Cube c; - - c = antindex_eofbepos_sym16(ind/(FACTORIAL4*POW3TO7)); - c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); - c.coud = ind % POW3TO7; - - return c; -} - -static uint64_t -index_coud_sym16(Cube cube) -{ - return sd_coud_16.class[coord_coud.index(cube)]; -} - -static uint64_t -index_cp_sym16(Cube cube) -{ - return sd_cp_16.class[coord_cp.index(cube)]; -} - -static uint64_t -index_drud_sym16(Cube cube) -{ - Trans t; - Cube c; - - t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)]; - c = apply_trans(t, cube); - - return index_eofbepos_sym16(c) * POW3TO7 + c.coud; -} - -static uint64_t -index_drudfin_noE_sym16(Cube cube) -{ - Trans t; - Cube c; - - t = sd_cp_16.transtorep[coord_cp.index(cube)]; - c = apply_trans(t, cube); - - return index_cp_sym16(c) * FACTORIAL8 + coord_epud.index(c); -} - -static uint64_t -index_eofbepos_sym16(Cube cube) -{ - return sd_eofbepos_16.class[coord_eofbepos.index(cube)]; -} - -static uint64_t -index_khuge(Cube cube) -{ - Trans t; - Cube c; - uint64_t a; - - t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)]; - c = apply_trans(t, cube); - a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); - - return a * POW3TO7 + c.coud; -} - -/* Other functions ***********************************************************/ - -static void -gensym(SymData *sd) -{ - uint64_t i, in, nreps = 0; - int j; - Cube c, d; - - if (sd->generated) - return; - - sd->class = malloc(sd->coord->max * sizeof(uint64_t)); - sd->rep = malloc(sd->coord->max * sizeof(Cube)); - sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); - - if (read_symdata_file(sd)) { - sd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); - - for (i = 0; i < sd->coord->max; i++) - sd->class[i] = sd->coord->max + 1; - - for (i = 0; i < sd->coord->max; i++) { - if (sd->class[i] == sd->coord->max + 1) { - c = sd->coord->cube(i); - sd->rep[nreps] = c; - for (j = 0; j < sd->ntrans; j++) { - d = apply_trans(sd->trans[j], c); - in = sd->coord->index(d); - - if (sd->class[in] == sd->coord->max + 1) { - sd->class[in] = nreps; - sd->transtorep[in] = - inverse_trans(sd->trans[j]); - } - } - nreps++; - } - } - - sd->sym_coord->max = nreps; - sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); - sd->generated = true; - - fprintf(stderr, "Found %lu classes\n", nreps); - - if (!write_symdata_file(sd)) - fprintf(stderr, "Error writing SymData file\n"); - - return; -} - -static bool -read_symdata_file(SymData *sd) -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -write_symdata_file(SymData *sd) -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -void -init_symcoord() -{ - int i; - - static bool initialized = false; - if (initialized) - return; - initialized = true; - - for (i = 0; i < nsymdata; i++) - gensym(all_sd[i]); -} - diff --git a/old/2021-11-10-beforeremovingchecker/symcoord.h b/old/2021-11-10-beforeremovingchecker/symcoord.h @@ -1,15 +0,0 @@ -#ifndef SYMCOORD_H -#define SYMCOORD_H - -#include "coord.h" - -extern Coordinate coord_coud_sym16; -extern Coordinate coord_cp_sym16; -extern Coordinate coord_eofbepos_sym16; -extern Coordinate coord_drud_sym16; -extern Coordinate coord_drudfin_noE_sym16; -extern Coordinate coord_khuge; - -void init_symcoord(); - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/trans.c b/old/2021-11-10-beforeremovingchecker/trans.c @@ -1,372 +0,0 @@ -#include "trans.h" - -/* Local functions ***********************************************************/ - -static bool read_ttables_file(); -static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); -static bool write_ttables_file(); - -/* Tables and other data *****************************************************/ - -static int ep_mirror[12] = { - [UF] = UF, [UL] = UR, [UB] = UB, [UR] = UL, - [DF] = DF, [DL] = DR, [DB] = DB, [DR] = DL, - [FR] = FL, [FL] = FR, [BL] = BR, [BR] = BL -}; - -static int cp_mirror[8] = { - [UFR] = UFL, [UFL] = UFR, [UBL] = UBR, [UBR] = UBL, - [DFR] = DFL, [DFL] = DFR, [DBL] = DBR, [DBR] = DBL -}; - -static int cpos_mirror[6] = { - [U_center] = U_center, [D_center] = D_center, - [R_center] = L_center, [L_center] = R_center, - [F_center] = F_center, [B_center] = B_center -}; - -/* TODO Is there a more elegant way? */ -static char rotation_alg_string[100][NROTATIONS] = { - [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", -}; - -static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ -static int eposs_source[NTRANS]; -static int eposm_source[NTRANS]; -static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ -static int eorl_source[NTRANS]; -static int eoud_source[NTRANS]; -static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ -static int cofb_source[NTRANS]; -static int corl_source[NTRANS]; - -static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; -static int eo_ttable[NTRANS][POW2TO11]; -static int cp_ttable[NTRANS][FACTORIAL8]; -static int co_ttable[NTRANS][POW3TO7]; -static int cpos_ttable[NTRANS][FACTORIAL6]; -static Move moves_ttable[NTRANS][NMOVES]; - -/* Local functions implementation ********************************************/ - -void -init_trans() { - static bool initialized = false; - if (initialized) - return; - initialized = true; - - Cube aux, cube, c[3]; - CubeArray epcp; - int i, eparr[12], eoarr[12], cparr[8], coarr[8]; - unsigned int ui; - Move mi, move; - Trans m; - - /* Compute sources */ - for (i = 0; i < NTRANS; i++) { - cube = apply_alg(rotation_alg(i), (Cube){0}); - - epose_source[i] = edge_slice(what_edge_at(cube, FR)); - eposs_source[i] = edge_slice(what_edge_at(cube, UR)); - eposm_source[i] = edge_slice(what_edge_at(cube, UF)); - eofb_source[i] = what_center_at(cube, F_center)/2; - eorl_source[i] = what_center_at(cube, R_center)/2; - eoud_source[i] = what_center_at(cube, U_center)/2; - coud_source[i] = what_center_at(cube, U_center)/2; - cofb_source[i] = what_center_at(cube, F_center)/2; - corl_source[i] = what_center_at(cube, R_center)/2; - } - - if (read_ttables_file()) - return; - - fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); - - /* Initialize tables */ - for (m = 0; m < NTRANS; m++) { - epcp = (CubeArray){ .ep = eparr, .cp = cparr }; - cube = apply_alg(rotation_alg(m), (Cube){0}); - cube_to_arrays(cube, &epcp, pf_epcp); - if (m >= NROTATIONS) { - apply_permutation(ep_mirror, eparr, 12); - apply_permutation(cp_mirror, cparr, 8); - } - - for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { - c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); - c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); - c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); - - cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); - epose_ttable[m][ui] = cube.epose; - - cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); - eposs_ttable[m][ui] = cube.eposs; - - cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); - eposm_ttable[m][ui] = cube.eposm; - } - for (ui = 0; ui < POW2TO11; ui++ ) { - int_to_sum_zero_array(ui, 2, 12, eoarr); - apply_permutation(eparr, eoarr, 12); - eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); - } - for (ui = 0; ui < POW3TO7; ui++) { - int_to_sum_zero_array(ui, 3, 8, coarr); - apply_permutation(cparr, coarr, 8); - co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); - if (m >= NROTATIONS) - co_ttable[m][ui] = - invert_digits(co_ttable[m][ui], 3, 7); - } - for (ui = 0; ui < FACTORIAL8; ui++) { - cube = (Cube){ .cp = ui }; - cube = rotate_via_compose(m, cube, pf_cp); - cp_ttable[m][ui] = cube.cp; - } - for (ui = 0; ui < FACTORIAL6; ui++) { - cube = (Cube){ .cpos = ui }; - cube = rotate_via_compose(m, cube, pf_cpos); - cpos_ttable[m][ui] = cube.cpos; - } - for (mi = 0; mi < NMOVES; mi++) { - /* Old version: - * - aux = apply_trans(m, apply_move(mi, (Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move(inverse_move(move), aux); - mirr = apply_trans(uf_mirror, cube); - if (is_solved(cube) || is_solved(mirr)) - moves_ttable[m][mi] = move; - } - */ - - aux = apply_trans(m, apply_move(mi, (Cube){0})); - for (move = 0; move < NMOVES; move++) { - cube = apply_move(inverse_move(move), aux); - if (is_solved(cube)) { - moves_ttable[m][mi] = move; - break; - } - } - } - } - - if (!write_ttables_file()) - fprintf(stderr, "Error writing ttables\n"); -} - -static bool -read_ttables_file() -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+20]; - int b = sizeof(int); - bool r = true; - Move m; - - /* Table sizes, used for reading and writing files */ - uint64_t me[11] = { - [0] = FACTORIAL12/FACTORIAL8, - [1] = FACTORIAL12/FACTORIAL8, - [2] = FACTORIAL12/FACTORIAL8, - [3] = POW2TO11, - [4] = FACTORIAL8, - [5] = POW3TO7, - [6] = FACTORIAL6, - [7] = NMOVES - }; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, "ttables"); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fread(cp_ttable[m], b, me[4], f) == me[4]; - r = r && fread(co_ttable[m], b, me[5], f) == me[5]; - r = r && fread(cpos_ttable[m], b, me[6], f) == me[6]; - r = r && fread(moves_ttable[m], b, me[7], f) == me[7]; - } - - fclose(f); - return r; -} - -static Cube -rotate_via_compose(Trans r, Cube c, PieceFilter f) -{ - static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static CubeArray ma = { - .ep = ep_mirror, - .eofb = zero12, - .eorl = zero12, - .eoud = zero12, - .cp = cp_mirror, - .coud = zero8, - .corl = zero8, - .cofb = zero8, - .cpos = cpos_mirror - }; - - Alg *inv = inverse_alg(rotation_alg(r)); - Cube ret = {0}; - - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - ret = apply_alg_generic(inv, ret, f, true); - - ret = compose_filtered(c, ret, f); - - ret = apply_alg_generic(rotation_alg(r), ret, f, true); - if (r >= NROTATIONS) - ret = move_via_arrays(&ma, ret, f); - - free_alg(inv); - return ret; -} - -static bool -write_ttables_file() -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+20]; - bool r = true; - int b = sizeof(int); - Move m; - - /* Table sizes, used for reading and writing files */ - uint64_t me[11] = { - [0] = FACTORIAL12/FACTORIAL8, - [1] = FACTORIAL12/FACTORIAL8, - [2] = FACTORIAL12/FACTORIAL8, - [3] = POW2TO11, - [4] = FACTORIAL8, - [5] = POW3TO7, - [6] = FACTORIAL6, - [7] = NMOVES - }; - - strcpy(fname, tabledir); - strcat(fname, "/ttables"); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - for (m = 0; m < NTRANS; m++) { - r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; - r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; - r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; - r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; - r = r && fwrite(cp_ttable[m], b, me[4], f) == me[4]; - r = r && fwrite(co_ttable[m], b, me[5], f) == me[5]; - r = r && fwrite(cpos_ttable[m], b, me[6], f) == me[6]; - r = r && fwrite(moves_ttable[m], b, me[7], f) == me[7]; - } - - fclose(f); - return r; -} - -/* Public functions **********************************************************/ - -Cube -apply_trans(Trans t, Cube cube) -{ - /*init_trans();*/ - - int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; - int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; - int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; - - return (Cube) { - .epose = epose_ttable[t][aux_epos[epose_source[t]]], - .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], - .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], - .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], - .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], - .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], - .coud = co_ttable[t][aux_co[coud_source[t]]], - .corl = co_ttable[t][aux_co[corl_source[t]]], - .cofb = co_ttable[t][aux_co[cofb_source[t]]], - .cp = cp_ttable[t][cube.cp], - .cpos = cpos_ttable[t][cube.cpos] - }; -} - -Trans -inverse_trans(Trans t) -{ - /* TODO is there a more elegant way? */ - static Trans inverse_trans_aux[NTRANS] = { - [uf] = uf, [ur] = ul, [ul] = ur, [ub] = ub, - [df] = df, [dr] = dr, [dl] = dl, [db] = db, - [rf] = lf, [rd] = bl, [rb] = rb, [ru] = fr, - [lf] = rf, [ld] = br, [lb] = lb, [lu] = fl, - [fu] = fu, [fr] = ru, [fd] = bu, [fl] = lu, - [bu] = fd, [br] = ld, [bd] = bd, [bl] = rd, - - [uf_mirror] = uf_mirror, [ur_mirror] = ur_mirror, - [ul_mirror] = ul_mirror, [ub_mirror] = ub_mirror, - [df_mirror] = df_mirror, [dr_mirror] = dl_mirror, - [dl_mirror] = dr_mirror, [db_mirror] = db_mirror, - [rf_mirror] = rf_mirror, [rd_mirror] = br_mirror, - [rb_mirror] = lb_mirror, [ru_mirror] = fl_mirror, - [lf_mirror] = lf_mirror, [ld_mirror] = bl_mirror, - [lb_mirror] = rb_mirror, [lu_mirror] = fr_mirror, - [fu_mirror] = fu_mirror, [fr_mirror] = lu_mirror, - [fd_mirror] = bu_mirror, [fl_mirror] = ru_mirror, - [bu_mirror] = fd_mirror, [br_mirror] = rd_mirror, - [bd_mirror] = bd_mirror, [bl_mirror] = ld_mirror - }; - - return inverse_trans_aux[t]; -} - -Alg * -rotation_alg(Trans t) -{ - int i; - - static Alg *rotation_alg_arr[NROTATIONS]; - static bool initialized = false; - - if (!initialized) { - for (i = 0; i < NROTATIONS; i++) - rotation_alg_arr[i] = new_alg(rotation_alg_string[i]); - - initialized = true; - } - - return rotation_alg_arr[t % NROTATIONS]; -} - -void -transform_alg(Trans t, Alg *alg) -{ - int i; - - /*init_trans();*/ - - for (i = 0; i < alg->len; i++) - alg->move[i] = moves_ttable[t][alg->move[i]]; -} diff --git a/old/2021-11-10-beforeremovingchecker/trans.h b/old/2021-11-10-beforeremovingchecker/trans.h @@ -1,13 +0,0 @@ -#ifndef TRANS_H -#define TRANS_H - -#include "moves.h" - -Cube apply_trans(Trans t, Cube cube); -Trans inverse_trans(Trans t); -Alg * rotation_alg(Trans i); -void transform_alg(Trans i, Alg *alg); - -void init_trans(); - -#endif diff --git a/old/2021-11-10-beforeremovingchecker/utils.c b/old/2021-11-10-beforeremovingchecker/utils.c @@ -1,274 +0,0 @@ -#include "utils.h" - -void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - memcpy(set, aux, n * sizeof(int)); - free(aux); -} - -int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -int -invert_digits(int a, int b, int n) -{ - int i, ret, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - ret = digit_array_to_int(r, n, b); - free(r); - return ret; -} - -bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -int -powint(int a, int b) -{ - if (b < 0) - return 0; - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -int -subset_to_index(int *a, int n, int k) -{ - int i, ret = 0; - - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} - -void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - diff --git a/old/2021-11-10-beforeremovingchecker/utils.h b/old/2021-11-10-beforeremovingchecker/utils.h @@ -1,41 +0,0 @@ -#ifndef UTILS_H -#define UTILS_H - -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> - -#define POW2TO6 64ULL -#define POW2TO11 2048ULL -#define POW2TO12 4096ULL -#define POW3TO7 2187ULL -#define POW3TO8 6561ULL -#define FACTORIAL4 24ULL -#define FACTORIAL6 720ULL -#define FACTORIAL7 5040ULL -#define FACTORIAL8 40320ULL -#define FACTORIAL12 479001600ULL -#define BINOM12ON4 495ULL -#define BINOM8ON4 70ULL -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) - -void apply_permutation(int *perm, int *set, int n); -int binomial(int n, int k); -int digit_array_to_int(int *a, int n, int b); -int factorial(int n); -void index_to_perm(int p, int n, int *r); -void index_to_subset(int s, int n, int k, int *r); -void int_to_digit_array(int a, int b, int n, int *r); -void int_to_sum_zero_array(int x, int b, int n, int *a); -int invert_digits(int a, int b, int n); -bool is_perm(int *a, int n); -bool is_subset(int *a, int n, int k); -int perm_sign(int *a, int n); -int perm_to_index(int *a, int n); -int powint(int a, int b); -int subset_to_index(int *a, int n, int k); -void sum_arrays_mod(int *src, int *dst, int n, int m); -void swap(int *a, int *b); - -#endif diff --git a/old/backup-manysteps-pretrans/steps.c b/old/backup-manysteps-pretrans/steps.c @@ -1,369 +0,0 @@ -#include "steps.h" - -/* Check functions ***********************************************************/ - -static int check_nothing(Cube cube); -static int check_eofb_HTM(Cube cube); -static int check_coud_HTM(Cube cube); -static int check_coud_URF(Cube cube); -static int check_corners_HTM(Cube cube); -static int check_corners_URF(Cube cube); -static int check_edges_HTM(Cube cube); -static int check_drud_HTM(Cube cube); -static int check_optimal_HTM(Cube cube); - - -/* Index functions ***********************************************************/ - -static uint64_t index_eofb(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_ep(Cube cube); -static uint64_t index_drud(Cube cube); - - -/* Steps *********************************************************************/ - -Step -eofb_HTM = { - .check = check_eofb_HTM, - .ready = check_nothing, - .pre_trans = uf, - .moveset = moveset_HTM -}; - -Step -eorl_HTM = { - .check = check_eofb_HTM, - .ready = check_nothing, - .pre_trans = ur, - .moveset = moveset_HTM -}; - -Step -eoud_HTM = { - .check = check_eofb_HTM, - .ready = check_nothing, - .pre_trans = bu, - .moveset = moveset_HTM -}; - -Step -coud_HTM = { - .check = check_coud_HTM, - .ready = check_nothing, - .pre_trans = uf, - .moveset = moveset_HTM -}; - -Step -corl_HTM = { - .check = check_coud_HTM, - .ready = check_nothing, - .pre_trans = rf, - .moveset = moveset_HTM -}; - -Step -cofb_HTM = { - .check = check_coud_HTM, - .ready = check_nothing, - .pre_trans = fd, - .moveset = moveset_HTM -}; - -Step -coud_URF = { - .check = check_coud_URF, - .ready = check_nothing, - .pre_trans = uf, - .moveset = moveset_URF -}; - -Step -corl_URF = { - .check = check_coud_URF, - .ready = check_nothing, - .pre_trans = rf, - .moveset = moveset_URF -}; - -Step -cofb_URF = { - .check = check_coud_URF, - .ready = check_nothing, - .pre_trans = fd, - .moveset = moveset_URF -}; - -Step -corners_HTM = { - .check = check_corners_HTM, - .ready = check_nothing, - .pre_trans = uf, - .moveset = moveset_HTM -}; - -Step -corners_URF = { - .check = check_corners_URF, - .ready = check_nothing, - .pre_trans = uf, - .moveset = moveset_URF -}; - -Step -edges_HTM = { - .check = check_edges_HTM, - .ready = check_nothing, - .pre_trans = uf, - .moveset = moveset_HTM -}; - -Step -drud_HTM = { - .check = check_drud_HTM, - .ready = check_nothing, - .pre_trans = uf, - .moveset = moveset_HTM -}; - -Step -optimal_HTM = { - .check = check_optimal_HTM, - .ready = check_nothing, - .pre_trans = uf, - .moveset = moveset_HTM -}; - - -/* Pruning tables ************************************************************/ - -PruneData -pd_eofb_HTM = { - .filename = "ptable_eofb_HTM", - .size = POW2TO11, - .index = index_eofb, - .moveset = moveset_HTM -}; - -PruneData -pd_coud_HTM = { - .filename = "ptable_coud_HTM", - .size = POW3TO7, - .index = index_coud, - .moveset = moveset_HTM -}; - -PruneData -pd_corners_HTM = { - .filename = "ptable_corners_HTM", - .size = POW3TO7 * FACTORIAL8, - .index = index_corners, - .moveset = moveset_HTM -}; - -PruneData -pd_ep_HTM = { - .filename = "ptable_ep_HTM", - .size = FACTORIAL12, - .index = index_ep, - .moveset = moveset_HTM -}; - -PruneData -pd_drud_HTM = { - .filename = "ptable_drud_HTM", - .size = POW2TO11 * POW3TO7 * BINOM12ON4, - .index = index_drud, - .moveset = moveset_HTM -}; - - -/* Check functions implementation ********************************************/ - -static int -check_nothing(Cube cube) -{ - /* At least we check that it is admissible */ - return is_admissible(cube); -} - -static int -check_eofb_HTM(Cube cube) -{ - if (!pd_eofb_HTM.generated) - generate_ptable(&pd_eofb_HTM); - - return PTABLEVAL(pd_eofb_HTM.ptable, cube.eofb); -} - -static int -check_coud_HTM(Cube cube) -{ - if (!pd_coud_HTM.generated) - generate_ptable(&pd_coud_HTM); - - return PTABLEVAL(pd_coud_HTM.ptable, cube.coud); -} - -static int -check_coud_URF(Cube cube) -{ - /* TODO: I can improve this by checking first the orientation of - * the corner in DBL and use that as a reference */ - - int ud = check_coud_HTM(cube); - int rl = check_coud_HTM(apply_move(z, cube)); - int fb = check_coud_HTM(apply_move(x, cube)); - - return MIN(ud, MIN(rl, fb)); -} - -static int -check_corners_HTM(Cube cube) -{ - if (!pd_corners_HTM.generated) - generate_ptable(&pd_corners_HTM); - - return PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); -} - -static int -check_corners_URF(Cube cube) -{ - /* TODO: I can improve this by checking first the corner in DBL - * and use that as a reference */ - - int ret = 15; - Trans i; - - for (i = 0; i < NROTATIONS; i++) - ret = MIN(ret,check_corners_HTM(apply_alg(trans_alg(i),cube))); - - return ret; -} - -static int -check_edges_HTM(Cube cube) -{ - int ret = 0; - - if (!pd_ep_HTM.generated) - generate_ptable(&pd_ep_HTM); - - ret = MAX(ret, PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube))); - ret = MAX(ret, check_eofb_HTM(cube)); - ret = MAX(ret, check_eofb_HTM(apply_trans(ur, cube))); - ret = MAX(ret, check_eofb_HTM(apply_trans(fd, cube))); - - return ret; -} - -static int -check_drud_HTM(Cube cube) -{ - if (!pd_drud_HTM.generated) - generate_ptable(&pd_drud_HTM); - - return PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); -} - -static int -check_optimal_HTM(Cube cube) -{ - int dr1, dr2, dr3, drmax, cor; /*ep;*/ - - if (!pd_drud_HTM.generated) - generate_ptable(&pd_drud_HTM); - if (!pd_corners_HTM.generated) - generate_ptable(&pd_corners_HTM); - /* - *if (!pd_ep_HTM.generated) - * generate_ptable(&pd_ep_HTM); - */ - - dr1 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); - dr2 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(rf, cube))); - dr3 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(fd, cube))); - - drmax = MAX(dr1, MAX(dr2, dr3)); - if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) - drmax++; - - cor = PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); - /* ep = PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube)); */ - - /*return MAX(drmax, MAX(ep, cor));*/ - if (drmax == 0 && cor == 0) - return is_solved(cube, false) ? 0 : 1; - return MAX(drmax, cor); -} - - -/* Index functions implementation ********************************************/ - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_ep(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eposs; - b = (cube.epose % FACTORIAL4) + epos_dependent_cube(cube)*FACTORIAL4; - c = cube.eposm % FACTORIAL4; - - b *= FACTORIAL4 * BINOM12ON4; - c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; - - return a + b + c; -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -/* Movesets ******************************************************************/ - -bool -moveset_HTM(Move m) -{ - return m >= U && m <= B3; -} - -bool -moveset_URF(Move m) -{ - Move b = base_move(m); - - return b == U || b == R || b == F; -} - diff --git a/old/backup-manysteps-pretrans/steps.h b/old/backup-manysteps-pretrans/steps.h @@ -1,36 +0,0 @@ -#ifndef STEPS_H -#define STEPS_H - -#include "cube.h" - -/* Steps *********************************************************************/ - -extern Step eofb_HTM; -extern Step eorl_HTM; -extern Step eoud_HTM; -extern Step coud_HTM; -extern Step corl_HTM; -extern Step cofb_HTM; -extern Step coud_URF; -extern Step corl_URF; -extern Step cofb_URF; -extern Step corners_HTM; -extern Step corners_URF; -extern Step edges_HTM; -extern Step drud_HTM; -extern Step optimal_HTM; - -/* Pruning tables ************************************************************/ - -extern PruneData pd_eofb_HTM; -extern PruneData pd_coud_HTM; -extern PruneData pd_corners_HTM; -extern PruneData pd_ep_HTM; -extern PruneData pd_drud_HTM; - -/* Movesets ******************************************************************/ - -bool moveset_HTM(Move m); -bool moveset_URF(Move m); - -#endif diff --git a/old/coord.c b/old/coord.c @@ -1,1014 +0,0 @@ -#include "coord.h" - -static Cube admissible_eos_from_eofbepos(Cube cube); -static Cube antindex_eofb(uint64_t ind); -static Cube antindex_eofbepos(uint64_t ind); -static Cube antindex_epud(uint64_t ind); -static Cube antindex_coud(uint64_t ind); -static Cube antindex_corners(uint64_t ind); -static Cube antindex_cp(uint64_t ind); -static Cube antindex_cornershtr(uint64_t ind); -static Cube antindex_drud(uint64_t ind); -static Cube antindex_coud_sym16(uint64_t ind); -static Cube antindex_cp_sym16(uint64_t ind); -static Cube antindex_eofbepos_sym16(uint64_t ind); -static Cube antindex_drud_sym16(uint64_t ind); -static Cube antindex_drud_eofb(uint64_t ind); -static Cube antindex_drudfin_noE_sym16(uint64_t ind); -static Cube antindex_htrfin(uint64_t ind); -static Cube antindex_khuge(uint64_t ind); -static int epos_dependent_pos(int pos1, int pos2); -static void gensym(SymData *sd); -static uint64_t index_eofb(Cube cube); -static uint64_t index_eofbepos(Cube cube); -static uint64_t index_epud(Cube cube); -static uint64_t index_coud(Cube cube); -static uint64_t index_corners(Cube cube); -static uint64_t index_cp(Cube cube); -static uint64_t index_cornershtr(Cube cube); -static uint64_t index_drud(Cube cube); -static uint64_t index_coud_sym16(Cube cube); -static uint64_t index_cp_sym16(Cube cube); -static uint64_t index_eofbepos_sym16(Cube cube); -static uint64_t index_drud_sym16(Cube cube); -static uint64_t index_drud_eofb(Cube cube); -static uint64_t index_drudfin_noE_sym16(Cube cube); -static uint64_t index_htrfin(Cube cube); -static uint64_t index_khuge(Cube cube); -static void init_cphtr_cosets(); -static void init_cphtr_left_cosets_bfs(int i, int c); -static void init_cphtr_right_cosets_color(int i, int c); -static void init_symdata(); -static bool read_symdata_file(SymData *sd); -static bool write_symdata_file(SymData *sd); - -/* All sorts of useful costants and tables **********************************/ - -/* TODO: Can I move inside functions that use them? - Maybe I need to pass them as argument to some - secondary function */ -static int cphtr_left_cosets[FACTORIAL8]; -static int cphtr_right_cosets[FACTORIAL8]; -static int cphtr_right_rep[BINOM8ON4*6]; - - -/* Symmetry data for some coordinates ****************************************/ - -static Trans -trans_group_trivial[1] = { uf }; - -static Trans -trans_group_udfix[16] = { - uf, ur, ub, ul, - df, dr, db, dl, - uf_mirror, ur_mirror, ub_mirror, ul_mirror, - df_mirror, dr_mirror, db_mirror, dl_mirror, -}; - -SymData -sd_coud_16 = { - .filename = "sd_coud_16", - .coord = &coord_coud, - .sym_coord = &coord_coud_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -SymData -sd_cp_16 = { - .filename = "sd_cp_16", - .coord = &coord_cp, - .sym_coord = &coord_cp_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -SymData -sd_eofbepos_16 = { - .filename = "sd_eofbepos_16", - .coord = &coord_eofbepos, - .sym_coord = &coord_eofbepos_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static int n_all_symdata = 3; -static SymData * all_sd[3] = { - &sd_coud_16, - &sd_cp_16, - &sd_eofbepos_16, -}; - -/* Coordinates and their implementation **************************************/ - -Coordinate -coord_eofb = { - .index = index_eofb, - .cube = antindex_eofb, - .check = check_eofb, - .max = POW2TO11, - .ntrans = 1, - .trans = trans_group_trivial, -}; - -Coordinate -coord_eofbepos = { - .index = index_eofbepos, - .cube = antindex_eofbepos, - .check = check_eofbepos, - .max = POW2TO11 * BINOM12ON4, - .ntrans = 1, - .trans = trans_group_trivial, -}; - -Coordinate -coord_coud = { - .index = index_coud, - .cube = antindex_coud, - .check = check_coud, - .max = POW3TO7, - .ntrans = 1, - .trans = trans_group_trivial, -}; - -Coordinate -coord_corners = { - .index = index_corners, - .cube = antindex_corners, - .check = check_corners, - .max = POW3TO7 * FACTORIAL8, - .ntrans = 1, - .trans = trans_group_trivial, -}; - -Coordinate -coord_cp = { - .index = index_cp, - .cube = antindex_cp, - .check = check_cp, - .max = FACTORIAL8, - .ntrans = 1, - .trans = trans_group_trivial, -}; - -Coordinate -coord_cornershtr = { - .index = index_cornershtr, - .cube = antindex_cornershtr, - .check = check_cornershtr, - .max = POW3TO7 * BINOM8ON4 * 6, - .ntrans = 1, - .trans = trans_group_trivial, -}; - -Coordinate -coord_drud = { - .index = index_drud, - .cube = antindex_drud, - .check = check_drud, - .max = POW2TO11 * POW3TO7 * BINOM12ON4, - .ntrans = 1, - .trans = trans_group_trivial, -}; - -Coordinate -coord_htrfin = { - .index = index_htrfin, - .cube = antindex_htrfin, - .check = check_htrfin, - .max = 24 * 24 * 24 *24 * 24, - .ntrans = 1, - .trans = trans_group_trivial, -}; - -Coordinate -coord_drud_eofb = { - .index = index_drud_eofb, - .cube = antindex_drud_eofb, - .check = check_drud, - .max = POW3TO7 * BINOM12ON4, - .ntrans = 1, - .trans = trans_group_trivial, -}; - -Coordinate -coord_eofbepos_sym16 = { - .index = index_eofbepos_sym16, - .cube = antindex_eofbepos_sym16, - .check = check_eofbepos, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_coud_sym16 = { - .index = index_coud_sym16, - .cube = antindex_coud_sym16, - .check = check_coud, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_cp_sym16 = { - .index = index_cp_sym16, - .cube = antindex_cp_sym16, - .check = check_cp, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_drud_sym16 = { - .index = index_drud_sym16, - .cube = antindex_drud_sym16, - .check = check_drud, - .max = POW3TO7 * 64430, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_drudfin_noE_sym16 = { - .index = index_drudfin_noE_sym16, - .cube = antindex_drudfin_noE_sym16, - .check = check_drudfin_noE, - .max = FACTORIAL8 * 2768, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -Coordinate -coord_khuge = { - .index = index_khuge, - .cube = antindex_khuge, - .check = check_khuge, - .max = POW3TO7 * FACTORIAL4 * 64430, - .ntrans = 16, - .trans = trans_group_udfix, -}; - -/* Functions *****************************************************************/ - -static Cube -admissible_eos_from_eofbepos(Cube cube) -{ - Edge e; - Cube ret; - CubeArray *arr = new_cubearray(cube, pf_all); - - memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); - memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); - - for (e = 0; e < 12; e++) { - if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || - (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) - arr->eorl[e] = 1 - arr->eorl[e]; - if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || - (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) - arr->eoud[e] = 1 - arr->eoud[e]; - } - - ret = arrays_to_cube(arr, pf_all); - free_cubearray(arr, pf_all); - - return ret; -} - - -static Cube -antindex_eofb(uint64_t ind) -{ - return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; -} - -static Cube -antindex_eofbepos(uint64_t ind) -{ - static bool initialized = false; - static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; - static Cube c1; - static int k; - static uint64_t ui; - - if (!initialized) { - for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { - k = (ui / POW2TO11) * 24; - c1 = admissible_ep((Cube){ .epose = k }, pf_e); - c1.eofb = ui % POW2TO11; - c1 = admissible_eos_from_eofbepos(c1); - admissible_ee_aux[ui] = c1; - } - - initialized = true; - } - - return admissible_ee_aux[ind]; -} - -static Cube -antindex_epud(uint64_t ind) -{ - static bool initialized = false; - static Cube epud_aux[FACTORIAL8]; - int a[12]; - uint64_t ui; - CubeArray arr; - - if (!initialized) { - a[FR] = FR; - a[FL] = FL; - a[BL] = BL; - a[BR] = BR; - for (ui = 0; ui < FACTORIAL8; ui++) { - index_to_perm(ui, 8, a); - arr.ep = a; - epud_aux[ui] = arrays_to_cube(&arr, pf_ep); - } - - initialized = true; - } - - return epud_aux[ind]; -} - -static Cube -antindex_coud(uint64_t ind) -{ - return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; -} - -static Cube -antindex_corners(uint64_t ind) -{ - Cube c = {0}; - - c.coud = ind / FACTORIAL8; - c.cp = ind % FACTORIAL8; - - return c; -} - -static Cube -antindex_cp(uint64_t ind) -{ - Cube c = {0}; - - c.cp = ind; - - return c; -} - -static Cube -antindex_cornershtr(uint64_t ind) -{ - Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); - - c.coud = ind / (BINOM8ON4 * 6); - - return c; -} - -/* TODO: admissible eos and cos */ -/* DONE: temporary fix, make it better */ -/* Or maybe it's ok like this? */ -static Cube -antindex_drud(uint64_t ind) -{ - uint64_t epos, eofb; - Cube c; - - eofb = ind % POW2TO11; - epos = ind / (POW2TO11 * POW3TO7); - c = antindex_eofbepos(eofb + POW2TO11 * epos); - - c.coud = (ind / POW2TO11) % POW3TO7; - c.corl = c.coud; - c.cofb = c.coud; - - return c; -} - -static Cube -antindex_drud_eofb(uint64_t ind) -{ - return antindex_drud(ind * POW2TO11); -} - -static Cube -antindex_coud_sym16(uint64_t ind) -{ - return sd_coud_16.rep[ind]; -} - -static Cube -antindex_cp_sym16(uint64_t ind) -{ - return sd_cp_16.rep[ind]; -} - -static Cube -antindex_eofbepos_sym16(uint64_t ind) -{ - return sd_eofbepos_16.rep[ind]; -} - -static Cube -antindex_drud_sym16(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/POW3TO7]; - c.coud = ind % POW3TO7; - c.cofb = c.coud; - c.corl = c.coud; - - return c; -} - -static Cube -antindex_drudfin_noE_sym16(uint64_t ind) -{ - Cube c1, c2; - - c1 = antindex_epud(ind % FACTORIAL8); - c2 = sd_cp_16.rep[ind/FACTORIAL8]; - c1.cp = c2.cp; - - return c1; -} - -static Cube -antindex_htrfin(uint64_t ind) -{ - Cube ret = {0}; - uint64_t cp1, cp2; - - static bool initialized = false; - static int i, j, k, c[8], c1[4], c2[4], cp[24][24]; - static int c1solved[4] = {UFR, UBL, DFL, DBR}; - static int c2solved[4] = {UFL, UBR, DFR, DBL}; - - if (!initialized) { - for (i = 0; i < 24; i++) { - for (j = 0; j < 24; j++) { - index_to_perm(i, 4, c1); - index_to_perm(j, 4, c2); - for (k = 0; k < 8; k++) - if (k == UFR || k == UBL || - k == DFL || k == DBR) - c[k] = c1[c1solved[k/2]]; - else - c[k] = c2[c2solved[k/2]]; - - cp[i][j] = perm_to_index(c, 8); - } - } - - initialized = true; - } - - cp2 = ind % 24; - ind /= 24; - cp1 = ind % 24; - ret.cp = cp[cp1][cp2]; - - ind /= 24; - ret.eposm = ind % 24; - ind /= 24; - ret.eposs = ind % 24; - ret.epose = ind / 24; - - return ret; -} - -static Cube -antindex_khuge(uint64_t ind) -{ - Cube c; - - c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; - c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); - c.coud = ind % POW3TO7; - - return c; -} - -bool -check_centers(Cube cube) -{ - return cube.cpos == 0; -} - -bool -check_corners(Cube cube) -{ - return cube.cp == 0 && cube.coud == 0; -} - -bool -check_cp(Cube cube) -{ - return cube.cp == 0; -} - -bool -check_cornershtr(Cube cube) -{ - return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ -} - -bool -check_coud(Cube cube) -{ - return cube.coud == 0; -} - -bool -check_drud(Cube cube) -{ - return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; -} - -bool -check_htr(Cube cube) -{ - return check_cornershtr(cube) && - cube.eofb == 0 && cube.eorl == 0 && cube.eoud == 0; -} - -bool -check_htrfin(Cube cube) -{ - return cube.cp == 0 && - cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; -} - -bool -check_drudfin_noE(Cube cube) -{ - return cube.eposs == 0 && cube.eposm == 0 && cube.cp == 0; -} - -bool -check_eofb(Cube cube) -{ - return cube.eofb == 0; -} - -bool -check_eofbepos(Cube cube) -{ - return cube.eofb == 0 && cube.epose / 24 == 0; -} - -bool -check_epose(Cube cube) -{ - return cube.epose == 0; -} - -bool -check_ep(Cube cube) -{ - return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; -} - -bool -check_khuge(Cube cube) -{ - return check_drud(cube) && cube.epose % 24 == 0; -} - -bool -check_nothing(Cube cube) -{ - return is_admissible(cube); /*TODO: maybe change?*/ -} - -static int -epos_dependent_pos(int poss, int pose) -{ - static int epe_solved[4] = {FR, FL, BL, BR}; - static int eps_solved[4] = {UL, UR, DL, DR}; - int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - int i, j; - - epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); - epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); - - for (i = 0, j = 0; i < 12; i++) - if (edge_slice(ep[i]) != 0) - ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; - - swap(&ep8[1], &ep8[4]); - swap(&ep8[3], &ep8[6]); - - return subset_to_index(ep8, 8, 4); -} - -static void -gensym(SymData *sd) -{ - uint64_t i, in, nreps = 0; - int j; - Cube c, d; - - if (sd->generated) - return; - - sd->class = malloc(sd->coord->max * sizeof(uint64_t)); - sd->rep = malloc(sd->coord->max * sizeof(Cube)); - sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); - - if (read_symdata_file(sd)) { - sd->generated = true; - return; - } - - fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); - - for (i = 0; i < sd->coord->max; i++) - sd->class[i] = sd->coord->max + 1; - - for (i = 0; i < sd->coord->max; i++) { - if (sd->class[i] == sd->coord->max + 1) { - c = sd->coord->cube(i); - sd->rep[nreps] = c; - for (j = 0; j < sd->ntrans; j++) { - d = apply_trans(sd->trans[j], c); - in = sd->coord->index(d); - - if (sd->class[in] == sd->coord->max + 1) { - sd->class[in] = nreps; - sd->transtorep[in] = - inverse_trans(sd->trans[j]); - } - } - nreps++; - } - } - - sd->sym_coord->max = nreps; - sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); - sd->generated = true; - - fprintf(stderr, "Found %lu classes\n", nreps); - - if (!write_symdata_file(sd)) - fprintf(stderr, "Error writing SymData file\n"); - - return; -} - -static uint64_t -index_eofb(Cube cube) -{ - return cube.eofb; -} - -static uint64_t -index_eofbepos(Cube cube) -{ - return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; -} - -static uint64_t -index_epud(Cube cube) -{ - uint64_t ret; - CubeArray *arr = new_cubearray(cube, pf_ep); - - ret = perm_to_index(arr->ep, 8); - free_cubearray(arr, pf_ep); - - return ret; -} - -static uint64_t -index_coud(Cube cube) -{ - return cube.coud; -} - -static uint64_t -index_corners(Cube cube) -{ - return cube.coud * FACTORIAL8 + cube.cp; -} - -static uint64_t -index_cp(Cube cube) -{ - return cube.cp; -} - -static uint64_t -index_cornershtr(Cube cube) -{ - return cube.coud * BINOM8ON4 * 6 + cphtr(cube); -} - -static uint64_t -index_drud(Cube cube) -{ - uint64_t a, b, c; - - a = cube.eofb; - b = cube.coud; - c = cube.epose / FACTORIAL4; - - b *= POW2TO11; - c *= POW2TO11 * POW3TO7; - - return a + b + c; -} - -static uint64_t -index_drud_eofb(Cube cube) -{ - return index_drud(cube) / POW2TO11; -} - -static uint64_t -index_coud_sym16(Cube cube) -{ - return sd_coud_16.class[index_coud(cube)]; -} - -static uint64_t -index_cp_sym16(Cube cube) -{ - return sd_cp_16.class[index_cp(cube)]; -} - -static uint64_t -index_drud_sym16(Cube cube) -{ - Trans t; - Cube c; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - - return index_eofbepos_sym16(c) * POW3TO7 + c.coud; -} - -static uint64_t -index_drudfin_noE_sym16(Cube cube) -{ - Trans t; - Cube c; - - t = sd_cp_16.transtorep[index_cp(cube)]; - c = apply_trans(t, cube); - - return index_cp_sym16(c) * FACTORIAL8 + index_epud(c); -} - -static uint64_t -index_htrfin(Cube cube) -{ - uint64_t epe, eps, epm, cp, ep; - - static bool initialized = false; - static uint64_t cp1[FACTORIAL8], cp2[FACTORIAL8]; - static unsigned int i; - static int j, n1, n2, c[8], c1[4], c2[4]; - - if (!initialized) { - for (i = 0; i < FACTORIAL8; i++) { - index_to_perm(i, 8, c); - n1 = 0; - n2 = 0; - for (j = 0; j < 8; j++) - if (c[j] == UFR || c[j] == UBL || - c[j] == DFL || c[j] == DBR) - c1[n1++] = c[j] / 2; - else - c2[n2++] = c[j] / 2; - - cp1[i] = perm_to_index(c1, 4); - cp2[i] = perm_to_index(c2, 4); - } - - initialized = true; - } - - epe = cube.epose % 24; - eps = cube.eposs % 24; - epm = cube.eposm % 24; - - cp = cp1[cube.cp] * 24 + cp2[cube.cp]; - ep = (epe * 24 + eps) *24 + epm; - - return ep * 24 * 24 + cp; -} - -static uint64_t -index_eofbepos_sym16(Cube cube) -{ - return sd_eofbepos_16.class[index_eofbepos(cube)]; -} - -static uint64_t -index_khuge(Cube cube) -{ - Trans t; - Cube c; - uint64_t a; - - t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; - c = apply_trans(t, cube); - a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); - - return a * POW3TO7 + c.coud; -} - -static bool -read_symdata_file(SymData *sd) -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "rb")) == NULL) - return false; - - r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -static bool -write_symdata_file(SymData *sd) -{ - init_env(); - - FILE *f; - char fname[strlen(tabledir)+100]; - uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; - bool r = true; - - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, sd->filename); - - if ((f = fopen(fname, "wb")) == NULL) - return false; - - r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; - r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; - r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; - r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; - - fclose(f); - return r; -} - -/* Init functions implementation *********************************************/ - -/* - * There is certainly a bette way to do this, but for now I just use - * a "graph coloring" algorithm to compute the left cosets, and I compose - * with every possible cp to get the right cosets (it is possible that I am - * mixing up left and right). - * - * For doing it better "Mathematically", we need 3 things: - * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other - * This is easy and it is done in the commented function cphtr_cp(). - * - Check that there is no ep/cp parity - * - Check that we are not in the "3c" case; this is the part I don't - * know how to do. - */ -static void -init_cphtr_cosets() -{ - unsigned int i; - int c = 0, d = 0; - - for (i = 0; i < FACTORIAL8; i++) { - cphtr_left_cosets[i] = -1; - cphtr_right_cosets[i] = -1; - } - - /* First we compute left cosets with a bfs */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_left_cosets[i] == -1) - init_cphtr_left_cosets_bfs(i, c++); - - /* Then we compute right cosets using compose() */ - for (i = 0; i < FACTORIAL8; i++) - if (cphtr_right_cosets[i] == -1) - init_cphtr_right_cosets_color(i, d++); -} - -static void -init_cphtr_left_cosets_bfs(int i, int c) -{ - int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; - Move moves[6] = {U2, D2, R2, L2, F2, B2}; - - n = 1; - next[0] = i; - cphtr_left_cosets[i] = c; - - while (n != 0) { - for (j = 0, n2 = 0; j < n; j++) { - for (k = 0; k < 6; k++) { - /*jj = cp_mtable[moves[k]][next[j]];*/ - /* TODO fix formatting */ - jj = apply_move(moves[k], (Cube){.cp=next[j]}).cp; - if (cphtr_left_cosets[jj] == -1) { - cphtr_left_cosets[jj] = c; - next2[n2++] = jj; - } - } - } - - for (j = 0; j < n2; j++) - next[j] = next2[j]; - n = n2; - } -} - -static void -init_cphtr_right_cosets_color(int i, int d) -{ - int cp; - unsigned int j; - - cphtr_right_rep[d] = i; - for (j = 0; j < FACTORIAL8; j++) { - if (cphtr_left_cosets[j] == 0) { - /* TODO: use antindexer, it's nicer */ - cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; - cphtr_right_cosets[cp] = d; - } - } -} - -static void -init_symdata() -{ - int i; - - for (i = 0; i < n_all_symdata; i++) - gensym(all_sd[i]); -} - -/*TODO maybe move the next two */ -uint64_t -cphtr(Cube cube) -{ - return cphtr_right_cosets[cube.cp]; -} - -Cube -anti_cphtr(uint64_t ind) -{ - return (Cube) { .cp = cphtr_right_rep[ind] }; -} - -uint64_t -epos_dependent(Cube c) -{ - static int initialized = false; - static int aux[BINOM12ON4][BINOM12ON4]; - static uint64_t ui, uj; - - if (!initialized) { - for (ui = 0; ui < BINOM12ON4; ui++) - for (uj = 0; uj < BINOM12ON4; uj++) - aux[ui][uj] = epos_dependent_pos(ui, uj); - - initialized = true; - } - - return aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; -} - -void -init_coord() -{ - static bool initialized = false; - if (initialized) - return; - initialized = true; - - init_cphtr_cosets(); - init_symdata(); -} - diff --git a/old/coord.h b/old/coord.h @@ -1,45 +0,0 @@ -#ifndef COORD_H -#define COORD_H - -#include "trans.h" - -extern Coordinate coord_eofb; -extern Coordinate coord_eofbepos; -extern Coordinate coord_coud; -extern Coordinate coord_cp; -extern Coordinate coord_corners; -extern Coordinate coord_cornershtr; -extern Coordinate coord_drud; -extern Coordinate coord_coud_sym16; -extern Coordinate coord_drud_eofb; -extern Coordinate coord_cp_sym16; -extern Coordinate coord_eofbepos_sym16; -extern Coordinate coord_drud_sym16; -extern Coordinate coord_drudfin_noE_sym16; -extern Coordinate coord_htrfin; -extern Coordinate coord_khuge; - -uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ -Cube anti_cphtr(uint64_t ind); /*TODO also this */ -uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ - -bool check_centers(Cube cube); -bool check_corners(Cube cube); -bool check_cp(Cube cube); -bool check_cornershtr(Cube cube); -bool check_coud(Cube cube); -bool check_drud(Cube cube); -bool check_htr(Cube cube); -bool check_htrfin(Cube cube); -bool check_drudfin_noE(Cube cube); -bool check_eofb(Cube cube); -bool check_eofbepos(Cube cube); -bool check_epose(Cube cube); -bool check_ep(Cube cube); -bool check_khuge(Cube cube); -bool check_nothing(Cube cube); - -void init_coord(); - -#endif - diff --git a/old/utils.c b/old/utils.c @@ -1,294 +0,0 @@ -#include "utils.h" - -/* Generic utility functions *************************************************/ - -void -apply_permutation(int *perm, int *set, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - if (!is_perm(perm, n)) - return; - - for (i = 0; i < n; i++) - aux[i] = set[perm[i]]; - - intarrcopy(aux, set, n); - free(aux); -} - -void -intarrcopy(int *src, int *dst, int n) -{ - int i; - for (i = 0; i < n; i++) - dst[i] = src[i]; -} - -bool -is_perm(int *a, int n) -{ - int *aux = malloc(n * sizeof(int)); - int i; - - for (i = 0; i < n; i++) - if (a[i] < 0 || a[i] >= n) - return false; - else - aux[a[i]] = 1; - - for (i = 0; i < n; i++) - if (!aux[i]) - return false; - - free(aux); - - return true; -} - -bool -is_subset(int *a, int n, int k) -{ - int i, sum = 0; - - for (i = 0; i < n; i++) - sum += a[i] ? 1 : 0; - - return sum == k; -} - -int -sum(int *a, int n) -{ - int i, ret = 0; - - for (i = 0; i < n; i++) - ret += a[i]; - - return ret; -} - -void -sum_arrays_mod(int *src, int *dst, int n, int m) -{ - int i; - - for (i = 0; i < n; i++) - dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; -} - -void -swap(int *a, int *b) -{ - int aux; - - aux = *a; - *a = *b; - *b = aux; -} - -/* Standard mathematical functions *******************************************/ - -int -binomial(int n, int k) -{ - if (n < 0 || k < 0 || k > n) - return 0; - - return factorial(n) / (factorial(k) * factorial(n-k)); -} - -int -factorial(int n) -{ - int i, ret = 1; - - if (n < 0) - return 0; - - for (i = 1; i <= n; i++) - ret *= i; - - return ret; -} - -int -perm_sign(int *a, int n) -{ - int i, j, ret = 0; - if (!is_perm(a,n)) - return -1; - - for (i = 0; i < n; i++) - for (j = i+1; j < n; j++) - ret += (a[i] > a[j]) ? 1 : 0; - - return ret % 2; -} - -int -powint(int a, int b) -{ - if (b < 0) - return 0; /* Truncate */ - if (b == 0) - return 1; - - if (b % 2) - return a * powint(a, b-1); - else - return powint(a*a, b/2); -} - -/* Conversions to and from int (base b digits, permutations...) **************/ - -int -digit_array_to_int(int *a, int n, int b) -{ - int i, ret = 0, p = 1; - - for (i = 0; i < n; i++, p *= b) - ret += a[i] * p; - - return ret; -} - -void -int_to_digit_array(int a, int b, int n, int *r) -{ - int i; - - if (b <= 1) - for (i = 0; i < n; i++) - r[i] = 0; - else - for (i = 0; i < n; i++, a /= b) - r[i] = a % b; -} - -void -int_to_sum_zero_array(int x, int b, int n, int *a) -{ - int i, s = 0; - - if (b <= 1) { - for (i = 0; i < n; i++) - a[i] = 0; - } else { - int_to_digit_array(x, b, n-1, a); - for (i = 0; i < n - 1; i++) - s = (s + a[i]) % b; - a[n-1] = (b - s) % b; - } -} - -int -invert_digits(int a, int b, int n) -{ - int i, *r = malloc(n * sizeof(int)); - - int_to_digit_array(a, b, n, r); - for (i = 0; i < n; i++) - r[i] = (b-r[i]) % b; - - return digit_array_to_int(r, n, b); -} - -void -index_to_perm(int p, int n, int *r) -{ - int *a = malloc(n * sizeof(int)); - int i, j, c; - - for (i = 0; i < n; i++) - a[i] = 0; - - if (p < 0 || p >= factorial(n)) - for (i = 0; i < n; i++) - r[i] = -1; - - for (i = 0; i < n; i++) { - c = 0; - j = 0; - while (c <= p / factorial(n-i-1)) - c += a[j++] ? 0 : 1; - r[i] = j-1; - a[j-1] = 1; - p %= factorial(n-i-1); - } - - free(a); -} - -int -perm_to_index(int *a, int n) -{ - int i, j, c, ret = 0; - - if (!is_perm(a, n)) - return -1; - - for (i = 0; i < n; i++) { - c = 0; - for (j = i+1; j < n; j++) - c += (a[i] > a[j]) ? 1 : 0; - ret += factorial(n-i-1) * c; - } - - return ret; -} - -void -index_to_subset(int s, int n, int k, int *r) -{ - int i, j, v; - - if (s < 0 || s >= binomial(n, k)) { - for (i = 0; i < n; i++) - r[i] = -1; - return; - } - - for (i = 0; i < n; i++) { - if (k == n-i) { - for (j = i; j < n; j++) - r[j] = 1; - return; - } - - if (k == 0) { - for (j = i; j < n; j++) - r[j] = 0; - return; - } - - v = binomial(n-i-1, k); - if (s >= v) { - r[i] = 1; - k--; - s -= v; - } else { - r[i] = 0; - } - } -} - -int subset_to_index(int *a, int n, int k) { - int i, ret = 0; - - /* TODO: better checks */ - if (!is_subset(a, n, k)) - return binomial(n, k); - - for (i = 0; i < n; i++) { - if (k == n-i) - return ret; - if (a[i]) { - ret += binomial(n-i-1, k); - k--; - } - } - - return ret; -} diff --git a/old/utils.h b/old/utils.h @@ -1,59 +0,0 @@ -#ifndef UTILS_H -#define UTILS_H - -#include <stdbool.h> -#include <stdlib.h> - -/* Constants and macros *****************************************************/ - -#define pow2to11 2048 -#define pow2to12 4096 -#define pow3to7 2187 -#define pow3to8 6561 -#define pow12to4 20736 -#define factorial4 24 -#define factorial6 720 -#define factorial8 40320 -#define factorial12 479001600 -#define binom12on4 495 -#define binom8on4 70 - -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -/* Generic utility functions *************************************************/ - -void apply_permutation(int *perm, int *set, int n); -void intarrcopy(int *src, int *dst, int n); -bool is_perm(int *a, int n); -bool is_subset(int *a, int n, int k); -int sum(int *a, int n); -void sum_arrays_mod(int *src, int *dst, int n, int m); -void swap(int *a, int *b); - -/* Standard mathematical functions *******************************************/ - -int binomial(int n, int k); -int factorial(int n); -int perm_sign(int a[], int n); -int powint(int a, int b); - -/* Conversions to and from int (base b digits, permutations...) **************/ - -int digit_array_to_int(int *a, int n, int b); -void int_to_digit_array(int a, int b, int n, int *r); -void int_to_sum_zero_array(int x, int b, int n, int *a); -int invert_digits(int a, int b, int n); - -void index_to_perm(int p, int n, int *r); -int perm_to_index(int *a, int n); - -void index_to_subset(int s, int n, int k, int *r); -int subset_to_index(int *a, int n, int k); - -/* Am I not using these two? -void index_to_ordered_subset(int s, int n, int k, int *r); -int ordered_subset_to_index(int *a, int n, int k); -*/ - -#endif