diff options
| author | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2020-07-12 20:44:09 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2020-07-12 20:44:09 +0200 |
| commit | e1ebff51092baf5581b728baec05c52c4bb3445e (patch) | |
| tree | 8e3cc3fa0cf10bbe35a3bacfba8e1d96f850b058 | |
| parent | 0fe7c8b43c50ae5701463acbb186a6fe0f53a773 (diff) | |
| download | nissy-e1ebff51092baf5581b728baec05c52c4bb3445e.tar.gz nissy-e1ebff51092baf5581b728baec05c52c4bb3445e.zip | |
Added feature: scramble
| -rwxr-xr-x | nissy | bin | 504736 -> 518520 bytes | |||
| -rw-r--r-- | src/main.c | 29 | ||||
| -rw-r--r-- | src/solver.c | 100 | ||||
| -rw-r--r-- | src/solver.h | 1 | ||||
| -rw-r--r-- | src/utils.c | 17 | ||||
| -rw-r--r-- | src/utils.h | 4 |
6 files changed, 135 insertions, 16 deletions
| Binary files differ | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | /* blabla */ | 1 | /* blabla */ |
| 2 | #include <stdio.h> | 2 | #include <stdio.h> |
| 3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
| 4 | #include <time.h> | ||
| 4 | #include "utils.h" | 5 | #include "utils.h" |
| 5 | #include "coordinates.h" | 6 | #include "coordinates.h" |
| 6 | #include "io.h" | 7 | #include "io.h" |
| @@ -11,6 +12,8 @@ | |||
| 11 | char *commands[][10] = { | 12 | char *commands[][10] = { |
| 12 | {"help", "[COMMAND]", | 13 | {"help", "[COMMAND]", |
| 13 | "Print this help, or a help page for COMMAND."}, | 14 | "Print this help, or a help page for COMMAND."}, |
| 15 | {"scramble", "", | ||
| 16 | "Prints a random-state scramble"}, | ||
| 14 | {"save", "[MOVES|@ID|$ID]", | 17 | {"save", "[MOVES|@ID|$ID]", |
| 15 | "Save or copy a scramble."}, | 18 | "Save or copy a scramble."}, |
| 16 | {"change", "$ID1 [MOVES|$ID2|@ID2]", | 19 | {"change", "$ID1 [MOVES|$ID2|@ID2]", |
| @@ -141,6 +144,28 @@ void help_cmd(int n, char cmdtok[][100]) { | |||
| 141 | } | 144 | } |
| 142 | } | 145 | } |
| 143 | 146 | ||
| 147 | void scramble_cmd(int n, char cmdtok[][100]) { | ||
| 148 | if (n > 1 || cmdtok[0][0] != 's') { /* Second case avoids warning */ | ||
| 149 | printf("scramble: wrong syntax\n"); | ||
| 150 | return; | ||
| 151 | } | ||
| 152 | |||
| 153 | srand(time(NULL)); | ||
| 154 | int eofb = rand() % pow2to11; | ||
| 155 | int coud = rand() % pow3to7; | ||
| 156 | int ep = rand() % factorial12; | ||
| 157 | int cp = rand() % factorial8; | ||
| 158 | while (perm_sign_int(ep, 12) != perm_sign_int(cp, 8)) | ||
| 159 | ep = (ep+1) % factorial12; | ||
| 160 | |||
| 161 | /* Debug */ | ||
| 162 | /* printf("State: %d %d %d %d\n", eofb, coud, ep, cp); */ | ||
| 163 | |||
| 164 | int scram[2][30]; | ||
| 165 | reach_state(eofb, coud, ep, cp, scram); | ||
| 166 | print_results(1, scram); | ||
| 167 | } | ||
| 168 | |||
| 144 | void save_cmd(int n, char cmdtok[][100]) { | 169 | void save_cmd(int n, char cmdtok[][100]) { |
| 145 | int scram[255]; | 170 | int scram[255]; |
| 146 | if (n == 1) { | 171 | if (n == 1) { |
| @@ -534,7 +559,7 @@ void dr_cmd(int n, char cmdtok[][100]) { | |||
| 534 | int dr_list[m+5][30], ndr; | 559 | int dr_list[m+5][30], ndr; |
| 535 | if (from) { | 560 | if (from) { |
| 536 | ndr = drfrom_scram_spam(scram_unnissed, dr_list, from, fb, rl, ud, | 561 | ndr = drfrom_scram_spam(scram_unnissed, dr_list, from, fb, rl, ud, |
| 537 | m, b, niss, hide); | 562 | m, b, niss, hide); |
| 538 | if (ndr == -1) { | 563 | if (ndr == -1) { |
| 539 | printf("dr: from given, but EO not found (possibly other error).\n"); | 564 | printf("dr: from given, but EO not found (possibly other error).\n"); |
| 540 | return; | 565 | return; |
| @@ -761,7 +786,7 @@ void exit_quit_cmd(int n, char cmdtok[][100]) { | |||
| 761 | } | 786 | } |
| 762 | 787 | ||
| 763 | void (*cmd_list[])(int n, char cmdtok[][100]) = { | 788 | void (*cmd_list[])(int n, char cmdtok[][100]) = { |
| 764 | help_cmd, save_cmd, change_cmd, print_cmd, | 789 | help_cmd, scramble_cmd, save_cmd, change_cmd, print_cmd, |
| 765 | add_cmd, invert_cmd, unniss_cmd, pic_cmd, | 790 | add_cmd, invert_cmd, unniss_cmd, pic_cmd, |
| 766 | solve_cmd, replace_cmd, | 791 | solve_cmd, replace_cmd, |
| 767 | eo_cmd, dr_cmd, htr_cmd, | 792 | eo_cmd, dr_cmd, htr_cmd, |
diff --git a/src/solver.c b/src/solver.c index d918a54..c61aec4 100644 --- a/src/solver.c +++ b/src/solver.c | |||
| @@ -463,11 +463,11 @@ int dr_scram_spam(int scram[], int dr_list[][30], int fb, int rl, int ud, | |||
| 463 | /* DR finish */ | 463 | /* DR finish */ |
| 464 | /*************/ | 464 | /*************/ |
| 465 | void dr_finish_dfs(int cp, int ep8, int ep4, int sol[][30], int *sol_count, | 465 | void dr_finish_dfs(int cp, int ep8, int ep4, int sol[][30], int *sol_count, |
| 466 | int ep8_t_table[factorial8][19], | 466 | int ep8_t_table[factorial8][19], |
| 467 | int ep4_t_table[factorial4][19], | 467 | int ep4_t_table[factorial4][19], |
| 468 | int cp_p_table[factorial8], | 468 | int cp_p_table[factorial8], |
| 469 | int ep8_p_table[factorial8], | 469 | int ep8_p_table[factorial8], |
| 470 | int mask, int last1, int last2, int moves, int m, int d) { | 470 | int mask, int last1, int last2, int moves, int m, int d) { |
| 471 | 471 | ||
| 472 | 472 | ||
| 473 | if (*sol_count >= m || moves + cp_p_table[cp] > d || | 473 | if (*sol_count >= m || moves + cp_p_table[cp] > d || |
| @@ -717,7 +717,7 @@ void small_optimal_dfs(int eofb, int eorl, int eoud, int ep, | |||
| 717 | } | 717 | } |
| 718 | } | 718 | } |
| 719 | 719 | ||
| 720 | /* Solves directly using only medium tables. Suitable for short solutions. */ | 720 | /* Solves directly using only medium tables. Suitable for short solutions. |
| 721 | void medium_optimal_dfs(int eofb, int eorl, int eoud, | 721 | void medium_optimal_dfs(int eofb, int eorl, int eoud, |
| 722 | int epose, int eposs, int eposm, int ep, | 722 | int epose, int eposs, int eposm, int ep, |
| 723 | int coud, int cofb, int corl, int cp, | 723 | int coud, int cofb, int corl, int cp, |
| @@ -766,6 +766,7 @@ void medium_optimal_dfs(int eofb, int eorl, int eoud, | |||
| 766 | } | 766 | } |
| 767 | } | 767 | } |
| 768 | } | 768 | } |
| 769 | */ | ||
| 769 | 770 | ||
| 770 | /* Uses huge tables */ | 771 | /* Uses huge tables */ |
| 771 | int optimal_dfs(int ep, int cp, int eo, int co, int emslices, | 772 | int optimal_dfs(int ep, int cp, int eo, int co, int emslices, |
| @@ -836,14 +837,6 @@ int solve_scram(int scram[], int sol[][30], int m, int b, int optimal) { | |||
| 836 | if (n >= m || b <= 10) | 837 | if (n >= m || b <= 10) |
| 837 | return n; | 838 | return n; |
| 838 | 839 | ||
| 839 | /* Then we try a slightly larger optimal solver */ | ||
| 840 | /* | ||
| 841 | int max_medium = 11; | ||
| 842 | init_directdr_pruning_tables(); | ||
| 843 | for (int i = 0; i <= min(b, max_medium); i++) | ||
| 844 | medium_optimal_dfs(eofb, eorl, eoud, epose, eposs, eposm, ep, | ||
| 845 | coud, cofb, corl, cp, sol, &n, 0, 0, 0, m, i); | ||
| 846 | */ | ||
| 847 | 840 | ||
| 848 | /* If we found at least a solution, we return */ | 841 | /* If we found at least a solution, we return */ |
| 849 | if (n > 0) | 842 | if (n > 0) |
| @@ -891,3 +884,82 @@ int solve_scram(int scram[], int sol[][30], int m, int b, int optimal) { | |||
| 891 | } | 884 | } |
| 892 | return best > b ? 0 : 1; | 885 | return best > b ? 0 : 1; |
| 893 | } | 886 | } |
| 887 | |||
| 888 | /* Given eofb, coud, ep and cp it finds a scramble that reaches that state. | ||
| 889 | * It uses a simple 3-step solver to find a preliminary "solution", and then | ||
| 890 | * gives this solutions as a scramble to a better solver (see above). */ | ||
| 891 | int reach_state(int eofb, int coud, int ep, int cp, int sol[][30]) { | ||
| 892 | |||
| 893 | int fake_count = 0, fake_scram[30]; | ||
| 894 | int eo_list[2][30], dr_list[2][30], finish_list[2][30]; | ||
| 895 | |||
| 896 | /* Convert ep to array */ | ||
| 897 | int ep_arr[12]; | ||
| 898 | ep_int_to_array(ep, ep_arr); | ||
| 899 | |||
| 900 | /* Find EO */ | ||
| 901 | init_small_pruning_tables(); | ||
| 902 | for (int d = 0; d < 10; d++) { | ||
| 903 | niss_eo_dfs(eofb, fake_scram, eo_list, &fake_count, eofb_transition_table, | ||
| 904 | eofb_pruning_table, 0, 0, 0, 1, d, 0, 0, 0); | ||
| 905 | if (fake_count) { | ||
| 906 | fake_count = 0; | ||
| 907 | break; | ||
| 908 | } | ||
| 909 | } | ||
| 910 | |||
| 911 | /* Apply moves found, find epose */ | ||
| 912 | for (int i = 0; eo_list[0][i]; i++) { | ||
| 913 | coud = coud_transition_table[coud][eo_list[0][i]]; | ||
| 914 | cp = cp_transition_table[cp][eo_list[0][i]]; | ||
| 915 | apply_move_ep_array(eo_list[0][i], ep_arr); | ||
| 916 | } | ||
| 917 | int epose = epose_array_to_int(ep_arr); | ||
| 918 | |||
| 919 | /* Find DR */ | ||
| 920 | init_drfromeo_pruning_tables(); | ||
| 921 | for (int d = 0; d < 16; d++) { | ||
| 922 | niss_dr_from_eo_dfs(coud, epose, fake_scram, fake_scram, dr_list, | ||
| 923 | &fake_count, coud_transition_table, | ||
| 924 | epose_transition_table, | ||
| 925 | coud_epose_from_eofb_pruning_table, move_mask_eofb, | ||
| 926 | 0, 0, 0, 0, 0, 1, d, 0, 0, 0); | ||
| 927 | if (fake_count) { | ||
| 928 | fake_count = 0; | ||
| 929 | break; | ||
| 930 | } | ||
| 931 | } | ||
| 932 | |||
| 933 | /* Apply moves found, find epud and epe */ | ||
| 934 | for (int i = 0; dr_list[0][i]; i++) { | ||
| 935 | cp = cp_transition_table[cp][dr_list[0][i]]; | ||
| 936 | apply_move_ep_array(dr_list[0][i], ep_arr); | ||
| 937 | } | ||
| 938 | int epud = epud_array_to_int(ep_arr); | ||
| 939 | int epe = epe_array_to_int(ep_arr); | ||
| 940 | |||
| 941 | /* Find finish */ | ||
| 942 | init_small_pruning_tables(); | ||
| 943 | for (int d = 0; d < 16; d++) { | ||
| 944 | dr_finish_dfs(cp, epud, epe, finish_list, &fake_count, | ||
| 945 | epud_transition_table, epe_transition_table, | ||
| 946 | cp_drud_pruning_table, epud_pruning_table, move_mask_drud, | ||
| 947 | 0, 0, 0, 1, d); | ||
| 948 | if (fake_count) { | ||
| 949 | fake_count = 0; | ||
| 950 | break; | ||
| 951 | } | ||
| 952 | } | ||
| 953 | |||
| 954 | int scram[50]; | ||
| 955 | |||
| 956 | /* Debug */ | ||
| 957 | /*print_moves(eo_list[0]); printf("\n"); | ||
| 958 | print_moves(dr_list[0]); printf("\n"); | ||
| 959 | print_moves(finish_list[0]); printf("\n");*/ | ||
| 960 | |||
| 961 | copy_moves(eo_list[0], scram); | ||
| 962 | append_moves(dr_list[0], scram); | ||
| 963 | append_moves(finish_list[0], scram); | ||
| 964 | return solve_scram(scram, sol, 1, 25, 0); | ||
| 965 | } | ||
diff --git a/src/solver.h b/src/solver.h index 14997ed..d154c8f 100644 --- a/src/solver.h +++ b/src/solver.h | |||
| @@ -11,3 +11,4 @@ int dr_corners_scram_spam(int scram[], int sol[][30], int from, int m, int b, | |||
| 11 | int dr_finish_scram_spam(int scram[], int sol[][30], int from, int m, int b); | 11 | int dr_finish_scram_spam(int scram[], int sol[][30], int from, int m, int b); |
| 12 | int htr_finish_scram_spam(int scram[], int sol[][30], int m, int b); | 12 | int htr_finish_scram_spam(int scram[], int sol[][30], int m, int b); |
| 13 | int solve_scram(int scram[], int sol[][30], int m, int b, int optimal); | 13 | int solve_scram(int scram[], int sol[][30], int m, int b, int optimal); |
| 14 | int reach_state(int eofb, int coud, int ep, int cp, int sol[][30]); | ||
diff --git a/src/utils.c b/src/utils.c index c672453..5b7df06 100644 --- a/src/utils.c +++ b/src/utils.c | |||
| @@ -65,6 +65,23 @@ void index_to_perm(int p, int n, int *r) { | |||
| 65 | } | 65 | } |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | |||
| 69 | int perm_sign_array(int a[], int n) { | ||
| 70 | int ret = 0; | ||
| 71 | for (int i = 0; i < n; i++) | ||
| 72 | for (int j = i+1; j < n; j++) | ||
| 73 | if (a[i]>a[j]) | ||
| 74 | ret++; | ||
| 75 | return ret % 2; | ||
| 76 | } | ||
| 77 | |||
| 78 | int perm_sign_int(int p, int n) { | ||
| 79 | int a[n]; | ||
| 80 | index_to_perm(p, n, a); | ||
| 81 | return perm_sign_array(a, n); | ||
| 82 | } | ||
| 83 | |||
| 84 | |||
| 68 | /* Converts a k-element subset of a set with an element from an array of n | 85 | /* Converts a k-element subset of a set with an element from an array of n |
| 69 | * elements, of which k are 1 (or just non-zero) and n-k are 0, to its index | 86 | * elements, of which k are 1 (or just non-zero) and n-k are 0, to its index |
| 70 | * in the sorted list of all such subsets. | 87 | * in the sorted list of all such subsets. |
diff --git a/src/utils.h b/src/utils.h index b24ccb2..45a6302 100644 --- a/src/utils.h +++ b/src/utils.h | |||
| @@ -36,6 +36,10 @@ int perm_to_index(int *a, int n); | |||
| 36 | * (see perm_to_index) and saves the result to r. */ | 36 | * (see perm_to_index) and saves the result to r. */ |
| 37 | void index_to_perm(int p, int n, int *r); | 37 | void index_to_perm(int p, int n, int *r); |
| 38 | 38 | ||
| 39 | /* Determine the sign of a permutation, either in integer or array format. */ | ||
| 40 | int perm_sign_array(int a[], int n); | ||
| 41 | int perm_sign_int(int p, int n); | ||
| 42 | |||
| 39 | /* Converts a k-element subset of a set with an element from an array of n | 43 | /* Converts a k-element subset of a set with an element from an array of n |
| 40 | * elements, of which k are 1 and n-k are 0, to its index in the sorted list | 44 | * elements, of which k are 1 and n-k are 0, to its index in the sorted list |
| 41 | * of all such subsets. | 45 | * of all such subsets. |
