aboutsummaryrefslogtreecommitdiff
path: root/src/utils.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/utils.c115
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). */
4int factorial[13] = {
5 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600
6};
7
8/* swaps two integers */
9void 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. */
17void 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. */
25int 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. */
37int 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. */
51void 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. */
72int 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 */
86void 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. */
109void 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

Generated with cgit - Back to sebastiano.tronto.net