diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2024-07-04 17:09:55 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2024-07-04 17:09:55 +0200 |
| commit | 518d98ad5f9eec0cf4124375bdbb84d1296b3f3f (patch) | |
| tree | 467b2b0387f23a0b379cf428c6883937ec18c134 /src | |
| parent | 425eee24421bf0a19c7e0199d2e3ecba3318c8f4 (diff) | |
| download | nissy-core-518d98ad5f9eec0cf4124375bdbb84d1296b3f3f.tar.gz nissy-core-518d98ad5f9eec0cf4124375bdbb84d1296b3f3f.zip | |
(almost) added getcube
Diffstat (limited to '')
| -rw-r--r-- | src/constants.h | 4 | ||||
| -rw-r--r-- | src/cube.c | 1 | ||||
| -rw-r--r-- | src/cube.h | 7 | ||||
| -rw-r--r-- | src/cube_generic.h | 59 | ||||
| -rw-r--r-- | src/cube_public.h | 30 | ||||
| -rw-r--r-- | src/io_cube.h | 11 | ||||
| -rw-r--r-- | src/utils.h | 125 |
7 files changed, 205 insertions, 32 deletions
diff --git a/src/constants.h b/src/constants.h index c8909d7..52e2810 100644 --- a/src/constants.h +++ b/src/constants.h | |||
| @@ -2,10 +2,14 @@ | |||
| 2 | #define _bit_u32(i) (UINT32_C(1) << (uint32_t)(i)) | 2 | #define _bit_u32(i) (UINT32_C(1) << (uint32_t)(i)) |
| 3 | #define _bit_u64(i) (UINT64_C(1) << (uint64_t)(i)) | 3 | #define _bit_u64(i) (UINT64_C(1) << (uint64_t)(i)) |
| 4 | 4 | ||
| 5 | #define _max_factorial INT64_C(12) | ||
| 6 | |||
| 5 | #define _2p11 INT64_C(2048) | 7 | #define _2p11 INT64_C(2048) |
| 6 | #define _2p12 INT64_C(4096) | 8 | #define _2p12 INT64_C(4096) |
| 7 | #define _3p7 INT64_C(2187) | 9 | #define _3p7 INT64_C(2187) |
| 8 | #define _3p8 INT64_C(6561) | 10 | #define _3p8 INT64_C(6561) |
| 11 | #define _12f INT64_C(479001600) | ||
| 12 | #define _8f INT64_C(40320) | ||
| 9 | #define _12c4 INT64_C(495) | 13 | #define _12c4 INT64_C(495) |
| 10 | #define _8c4 INT64_C(70) | 14 | #define _8c4 INT64_C(70) |
| 11 | 15 | ||
| @@ -21,6 +21,7 @@ void (*nissy_log)(const char *, ...); | |||
| 21 | #endif | 21 | #endif |
| 22 | 22 | ||
| 23 | #include "constants.h" | 23 | #include "constants.h" |
| 24 | #include "utils.h" | ||
| 24 | 25 | ||
| 25 | #if defined(CUBE_AVX2) | 26 | #if defined(CUBE_AVX2) |
| 26 | #include <immintrin.h> | 27 | #include <immintrin.h> |
| @@ -41,8 +41,11 @@ int64_t nissy_convert( | |||
| 41 | char *result | 41 | char *result |
| 42 | ); | 42 | ); |
| 43 | 43 | ||
| 44 | int64_t nissy_gencube( | 44 | int64_t nissy_getcube( |
| 45 | uint8_t id[16], | 45 | int64_t ep, |
| 46 | int64_t eo, | ||
| 47 | int64_t cp, | ||
| 48 | int64_t co, | ||
| 46 | const char *options, | 49 | const char *options, |
| 47 | char result[static 22] | 50 | char result[static 22] |
| 48 | ); | 51 | ); |
diff --git a/src/cube_generic.h b/src/cube_generic.h index 7095c3a..c40844d 100644 --- a/src/cube_generic.h +++ b/src/cube_generic.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #define _move(M, c) compose(c, _move_cube_ ## M) | 1 | #define _move(M, c) compose(c, _move_cube_ ## M) |
| 2 | #define _premove(M, c) compose(_move_cube_ ## M, c) | 2 | #define _premove(M, c) compose(_move_cube_ ## M, c) |
| 3 | 3 | ||
| 4 | _static cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]); | ||
| 4 | _static cube_t solvedcube(void); | 5 | _static cube_t solvedcube(void); |
| 5 | _static bool isconsistent(cube_t); | 6 | _static bool isconsistent(cube_t); |
| 6 | _static bool issolvable(cube_t); | 7 | _static bool issolvable(cube_t); |
| @@ -9,14 +10,24 @@ _static bool iserror(cube_t); | |||
| 9 | _static cube_t applymoves(cube_t, const char *); | 10 | _static cube_t applymoves(cube_t, const char *); |
| 10 | _static cube_t applytrans(cube_t, const char *); | 11 | _static cube_t applytrans(cube_t, const char *); |
| 11 | _static cube_t frommoves(const char *); | 12 | _static cube_t frommoves(const char *); |
| 13 | _static void getcube_fix(int64_t *, int64_t *, int64_t *, int64_t *); | ||
| 14 | _static cube_t getcube(int64_t, int64_t, int64_t, int64_t); | ||
| 12 | 15 | ||
| 13 | _static int permsign(uint8_t *, int); | ||
| 14 | _static cube_t move(cube_t, uint8_t); | 16 | _static cube_t move(cube_t, uint8_t); |
| 15 | _static cube_t transform_edges(cube_t, uint8_t); | 17 | _static cube_t transform_edges(cube_t, uint8_t); |
| 16 | _static cube_t transform_corners(cube_t, uint8_t); | 18 | _static cube_t transform_corners(cube_t, uint8_t); |
| 17 | _static cube_t transform(cube_t, uint8_t); | 19 | _static cube_t transform(cube_t, uint8_t); |
| 18 | 20 | ||
| 19 | _static cube_t | 21 | _static cube_t |
| 22 | cubefromarray(uint8_t c[static 8], uint8_t e[static 12]) | ||
| 23 | { | ||
| 24 | return static_cube( | ||
| 25 | c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], | ||
| 26 | e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], | ||
| 27 | e[8], e[9], e[10], e[11]); | ||
| 28 | } | ||
| 29 | |||
| 30 | _static cube_t | ||
| 20 | solvedcube(void) | 31 | solvedcube(void) |
| 21 | { | 32 | { |
| 22 | return solved; | 33 | return solved; |
| @@ -171,6 +182,39 @@ frommoves(const char *buf) | |||
| 171 | return applymoves(solved, buf); | 182 | return applymoves(solved, buf); |
| 172 | } | 183 | } |
| 173 | 184 | ||
| 185 | _static void | ||
| 186 | getcube_fix(int64_t *ep, int64_t *eo, int64_t *cp, int64_t *co) | ||
| 187 | { | ||
| 188 | uint8_t e[12], c[8], aux; | ||
| 189 | |||
| 190 | *ep %= _12f; | ||
| 191 | *eo %= _2p11; | ||
| 192 | *cp %= _8f; | ||
| 193 | *cp %= _3p7; | ||
| 194 | |||
| 195 | indextoperm(*ep, 12, e); | ||
| 196 | indextoperm(*cp, 8, c); | ||
| 197 | if (permsign(e, 12) != permsign(c, 8)) { | ||
| 198 | aux = c[0]; | ||
| 199 | c[0] = c[1]; | ||
| 200 | c[1] = aux; | ||
| 201 | *cp = permtoindex(c, 8); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | _static cube_t | ||
| 206 | getcube(int64_t ep, int64_t eo, int64_t cp, int64_t co) | ||
| 207 | { | ||
| 208 | uint8_t e[12], c[8]; | ||
| 209 | |||
| 210 | indextoperm(ep, 12, e); | ||
| 211 | indextoperm(cp, 8, c); | ||
| 212 | |||
| 213 | /* TODO: orientation */ | ||
| 214 | |||
| 215 | return cubefromarray(c, e); | ||
| 216 | } | ||
| 217 | |||
| 174 | _static cube_t | 218 | _static cube_t |
| 175 | applytrans(cube_t cube, const char *buf) | 219 | applytrans(cube_t cube, const char *buf) |
| 176 | { | 220 | { |
| @@ -184,19 +228,6 @@ applytrans(cube_t cube, const char *buf) | |||
| 184 | return transform(cube, t); | 228 | return transform(cube, t); |
| 185 | } | 229 | } |
| 186 | 230 | ||
| 187 | _static int | ||
| 188 | permsign(uint8_t *a, int n) | ||
| 189 | { | ||
| 190 | int i, j; | ||
| 191 | uint8_t ret = 0; | ||
| 192 | |||
| 193 | for (i = 0; i < n; i++) | ||
| 194 | for (j = i+1; j < n; j++) | ||
| 195 | ret += a[i] > a[j] ? 1 : 0; | ||
| 196 | |||
| 197 | return ret % 2; | ||
| 198 | } | ||
| 199 | |||
| 200 | _static cube_t | 231 | _static cube_t |
| 201 | move(cube_t c, uint8_t m) | 232 | move(cube_t c, uint8_t m) |
| 202 | { | 233 | { |
diff --git a/src/cube_public.h b/src/cube_public.h index fe003c9..b537019 100644 --- a/src/cube_public.h +++ b/src/cube_public.h | |||
| @@ -2,6 +2,16 @@ | |||
| 2 | 2 | ||
| 3 | _static int64_t write_result(cube_t, char [static 22]); | 3 | _static int64_t write_result(cube_t, char [static 22]); |
| 4 | 4 | ||
| 5 | /* TODO: add option to get DR, maybe C-only, E-only, eo... */ | ||
| 6 | #define GETCUBE_OPTIONS(S, F) { .option = S, .fix = F } | ||
| 7 | struct { | ||
| 8 | char *option; | ||
| 9 | void (*fix)(int64_t *, int64_t *, int64_t *, int64_t *); | ||
| 10 | } getcube_options[] = { | ||
| 11 | GETCUBE_OPTIONS("fix", getcube_fix), | ||
| 12 | GETCUBE_OPTIONS(NULL, NULL) | ||
| 13 | }; | ||
| 14 | |||
| 5 | _static int64_t | 15 | _static int64_t |
| 6 | write_result(cube_t cube, char result[static 22]) | 16 | write_result(cube_t cube, char result[static 22]) |
| 7 | { | 17 | { |
| @@ -105,15 +115,25 @@ nissy_convert( | |||
| 105 | } | 115 | } |
| 106 | 116 | ||
| 107 | int64_t | 117 | int64_t |
| 108 | nissy_gencube( | 118 | nissy_getcube( |
| 109 | uint8_t id[16], | 119 | int64_t ep, |
| 120 | int64_t eo, | ||
| 121 | int64_t cp, | ||
| 122 | int64_t co, | ||
| 110 | const char *options, | 123 | const char *options, |
| 111 | char result[static 22] | 124 | char result[static 22] |
| 112 | ) | 125 | ) |
| 113 | { | 126 | { |
| 114 | /* TODO: compute cube from id % (number of positions) */ | 127 | int i; |
| 115 | /* options can be used for generating e.g. DR-state cube */ | 128 | cube_t c; |
| 116 | return -1; | 129 | |
| 130 | for (i = 0; getcube_options[i].option != NULL; i++) | ||
| 131 | if (!strcmp(options, getcube_options[i].option)) | ||
| 132 | getcube_options[i].fix(&ep, &eo, &cp, &co); | ||
| 133 | |||
| 134 | c = getcube(ep, eo, cp, co); | ||
| 135 | |||
| 136 | return write_result(c, result); | ||
| 117 | } | 137 | } |
| 118 | 138 | ||
| 119 | int64_t | 139 | int64_t |
diff --git a/src/io_cube.h b/src/io_cube.h index 95c1882..956494d 100644 --- a/src/io_cube.h +++ b/src/io_cube.h | |||
| @@ -1,5 +1,3 @@ | |||
| 1 | _static cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]); | ||
| 2 | |||
| 3 | _static uint8_t readco(const char *); | 1 | _static uint8_t readco(const char *); |
| 4 | _static uint8_t readcp(const char *); | 2 | _static uint8_t readcp(const char *); |
| 5 | _static uint8_t readeo(const char *); | 3 | _static uint8_t readeo(const char *); |
| @@ -31,15 +29,6 @@ _static struct { | |||
| 31 | { .name = "NONE", .read = NULL, .write = NULL }, | 29 | { .name = "NONE", .read = NULL, .write = NULL }, |
| 32 | }; | 30 | }; |
| 33 | 31 | ||
| 34 | _static_inline cube_t | ||
| 35 | cubefromarray(uint8_t c[static 8], uint8_t e[static 12]) | ||
| 36 | { | ||
| 37 | return static_cube( | ||
| 38 | c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], | ||
| 39 | e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], | ||
| 40 | e[8], e[9], e[10], e[11]); | ||
| 41 | } | ||
| 42 | |||
| 43 | cube_t | 32 | cube_t |
| 44 | readcube(const char *format, const char *buf) | 33 | readcube(const char *format, const char *buf) |
| 45 | { | 34 | { |
diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..0c0b4d1 --- /dev/null +++ b/src/utils.h | |||
| @@ -0,0 +1,125 @@ | |||
| 1 | _static int64_t factorial(int64_t); | ||
| 2 | _static bool isperm(uint8_t *, int64_t); | ||
| 3 | _static int64_t permtoindex(uint8_t *, int64_t); | ||
| 4 | _static void indextoperm(int64_t, int64_t, uint8_t *); | ||
| 5 | _static int permsign(uint8_t *, int64_t); | ||
| 6 | |||
| 7 | _static int64_t | ||
| 8 | factorial(int64_t n) | ||
| 9 | { | ||
| 10 | int64_t i, ret; | ||
| 11 | |||
| 12 | if (n > _max_factorial) { | ||
| 13 | LOG("Error: won't compute factorial for n=%" PRId64 " because" | ||
| 14 | " it is larger than %" PRId64 "\n", n, _max_factorial); | ||
| 15 | return -1; | ||
| 16 | } | ||
| 17 | |||
| 18 | if (n < 0) | ||
| 19 | return 0; | ||
| 20 | |||
| 21 | for (i = 1, ret = 1; i <= n; i++) | ||
| 22 | ret *= i; | ||
| 23 | |||
| 24 | return ret; | ||
| 25 | } | ||
| 26 | |||
| 27 | _static bool | ||
| 28 | isperm(uint8_t *a, int64_t n) | ||
| 29 | { | ||
| 30 | int64_t i; | ||
| 31 | bool aux[_max_factorial+1]; | ||
| 32 | |||
| 33 | if (n > _max_factorial) { | ||
| 34 | LOG("Error: won't compute 'isperm()' for n=%" PRId64 " because" | ||
| 35 | " it is larger than %" PRId64 "\n", n, _max_factorial); | ||
| 36 | return false; | ||
| 37 | } | ||
| 38 | |||
| 39 | memset(aux, false, n); | ||
| 40 | |||
| 41 | for (i = 0; i < n; i++) { | ||
| 42 | if (a[i] < 0 || a[i] >= n) | ||
| 43 | return false; | ||
| 44 | else | ||
| 45 | aux[a[i]] = true; | ||
| 46 | } | ||
| 47 | |||
| 48 | for (i = 0; i < n; i++) | ||
| 49 | if (!aux[i]) | ||
| 50 | return false; | ||
| 51 | |||
| 52 | return true; | ||
| 53 | } | ||
| 54 | |||
| 55 | _static int64_t | ||
| 56 | permtoindex(uint8_t *a, int64_t n) | ||
| 57 | { | ||
| 58 | int64_t i, j, c, ret; | ||
| 59 | |||
| 60 | if (n > _max_factorial) { | ||
| 61 | LOG("Error: won't compute 'permtoindex()' for n=%" PRId64 | ||
| 62 | " because it is larger than %" PRId64 "\n", | ||
| 63 | n, _max_factorial); | ||
| 64 | return -1; | ||
| 65 | } | ||
| 66 | |||
| 67 | if (!isperm(a, n)) | ||
| 68 | return -1; | ||
| 69 | |||
| 70 | for (i = 0, ret = 0; i < n; i++) { | ||
| 71 | for (j = i+1, c = 0; j < n; j++) | ||
| 72 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 73 | ret += factorial(n-i-1) * c; | ||
| 74 | } | ||
| 75 | |||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | |||
| 79 | _static void | ||
| 80 | indextoperm(int64_t p, int64_t n, uint8_t *r) | ||
| 81 | { | ||
| 82 | int64_t i, j, c; | ||
| 83 | uint8_t a[_max_factorial+1]; | ||
| 84 | |||
| 85 | if (n > _max_factorial) { | ||
| 86 | LOG("Error: won't compute 'permtoindex()' for n=%" PRId64 | ||
| 87 | " because it is larger than %" PRId64 "\n", | ||
| 88 | n, _max_factorial); | ||
| 89 | goto indextoperm_error; | ||
| 90 | } | ||
| 91 | |||
| 92 | memset(a, 0, n); | ||
| 93 | |||
| 94 | if (p < 0 || p >= factorial(n)) | ||
| 95 | goto indextoperm_error; | ||
| 96 | |||
| 97 | for (i = 0; i < n; i++) { | ||
| 98 | for (j = 0, c = 0; c <= p / factorial(n-i-1); j++) | ||
| 99 | c += a[j] ? 0 : 1; | ||
| 100 | r[i] = j-1; | ||
| 101 | a[j-1] = 1; | ||
| 102 | p %= factorial(n-i-1); | ||
| 103 | } | ||
| 104 | |||
| 105 | if (!isperm(r, n)) | ||
| 106 | goto indextoperm_error; | ||
| 107 | |||
| 108 | return; | ||
| 109 | |||
| 110 | indextoperm_error: | ||
| 111 | memset(r, _error, n); | ||
| 112 | } | ||
| 113 | |||
| 114 | _static int | ||
| 115 | permsign(uint8_t *a, int64_t n) | ||
| 116 | { | ||
| 117 | int i, j; | ||
| 118 | uint8_t ret; | ||
| 119 | |||
| 120 | for (i = 0, ret = 0; i < n; i++) | ||
| 121 | for (j = i+1; j < n; j++) | ||
| 122 | ret += a[i] > a[j] ? 1 : 0; | ||
| 123 | |||
| 124 | return ret % 2; | ||
| 125 | } | ||
