diff options
| author | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2020-06-21 23:01:57 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2020-06-21 23:01:57 +0200 |
| commit | 0e8d73bb3edcc8bdff6e3ded442b66f68265059a (patch) | |
| tree | 4f92deb9ace97e79332c0e7ce390b76b81aeaae9 /src/utils.c | |
| parent | 4e359b44ce111b04cc4d2b28033fba4ab4e6e989 (diff) | |
| download | nissy-0e8d73bb3edcc8bdff6e3ded442b66f68265059a.tar.gz nissy-0e8d73bb3edcc8bdff6e3ded442b66f68265059a.zip | |
First push
Diffstat (limited to '')
| -rw-r--r-- | src/utils.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..c672453 --- /dev/null +++ b/src/utils.c | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | #include "utils.h" | ||
| 2 | |||
| 3 | /* Hardcoded factorial of small numbers (n<=12). */ | ||
| 4 | int factorial[13] = { | ||
| 5 | 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600 | ||
| 6 | }; | ||
| 7 | |||
| 8 | /* swaps two integers */ | ||
| 9 | void swap(int *a, int *b) { | ||
| 10 | int aux = *a; | ||
| 11 | *a = *b; | ||
| 12 | *b = aux; | ||
| 13 | } | ||
| 14 | |||
| 15 | /* Converts the integer a to its representation in base b (first n digits | ||
| 16 | * only) and saves the result in r. */ | ||
| 17 | void int_to_digit_array(int a, int b, int n, int *r) { | ||
| 18 | for (int i = 0; i < n; i++) { | ||
| 19 | r[i] = a % b; | ||
| 20 | a /= b; | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | /* Converts the array of n digits a to a integer using base b. */ | ||
| 25 | int digit_array_to_int(int *a, int n, int b) { | ||
| 26 | int ret = 0, p = 1; | ||
| 27 | for (int i = 0; i < n; i++) { | ||
| 28 | ret += a[i] * p; | ||
| 29 | p *= b; | ||
| 30 | } | ||
| 31 | return ret; | ||
| 32 | } | ||
| 33 | |||
| 34 | /* Converts a permutation on [0..(n-1)] into the integer i which is the index | ||
| 35 | * of the permutation in the sorted list of all n! such permutations. | ||
| 36 | * Only works for n<=12. */ | ||
| 37 | int perm_to_index(int *a, int n) { | ||
| 38 | int ret = 0; | ||
| 39 | for (int i = 0; i < n; i++) { | ||
| 40 | int c = 0; | ||
| 41 | for (int j = i+1; j < n; j++) | ||
| 42 | if (a[i] > a[j]) | ||
| 43 | c++; | ||
| 44 | ret += factorial[n-i-1] * c; | ||
| 45 | } | ||
| 46 | return ret; | ||
| 47 | } | ||
| 48 | |||
| 49 | /* Converts a permutation index to the actual permutation as an array | ||
| 50 | * (see perm_to_index) and saves the result to r. */ | ||
| 51 | void index_to_perm(int p, int n, int *r) { | ||
| 52 | int a[n]; | ||
| 53 | for (int j = 0; j < n; j++) | ||
| 54 | a[j] = 0; /* picked elements */ | ||
| 55 | for (int i = 0; i < n; i++) { | ||
| 56 | int c = 0, j = 0; | ||
| 57 | while (c <= p / factorial[n-i-1]) { | ||
| 58 | if (!a[j]) | ||
| 59 | c++; | ||
| 60 | j++; | ||
| 61 | } | ||
| 62 | r[i] = j-1; | ||
| 63 | a[j-1] = 1; | ||
| 64 | p %= factorial[n-i-1]; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | /* 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 | ||
| 70 | * in the sorted list of all such subsets. | ||
| 71 | * Works only for n <= 12. */ | ||
| 72 | int subset_to_index(int *a, int n, int k) { | ||
| 73 | int ret = 0; | ||
| 74 | for (int i = 0; i < n; i++) { | ||
| 75 | if (k == n-i) | ||
| 76 | return ret; | ||
| 77 | if (a[i]) { | ||
| 78 | ret += factorial[n-i-1] / (factorial[k] * factorial[n-i-1-k]); | ||
| 79 | k--; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | return ret; | ||
| 83 | } | ||
| 84 | |||
| 85 | /* Inverse of the above */ | ||
| 86 | void index_to_subset(int s, int n, int k, int *r) { | ||
| 87 | for (int i = 0; i < n; i++) { | ||
| 88 | if (k == n-i) { | ||
| 89 | for (int j = i; j < n; j++) | ||
| 90 | r[j] = 1; | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | int v = factorial[n-i-1] / (factorial[k] * factorial[n-i-1-k]); | ||
| 94 | if (s >= v) { | ||
| 95 | r[i] = 1; | ||
| 96 | k--; | ||
| 97 | s -= v; | ||
| 98 | } else { | ||
| 99 | r[i] = 0; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | /* Converts the first n-1 digits of a number to an array a of digits in base b; | ||
| 105 | * then adds one element to the array, so that the sum of the elements of a is | ||
| 106 | * zero modulo b. | ||
| 107 | * This is used for determing the edge orientation from an 11-bits integer or | ||
| 108 | * the corner orientation from a 7-trits integer. */ | ||
| 109 | void int_to_sum_zero_array(int x, int b, int n, int *a) { | ||
| 110 | int_to_digit_array(x, b, n-1, a); | ||
| 111 | int s = 0; | ||
| 112 | for (int i = 0; i < n - 1; i++) s = (s + a[i]) % b; | ||
| 113 | a[n-1] = (b - s) % b; | ||
| 114 | } | ||
| 115 | |||
