aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano.tronto@gmail.com>2020-09-22 00:04:49 +0200
committerSebastiano Tronto <sebastiano.tronto@gmail.com>2020-09-22 00:04:49 +0200
commita2a7678518ec1db608f37f0521a3f8b61e97f868 (patch)
treee699f93ab5836df930b50bbcb492a77302934ebd
parent96ffb29a550451152b125f353a2107141610bc27 (diff)
downloadnissy-a2a7678518ec1db608f37f0521a3f8b61e97f868.tar.gz
nissy-a2a7678518ec1db608f37f0521a3f8b61e97f868.zip
Added CO first command
-rw-r--r--README.md2
-rw-r--r--docs/co.txt39
-rwxr-xr-xnissybin302560 -> 319784 bytes
-rw-r--r--src/helppages.h46
-rw-r--r--src/main.c211
-rw-r--r--src/solver.c96
-rw-r--r--src/solver.h2
7 files changed, 323 insertions, 73 deletions
diff --git a/README.md b/README.md
index 1278b31..25ba2d4 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ example, on a Linux system with GCC installed:
26 26
27``` 27```
28cd path/to/nissy 28cd path/to/nissy
29gcc -O3 -std=c99 -o nissy ./src/*.c 29gcc -O2 -std=c99 -o nissy ./src/*.c
30./nissy 30./nissy
31``` 31```
32 32
diff --git a/docs/co.txt b/docs/co.txt
new file mode 100644
index 0000000..27c0b43
--- /dev/null
+++ b/docs/co.txt
@@ -0,0 +1,39 @@
1
2HELP PAGE FOR COMMAND co
3
4SYNTAX
5co [OPTIONS] [MOVES|$ID|@ID]
6
7DESCRIPTION
8Solves CO for a given scramble. A scramble can be given as last argument of the
9command, or an ID of a saved scramble can be provided. If none of the two is
10given, a prompt will ask the user to input a new scramble.
11
12OPTIONS
13axis={fb,rl,ud} Specify the axis for the CO. One to three axes can be given,
14 comma separated, no spaces.
15 Default: CO on any of the three axis (omitting the option is
16 the same as specifying axis=fb,rl,ud).
17b=N Specify a bound for the number of moves. N must be a number.
18 Default value: 20.
19h Show hidden COs.
20 Default, if an CO ending in e.g. F is shown, the equivalent
21 one ending in F' is hidden.
22i Ignore centers. By default the CO is aligned with centers.
23niss Use NISS.
24 Default: does not use NISS.
25n=N Specify a maximum number of COs to be output. N must be a
26 number.
27 Default value: 1.
28
29EXAMPLES
30co axis=fb $1
31 Finds one optimal CO on fb for the first saved scramble.
32
33co n=5 b=4 U R F
34 Finds up to 5 COs of length at most 4 for scramble U R F.
35
36co n=100 b=5 niss axis=fb,ud h R' U' F L R'U'F
37 Finds up to 100 COs of lenth at most 4, possibly using NISS, including
38 "hidden" COs, excluding the rl axis.
39
diff --git a/nissy b/nissy
index 76442d5..0f435d3 100755
--- a/nissy
+++ b/nissy
Binary files differ
diff --git a/src/helppages.h b/src/helppages.h
index 5ee0e4a..178de37 100644
--- a/src/helppages.h
+++ b/src/helppages.h
@@ -1,6 +1,6 @@
1/* To generate this help page, use the script makedoc.sh */ 1/* To generate this help page, use the script makedoc.sh */
2 2
3int Npages = 21; 3int Npages = 22;
4 4
5char *helppages[][10] = { 5char *helppages[][10] = {
6 6
@@ -67,6 +67,50 @@ Resets all saved scrambles and output sequences.\n\
67" 67"
68}, 68},
69 69
70{ "co",
71"\
72\n\
73HELP PAGE FOR COMMAND co\n\
74\n\
75SYNTAX\n\
76co [OPTIONS] [MOVES|$ID|@ID]\n\
77\n\
78DESCRIPTION\n\
79Solves CO for a given scramble. A scramble can be given as last argument of the\n\
80command, or an ID of a saved scramble can be provided. If none of the two is\n\
81given, a prompt will ask the user to input a new scramble.\n\
82\n\
83OPTIONS\n\
84axis={fb,rl,ud} Specify the axis for the CO. One to three axes can be given,\n\
85 comma separated, no spaces.\n\
86 Default: CO on any of the three axis (omitting the option is\n\
87 the same as specifying axis=fb,rl,ud).\n\
88b=N Specify a bound for the number of moves. N must be a number.\n\
89 Default value: 20.\n\
90h Show hidden COs.\n\
91 Default, if an CO ending in e.g. F is shown, the equivalent\n\
92 one ending in F' is hidden.\n\
93i Ignore centers. By default the CO is aligned with centers.\n\
94niss Use NISS.\n\
95 Default: does not use NISS.\n\
96n=N Specify a maximum number of COs to be output. N must be a\n\
97 number.\n\
98 Default value: 1.\n\
99\n\
100EXAMPLES\n\
101co axis=fb $1\n\
102 Finds one optimal CO on fb for the first saved scramble.\n\
103\n\
104co n=5 b=4 U R F \n\
105 Finds up to 5 COs of length at most 4 for scramble U R F.\n\
106\n\
107co n=100 b=5 niss axis=fb,ud h R' U' F L R'U'F\n\
108 Finds up to 100 COs of lenth at most 4, possibly using NISS, including\n\
109 \"hidden\" COs, excluding the rl axis.\n\
110\n\
111"
112},
113
70{ "dr", 114{ "dr",
71"\ 115"\
72\n\ 116\n\
diff --git a/src/main.c b/src/main.c
index 5bed343..a14e365 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,51 +8,6 @@
8#include "solver.h" 8#include "solver.h"
9#include "string.h" 9#include "string.h"
10#include "helppages.h" 10#include "helppages.h"
11
12char *commands[][10] = {
13 {"help", "[COMMAND]",
14 "Print this help, or a help page for COMMAND."},
15 {"scramble", "[OPTIONS]",
16 "Prints a random-state scramble."},
17 {"save", "[MOVES|@ID|$ID]",
18 "Save or copy a scramble."},
19 {"change", "$ID1 [MOVES|$ID2|@ID2]",
20 "Change a memorized scramble."},
21 {"print", "[$ID|@ID]",
22 "Print memorized sequences."},
23 {"add", "[MOVES|$ID1|@ID1] $ID2",
24 "Add moves at the end of a memorized scramble."},
25 {"invert", "[MOVES|$ID|@ID]",
26 "Inverts the given sequence of moves."},
27 {"unniss", "[MOVES|$ID|@ID]}",
28 "Removes NISS: A (B) -> B\' A."},
29 {"pic", "[MOVES|$ID|@ID]",
30 "Show a text description of the scrambled cube."},
31 {"solve", "[MOVES|$ID|@ID]",
32 "Solves a scramble."},
33 {"replace", "[MOVES|$ID|@ID]",
34 "Find non-optimal subsequences."},
35 {"clear", "",
36 "Delete saved scrambles and output sequences."},
37 {"eo", "[MOVES|$ID|@ID]",
38 "Solves EO."},
39 {"dr", "[MOVES|$ID|@ID]",
40 "Solves DR, either directly or from eo."},
41 {"htr", "[MOVES|$ID|@ID]",
42 "Solves HTR from DR."},
43 {"drfinish", "[MOVES|$ID|@ID]",
44 "Solves the cube after DR."},
45 {"htrfinish", "[MOVES|$ID|@ID]",
46 "Solves the cube using only half turns."},
47 {"drcorners", "[MOVES|$ID|@ID]",
48 "Solves corners after DR."},
49 {"exit", "",
50 "Exit nissy."},
51 {"quit", "",
52 "Exit nissy."},
53 {"", "", ""}
54};
55
56/* Saved sequences of moves */ 11/* Saved sequences of moves */
57int scr_count=1, tmp_count=1, max_tmp=999; 12int scr_count=1, tmp_count=1, max_tmp=999;
58int scrambles[255][255], tmp[1000][255]; 13int scrambles[255][255], tmp[1000][255];
@@ -122,28 +77,6 @@ int parsecmd(char *cmd, char cmdtok[][100]) {
122 return n; 77 return n;
123} 78}
124 79
125void help_cmd(int n, char cmdtok[][100]) {
126 if (n == 1) {
127 printf("\n");
128 for (int i = 0; commands[i][0][0]; i++)
129 printf("%-10s%-25s%s\n", commands[i][0], commands[i][1], commands[i][2]);
130 printf("\n");
131 printf("Type \'help\' followed by a command for a detailed help page.\n");
132 printf("Type \'help nissy\' for a general user guide.\n");
133 } else if (n == 2) {
134 for (int i = 0; i < Npages; i++) {
135 if (!strcmp(helppages[i][0], cmdtok[1])) {
136 printf("%s", helppages[i][1]);
137 return;
138 }
139 }
140 printf("No help page for %s.\n", cmdtok[1]);
141 return;
142 } else {
143 printf("help: wrong syntax.\n");
144 }
145}
146
147void scramble_cmd(int n, char cmdtok[][100]) { 80void scramble_cmd(int n, char cmdtok[][100]) {
148 int c = 0, e = 0, dr = 0; 81 int c = 0, e = 0, dr = 0;
149 82
@@ -528,6 +461,69 @@ void eo_cmd(int n, char cmdtok[][100]) {
528 print_results(neo, eo_list); 461 print_results(neo, eo_list);
529} 462}
530 463
464void co_cmd(int n, char cmdtok[][100]) {
465
466 /* Default values */
467 int m = 1, b = 20, ignore = 0;
468 int niss = 0, hide = 1;
469 int fb = 1, rl = 1, ud = 1;
470 int scram[255] = {[0] = 0};
471 int scram_unnissed[255];
472
473 /* Parse options */
474 for (int i = 1; i < n && scram[0] == 0; i++) {
475 if (!strcmp(cmdtok[i], "h")) {
476 hide = 0;
477 } else if (!strcmp(cmdtok[i], "niss")) {
478 niss = 1;
479 } else if (!strcmp(cmdtok[i], "i")) {
480 ignore = 1;
481 } else if (!strncmp(cmdtok[i], "axis=", 5)) {
482 fb = rl = ud = 0;
483 if (strstr(cmdtok[i], "fb") != NULL)
484 fb = 1;
485 if (strstr(cmdtok[i], "rl") != NULL)
486 rl = 1;
487 if (strstr(cmdtok[i], "ud") != NULL)
488 ud = 1;
489 if (fb + rl + ud == 0) {
490 printf("co: bad axis option.\n");
491 return;
492 }
493 } else if (!strncmp(cmdtok[i], "n=", 2)) {
494 m = atoi(cmdtok[i]+2);
495 if (m <= 0) {
496 printf("co: bad option n.\n");
497 return;
498 }
499 } else if (!strncmp(cmdtok[i], "b=", 2)) {
500 b = atoi(cmdtok[i]+2);
501 if (b <= 0) {
502 printf("co: bad option b.\n");
503 return;
504 }
505 } else if (read_moves_from_argument(n-i, cmdtok+i, scram) == -1) {
506 printf("co: error reading moves or ID.\n");
507 return;
508 }
509 }
510
511 if (scram[0] == 0) {
512 if (read_moves_from_prompt(scram) == -1) {
513 printf("co: error reading moves.\n");
514 return;
515 }
516 }
517
518 unniss(scram, scram_unnissed);
519
520 /* Call solver and print results */
521 int co_list[m+5][30];
522 int nco = co_scram_spam(scram_unnissed, co_list, fb, rl, ud, m, b, niss,
523 hide, ignore);
524 print_results(nco, co_list);
525}
526
531void dr_cmd(int n, char cmdtok[][100]) { 527void dr_cmd(int n, char cmdtok[][100]) {
532 528
533 /* Default values */ 529 /* Default values */
@@ -763,7 +759,7 @@ void htrfinish_cmd(int n, char cmdtok[][100]) {
763 759
764void drcorners_cmd(int n, char cmdtok[][100]) { 760void drcorners_cmd(int n, char cmdtok[][100]) {
765 /* Default values */ 761 /* Default values */
766 int m = 1, b = 20, ignore=0; 762 int m = 1, b = 20, ignore = 0;
767 int from = 0; /* 0: unspecified; {1,2,3}: from {ud,fb,rl} */ 763 int from = 0; /* 0: unspecified; {1,2,3}: from {ud,fb,rl} */
768 int scram[255] = {[0] = 0}; 764 int scram[255] = {[0] = 0};
769 int scram_unnissed[255]; 765 int scram_unnissed[255];
@@ -823,15 +819,89 @@ void exit_quit_cmd(int n, char cmdtok[][100]) {
823 printf("%s: wrong synstax.\n", cmdtok[0]); 819 printf("%s: wrong synstax.\n", cmdtok[0]);
824} 820}
825 821
822/***************************************************************/
823/* List of all commands */
824/* Important: they must be in the same order in the two arrays */
825/***************************************************************/
826
827char *commands[][10] = {
828 {"help", "[COMMAND]",
829 "Print this help, or a help page for COMMAND."},
830 {"scramble", "[OPTIONS]",
831 "Prints a random-state scramble."},
832 {"save", "[MOVES|@ID|$ID]",
833 "Save or copy a scramble."},
834 {"change", "$ID1 [MOVES|$ID2|@ID2]",
835 "Change a memorized scramble."},
836 {"print", "[$ID|@ID]",
837 "Print memorized sequences."},
838 {"add", "[MOVES|$ID1|@ID1] $ID2",
839 "Add moves at the end of a memorized scramble."},
840 {"invert", "[MOVES|$ID|@ID]",
841 "Inverts the given sequence of moves."},
842 {"unniss", "[MOVES|$ID|@ID]}",
843 "Removes NISS: A (B) -> B\' A."},
844 {"pic", "[MOVES|$ID|@ID]",
845 "Show a text description of the scrambled cube."},
846 {"solve", "[MOVES|$ID|@ID]",
847 "Solves a scramble."},
848 {"replace", "[MOVES|$ID|@ID]",
849 "Find non-optimal subsequences."},
850 {"clear", "",
851 "Delete saved scrambles and output sequences."},
852 {"eo", "[MOVES|$ID|@ID]",
853 "Solves EO."},
854 {"co", "[MOVES|$ID|@ID]",
855 "Solves CO."},
856 {"dr", "[MOVES|$ID|@ID]",
857 "Solves DR, either directly or from eo."},
858 {"htr", "[MOVES|$ID|@ID]",
859 "Solves HTR from DR."},
860 {"drfinish", "[MOVES|$ID|@ID]",
861 "Solves the cube after DR."},
862 {"htrfinish", "[MOVES|$ID|@ID]",
863 "Solves the cube using only half turns."},
864 {"drcorners", "[MOVES|$ID|@ID]",
865 "Solves corners after DR."},
866 {"exit", "",
867 "Exit nissy."},
868 {"quit", "",
869 "Exit nissy."},
870 {"", "", ""}
871};
872
873void help_cmd(int n, char cmdtok[][100]) {
874 if (n == 1) {
875 printf("\n");
876 for (int i = 0; commands[i][0][0]; i++)
877 printf("%-10s%-25s%s\n", commands[i][0], commands[i][1], commands[i][2]);
878 printf("\n");
879 printf("Type \'help\' followed by a command for a detailed help page.\n");
880 printf("Type \'help nissy\' for a general user guide.\n");
881 } else if (n == 2) {
882 for (int i = 0; i < Npages; i++) {
883 if (!strcmp(helppages[i][0], cmdtok[1])) {
884 printf("%s", helppages[i][1]);
885 return;
886 }
887 }
888 printf("No help page for %s.\n", cmdtok[1]);
889 return;
890 } else {
891 printf("help: wrong syntax.\n");
892 }
893}
894
826void (*cmd_list[])(int n, char cmdtok[][100]) = { 895void (*cmd_list[])(int n, char cmdtok[][100]) = {
827 help_cmd, scramble_cmd, save_cmd, change_cmd, print_cmd, 896 help_cmd, scramble_cmd, save_cmd, change_cmd, print_cmd,
828 add_cmd, invert_cmd, unniss_cmd, pic_cmd, 897 add_cmd, invert_cmd, unniss_cmd, pic_cmd,
829 solve_cmd, replace_cmd, clear_cmd, 898 solve_cmd, replace_cmd, clear_cmd,
830 eo_cmd, dr_cmd, htr_cmd, 899 eo_cmd, co_cmd, dr_cmd, htr_cmd,
831 drfinish_cmd, htrfinish_cmd, drcorners_cmd, 900 drfinish_cmd, htrfinish_cmd, drcorners_cmd,
832 exit_quit_cmd, exit_quit_cmd, NULL 901 exit_quit_cmd, exit_quit_cmd, NULL
833}; 902};
834 903
904
835void execcmd(int n, char cmdtok[][100]) { 905void execcmd(int n, char cmdtok[][100]) {
836 int i = 0; 906 int i = 0;
837 while (strcmp(commands[i][0], cmdtok[0]) && strcmp(commands[i][0], "")) 907 while (strcmp(commands[i][0], cmdtok[0]) && strcmp(commands[i][0], ""))
@@ -842,6 +912,9 @@ void execcmd(int n, char cmdtok[][100]) {
842 printf("%s: not a command.\n", cmdtok[0]); 912 printf("%s: not a command.\n", cmdtok[0]);
843} 913}
844 914
915
916/* Main loop */
917
845int main() { 918int main() {
846 init_transition_table(); 919 init_transition_table();
847 init_possible_next(); 920 init_possible_next();
diff --git a/src/solver.c b/src/solver.c
index 82abd85..48e845f 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -107,6 +107,88 @@ int eo_scram_spam(int scram[], int eo_list[][30], int fb, int rl, int ud,
107} 107}
108 108
109 109
110/******/
111/* CO */
112/******/
113void niss_co_dfs(int co, int scramble[], int co_list[][30], int *co_count,
114 int t_table[pow3to7][19], int p_table[pow3to7],
115 int last1, int last2, int moves, int m, int d, int niss,
116 int can_use_niss, int hide, int ignore) {
117
118
119 if (*co_count >= m || moves > d ||
120 ((!can_use_niss || niss) && ((!ignore && moves + p_table[co] > d) ||
121 ( ignore && moves + p_table[co] - 2 > d))))
122 return;
123
124 co_list[*co_count][moves] = 0;
125
126 if (co == 0 || (ignore && ( t_table[t_table[co][F]][B] == 0 ||
127 t_table[t_table[co][R]][L] == 0 ||
128 t_table[t_table[co][U]][D] == 0 ))) {
129 /* If an early CO is found, or if "case F2 B", or if hide is on. */
130 if (moves != d || (parallel(last1, last2) && last2 % 3 == 2) ||
131 (hide && moves > 0 &&
132 (last1 % 3 == 0 || (parallel(last1, last2) && last2 % 3 == 0))))
133 return;
134 /* Copy moves for the next solution */
135 if (*co_count < m - 1)
136 copy_moves(co_list[*co_count], co_list[(*co_count)+1]);
137 (*co_count)++;
138 return;
139 }
140
141 for (int i = 1; i < 19; i++) {
142 if (possible_next[last1][last2] & (1 << i)) {
143 co_list[*co_count][moves] = niss ? -i : i;
144 niss_co_dfs(t_table[co][i], scramble, co_list, co_count, t_table,
145 p_table, i, last1, moves+1, m, d, niss,
146 can_use_niss, hide, ignore);
147 }
148 }
149
150 if (*co_count >= m)
151 return;
152 co_list[*co_count][moves] = 0;
153
154 /* If not nissing already and we either have not done any move yet or
155 * the last move was F/F' etc, and if I am allowed to niss, try niss! */
156 if (!niss && (last1 == 0 || t_table[0][last1] != 0) && can_use_niss &&
157 !(hide && moves > 0 &&
158 (last1 % 3 == 0 || (parallel(last1, last2) && last2 % 3 == 0)))) {
159 int aux[] = {0,0};
160 niss_co_dfs(premoves_inverse(co_list[*co_count], scramble, aux, t_table),
161 scramble, co_list, co_count, t_table, p_table,
162 0, 0, moves, m, d, 1, can_use_niss, hide, ignore);
163 }
164}
165
166int co_scram_spam(int scram[], int co_list[][30], int fb, int rl, int ud,
167 int m, int b, int niss, int h, int ignore) {
168
169 init_small_pruning_tables();
170
171 int n = 0, cofb = 0, corl = 0, coud = 0;
172 for (int i = 0; scram[i]; i++) {
173 cofb = cofb_transition_table[cofb][scram[i]];
174 corl = corl_transition_table[corl][scram[i]];
175 coud = coud_transition_table[coud][scram[i]];
176 }
177 for (int i = 0; i <= b; i++) {
178 if (fb)
179 niss_co_dfs(cofb, scram, co_list, &n, cofb_transition_table,
180 cofb_pruning_table, 0, 0, 0, m, i, 0, niss, h, ignore);
181 if (rl)
182 niss_co_dfs(corl, scram, co_list, &n, corl_transition_table,
183 corl_pruning_table, 0, 0, 0, m, i, 0, niss, h, ignore);
184 if (ud)
185 niss_co_dfs(coud, scram, co_list, &n, coud_transition_table,
186 coud_pruning_table, 0, 0, 0, m, i, 0, niss, h, ignore);
187 }
188 return n;
189}
190
191
110/**************/ 192/**************/
111/* DR from EO */ 193/* DR from EO */
112/**************/ 194/**************/
@@ -600,10 +682,20 @@ void dr_corners_dfs(int cp, int sol[][30], int *sol_count,
600 682
601 sol[*sol_count][moves] = 0; 683 sol[*sol_count][moves] = 0;
602 684
603 if (cp == 0 || (ignore && 685 if (cp == 0 ||
686 (ignore && mask == move_mask_drud &&
604 (cp_transition_table[cp_transition_table[cp][U]][D3] == 0 || 687 (cp_transition_table[cp_transition_table[cp][U]][D3] == 0 ||
605 cp_transition_table[cp_transition_table[cp][U2]][D2] == 0 || 688 cp_transition_table[cp_transition_table[cp][U2]][D2] == 0 ||
606 cp_transition_table[cp_transition_table[cp][U3]][D] == 0 ))) { 689 cp_transition_table[cp_transition_table[cp][U3]][D] == 0 )) ||
690 (ignore && mask == move_mask_drfb &&
691 (cp_transition_table[cp_transition_table[cp][F]][B3] == 0 ||
692 cp_transition_table[cp_transition_table[cp][F2]][B2] == 0 ||
693 cp_transition_table[cp_transition_table[cp][F3]][B] == 0 )) ||
694 (ignore && mask == move_mask_drrl &&
695 (cp_transition_table[cp_transition_table[cp][R]][L3] == 0 ||
696 cp_transition_table[cp_transition_table[cp][R2]][L2] == 0 ||
697 cp_transition_table[cp_transition_table[cp][R3]][L] == 0 ))
698 ) {
607 if (moves != d) 699 if (moves != d)
608 return; 700 return;
609 /* Copy moves for the next solution */ 701 /* Copy moves for the next solution */
diff --git a/src/solver.h b/src/solver.h
index d154c8f..abb55d3 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -1,5 +1,7 @@
1int eo_scram_spam(int scram[], int eo_list[][30], int fb, int rl, int ud, 1int eo_scram_spam(int scram[], int eo_list[][30], int fb, int rl, int ud,
2 int m, int b, int niss, int h); 2 int m, int b, int niss, int h);
3int co_scram_spam(int scram[], int co_list[][30], int fb, int rl, int ud,
4 int m, int b, int niss, int h, int i);
3int dr_scram_spam(int scram[], int dr_list[][30], int fb, int rl, int ud, 5int dr_scram_spam(int scram[], int dr_list[][30], int fb, int rl, int ud,
4 int m, int b, int h); 6 int m, int b, int h);
5int drfrom_scram_spam(int scram[], int dr_list[][30], int from, int fb, 7int drfrom_scram_spam(int scram[], int dr_list[][30], int from, int fb,

Generated with cgit - Back to sebastiano.tronto.net