diff --git a/.gitignore b/.gitignore index bfe84f9..0f3caa3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ simplifications.bin .simplifier-*.bin +.direnv/ +typescript diff --git a/main.c b/main.c index 8d917d1..58faa43 100644 --- a/main.c +++ b/main.c @@ -182,7 +182,8 @@ static void parse_args(int argc, char* const* argv) #define N (65536) enum kind { - ek_undef, + ek_unreachable, + ek_0, ek_1, ek_W, @@ -215,11 +216,10 @@ struct expr { enum kind kind; uint16_t cond, left, right; + + int cost; } lookup[N]; -// truthtable -> cost -int costs[N] = {}; - static void print(uint16_t truthtable, int depth) { #define LITERAL_ESCAPE "\e[38;2;200;200;100m" @@ -243,10 +243,12 @@ static void print(uint16_t truthtable, int depth) switch (e->kind) { - case ek_undef: + case ek_unreachable: + { assert(!"NOPE"); break; - + } + case ek_0: { printf(print_with_color ? LITERAL_ESCAPE "0" RESET_ESCAPE : "0"); @@ -364,34 +366,46 @@ static void print(uint16_t truthtable, int depth) void calculate_simplifications(void) { - // heap of truthtables; key = cost - uint16_t todo[N]; - int todo_n = 0; - - // truthtable -> index in 'todo' - int reverse[N]; - - // init: - for (int i = 0; i < N; i++) + // init 'lookup': { - lookup[i].kind = ek_undef; - - reverse[i] = -1; - - costs[i] = INT_MAX; + for (int i = 0; i < N; i++) + { + lookup[i].kind = ek_unreachable; + + lookup[i].cost = INT_MAX; + } } - + + // heap of truthtables; key = cost + struct { + uint16_t data[N]; + int n; + + // truthtable -> index in 'todo' + int reverse[N]; + } todo; + + // init 'todo': + { + todo.n = 0; + + for (int i = 0; i < N; i++) + { + todo.reverse[i] = -1; + } + } + uint16_t pop(void) { - assert(todo_n > 0); + assert(todo.n > 0); - uint16_t retval = todo[0]; + uint16_t retval = todo.data[0]; - reverse[retval] = -1; + todo.reverse[retval] = -1; - uint16_t moving = todo[todo_n-- - 1]; + uint16_t moving = todo.data[todo.n-- - 1]; - int cost = costs[moving]; + int cost = lookup[moving].cost; int index = 0; @@ -402,25 +416,25 @@ void calculate_simplifications(void) uint16_t smallest = moving; - if (left < todo_n && costs[todo[left]] < cost) - smallest = todo[left]; + if (left < todo.n && lookup[todo.data[left]].cost < cost) + smallest = todo.data[left]; - if (right < todo_n && costs[todo[right]] < costs[smallest]) - smallest = todo[right]; + if (right < todo.n && lookup[todo.data[right]].cost < lookup[smallest].cost) + smallest = todo.data[right]; if (smallest == moving) { - todo[index] = moving; + todo.data[index] = moving; - reverse[moving] = index; + todo.reverse[moving] = index; } else { - int new = reverse[smallest]; + int new = todo.reverse[smallest]; - todo[index] = smallest; + todo.data[index] = smallest; - reverse[smallest] = index; + todo.reverse[smallest] = index; index = new; @@ -433,73 +447,166 @@ void calculate_simplifications(void) void append(uint16_t truthtable, int cost) { - assert(reverse[truthtable] == -1); + assert(todo.reverse[truthtable] == -1); - int index = todo_n++, new_index; + int index = todo.n++, new_index; - while (index > 0 && costs[todo[new_index = (index - 1) / 2]] > cost) + while (index > 0 && lookup[todo.data[new_index = (index - 1) / 2]].cost > cost) { - todo[index] = todo[new_index]; + todo.data[index] = todo.data[new_index]; - reverse[todo[new_index]] = index; + todo.reverse[todo.data[new_index]] = index; index = new_index; } - - todo[index] = truthtable; - - reverse[truthtable] = index; - - costs[truthtable] = cost; + + todo.data[index] = truthtable; + + todo.reverse[truthtable] = index; + + lookup[truthtable].cost = cost; } void update(uint16_t truthtable, int cost) { - assert(reverse[truthtable] != -1); + assert(todo.reverse[truthtable] != -1); - assert(cost < costs[truthtable]); + assert(cost < lookup[truthtable].cost); - int index = reverse[truthtable], new_index; + int index =todo. reverse[truthtable], new_index; - while (index > 0 && costs[todo[new_index = (index - 1) / 2]] > cost) + while (index > 0 && lookup[todo.data[new_index = (index - 1) / 2]].cost > cost) { - todo[index] = todo[new_index]; + todo.data[index] = todo.data[new_index]; - reverse[todo[new_index]] = index; + todo.reverse[todo.data[new_index]] = index; index = new_index; } - todo[index] = truthtable; - reverse[truthtable] = index; + todo.data[index] = truthtable; + todo.reverse[truthtable] = index; - costs[truthtable] = cost; + lookup[truthtable].cost = cost; } - + + // create a list of the "done" truthtables + struct { + int headtails[N], next[N], head; + + // for debugging: + bool in[N]; + } done = {}; + + // init 'done': + { + done.head = -1; + + for (int i = 0; i < N; i++) + { + done.headtails[i] = -1; + + done.in[i] = false; + } + } + + void insert(int index) + { + assert(!done.in[index]); + + int head = index & 1 ? index & ~(index & -index) : index, prevhead = -1; + + while (done.headtails[head] == -1 || index < done.headtails[head]) + { + done.headtails[head] = index; + + prevhead = head, head = head & ~(head & -head); + } + + if (done.headtails[head] < index) + { + if (prevhead == -1) + { + assert(done.headtails[head] == head); + + done.next[head] = index; + } + else + { + int tophalftail = done.headtails[prevhead - 1]; + + assert(tophalftail != -1); + + done.next[tophalftail] = index; + } + } + else + { + done.head = index; + } + + int n = ~index & M; + int tail = index & 1 ? index : index | (n & -n), prevtail = -1; + + while (done.headtails[tail] == -1 || done.headtails[tail] < index) + { + done.headtails[tail] = index; + + prevtail = tail, tail = tail | (n = ~tail & M, n & -n); + } + + if (index < done.headtails[tail]) + { + if (prevtail == -1) + { + assert(done.headtails[tail] == tail); + + assert(done.in[tail]); + + done.next[index] = tail; + } + else + { + int bottomhalfhead = done.headtails[prevtail + 1]; + + assert(bottomhalfhead != -1); + + done.next[index] = bottomhalfhead; + } + } + else + { + done.next[index] = -1; + } + + done.in[index] = true; + } + append(W, 0), lookup[W].kind = ek_W; append(X, 0), lookup[X].kind = ek_X; append(Y, 0), lookup[Y].kind = ek_Y; append(Z, 0), lookup[Z].kind = ek_Z; - + append(0, 1), lookup[0].kind = ek_0; append(M, 1), lookup[M].kind = ek_1; - - while (todo_n) + + for (int iterations = 1; todo.n && iterations <= N; iterations++) { uint16_t truthtable = pop(); - - int cost = costs[truthtable]; + + insert(truthtable); + + int cost = lookup[truthtable].cost; if (verbose) { - int left = N - todo_n; - if (print_with_color) { printf("\e[2K"); } - printf("%i of %i (%.2f%%): [%i] ", left, N, (100.0 * left / N), cost); + printf("%i of %i (%.2f%%): [%i] ", + iterations, N, (100.0 * iterations / N), cost); print(truthtable, 0), puts(""); @@ -516,9 +623,9 @@ void calculate_simplifications(void) int not_cost = cost + 1; - if (not_cost < costs[not_truthtable]) + if (not_cost < lookup[not_truthtable].cost) { - if (reverse[not_truthtable] == -1) + if (todo.reverse[not_truthtable] == -1) { append(not_truthtable, not_cost); } @@ -534,44 +641,41 @@ void calculate_simplifications(void) #define BINARY_OPERATOR(ekind, function) \ { \ - for (int i = 0; i < N; i++) \ + for (int i = done.head; i != -1; i = done.next[i]) \ { \ - if (costs[i] != INT_MAX) \ { \ + uint16_t bin_truthtable = function(truthtable, i) & M; \ + \ + int bin_cost = 1 + cost + lookup[i].cost; \ + \ + if (bin_cost < lookup[bin_truthtable].cost) \ { \ - uint16_t bin_truthtable = function(truthtable, i) & M; \ + if (todo.reverse[bin_truthtable] == -1) \ + append(bin_truthtable, bin_cost); \ + else \ + update(bin_truthtable, bin_cost); \ \ - int bin_cost = 1 + cost + costs[i]; \ - \ - if (bin_cost < costs[bin_truthtable]) \ - { \ - if (reverse[bin_truthtable] == -1) \ - append(bin_truthtable, bin_cost); \ - else \ - update(bin_truthtable, bin_cost); \ - \ - lookup[bin_truthtable].kind = ekind; \ - lookup[bin_truthtable].left = truthtable; \ - lookup[bin_truthtable].right = i; \ - } \ + lookup[bin_truthtable].kind = ekind; \ + lookup[bin_truthtable].left = truthtable; \ + lookup[bin_truthtable].right = i; \ } \ - \ + } \ + \ + { \ + uint16_t bin_truthtable = function(i, truthtable) & M; \ + \ + int bin_cost = 1 + cost + lookup[i].cost; \ + \ + if (bin_cost < lookup[bin_truthtable].cost) \ { \ - uint16_t bin_truthtable = function(i, truthtable) & M; \ + if (todo.reverse[bin_truthtable] == -1) \ + append(bin_truthtable, bin_cost); \ + else \ + update(bin_truthtable, bin_cost); \ \ - int bin_cost = 1 + cost + costs[i]; \ - \ - if (bin_cost < costs[bin_truthtable]) \ - { \ - if (reverse[bin_truthtable] == -1) \ - append(bin_truthtable, bin_cost); \ - else \ - update(bin_truthtable, bin_cost); \ - \ - lookup[bin_truthtable].kind = ekind; \ - lookup[bin_truthtable].left = i; \ - lookup[bin_truthtable].right = truthtable; \ - } \ + lookup[bin_truthtable].kind = ekind; \ + lookup[bin_truthtable].left = i; \ + lookup[bin_truthtable].right = truthtable; \ } \ } \ } \ @@ -654,44 +758,38 @@ void calculate_simplifications(void) if (use_operators.ternary) { - for (int i = 0; i < N; i++) + for (int i = done.head; i != -1; i = done.next[i]) { - if (costs[i] != INT_MAX) + for (int j = done.head; j != -1; j = done.next[j]) { - for (int j = 0; j < N; j++) - { - if (costs[j] != INT_MAX) - { - int ternary_cost = 1 + cost + costs[i] + costs[j]; + int ternary_cost = 1 + cost + lookup[i].cost + lookup[j].cost; - #define TERNARY(C, T, F) \ + #define TERNARY(C, T, F) \ + { \ + uint16_t ternary_truthtable = \ + ((C) & (T)) | (~(C) & (F)); \ + \ + if (ternary_cost < lookup[ternary_truthtable].cost) \ + { \ + if (todo.reverse[ternary_truthtable] == -1) \ { \ - uint16_t ternary_truthtable = \ - ((C) & (T)) | (~(C) & (F)); \ - \ - if (ternary_cost < costs[ternary_truthtable]) \ - { \ - if (reverse[ternary_truthtable] == -1) \ - { \ - append(ternary_truthtable, ternary_cost); \ - } \ - else \ - { \ - update(ternary_truthtable, ternary_cost); \ - } \ - \ - lookup[ternary_truthtable].kind = ek_ternary; \ - lookup[ternary_truthtable].cond = (C); \ - lookup[ternary_truthtable].left = (T); \ - lookup[ternary_truthtable].right = (F); \ - } \ + append(ternary_truthtable, ternary_cost); \ } \ + else \ + { \ + update(ternary_truthtable, ternary_cost); \ + } \ + \ + lookup[ternary_truthtable].kind = ek_ternary; \ + lookup[ternary_truthtable].cond = (C); \ + lookup[ternary_truthtable].left = (T); \ + lookup[ternary_truthtable].right = (F); \ + } \ + } \ - TERNARY(truthtable, i, j); - TERNARY(i, truthtable, j); - TERNARY(i, j, truthtable); - } - } + TERNARY(truthtable, i, j); + TERNARY(i, truthtable, j); + TERNARY(i, j, truthtable); } } } @@ -705,7 +803,7 @@ void calculate_simplifications(void) void get_simplifications(void) { - char path[PATH_MAX] = ".simplifier-cache"; + char path[PATH_MAX] = ".simplifier-cache-2"; if (use_operators.not) strcat(path, "-not"); @@ -766,12 +864,6 @@ void get_simplifications(void) printf("%s: read() to cache failed: %m\n", argv0); exit(1); } - - if (read(fd, costs, sizeof(costs)) < (ssize_t) sizeof(costs)) - { - printf("%s: read() to cache failed: %m\n", argv0); - exit(1); - } } else if (fd < 0 && errno == ENOENT) { @@ -806,12 +898,6 @@ void get_simplifications(void) printf("%s: write() to cache failed: %m\n", argv0); exit(1); } - - if (write(fd, costs, sizeof(costs)) < (ssize_t) sizeof(costs)) - { - printf("%s: write() to cache failed: %m\n", argv0); - exit(1); - } } else { @@ -1326,7 +1412,7 @@ int main(int argc, char* const* argv) { for (int i = 0; i < N; i++) { - int cost = costs[i]; + int cost = lookup[i].cost; if (cost != INT_MAX) { @@ -1340,48 +1426,52 @@ int main(int argc, char* const* argv) // printf("truthtable = 0b%016b\n", truthtable); - if (costs[truthtable] == INT_MAX) + if (lookup[truthtable].kind == ek_unreachable) { puts("unreachable"); } else { - printf("%2i: ", costs[truthtable]), print(truthtable, 0), puts(""); + printf("%2i: ", lookup[truthtable].cost), print(truthtable, 0), puts(""); } } else { - int max_cost = 0; - - for (int i = 0; i < N; i++) + // Let's humble-brag just a little. { - int cost = costs[i]; + int max_cost = 0; - if (cost != INT_MAX && max_cost < cost) + for (int i = 0; i < N; i++) { - max_cost = cost; + int cost = lookup[i].cost; + + if (cost != INT_MAX && max_cost < cost) + { + max_cost = cost; + } } + + puts(""); + printf("I can simplify any tree down to %i operators or less.\n", + max_cost); + puts(""); } - - // we subtract 4 from the cost because - puts(""); - printf("I can simplify any tree down to %i operators or less.\n", - max_cost); - puts(""); - + for (char* line; (line = readline(">>> ")); free(line)) { + add_history(line); + uint16_t truthtable = evaluate(line); // printf("truthtable = 0b%016b\n", truthtable); - if (costs[truthtable] == INT_MAX) + if (lookup[truthtable].kind == ek_unreachable) { puts("unreachable"); } else { - printf("%2i: ", costs[truthtable]), print(truthtable, 0), puts(""); + printf("%2i: ", lookup[truthtable].cost), print(truthtable, 0), puts(""); } } } diff --git a/makefile b/makefile index 47556c4..b19cc63 100644 --- a/makefile +++ b/makefile @@ -23,5 +23,6 @@ run: /tmp/4-variable-simplifier $< $(args) -# nix --extra-experimental-features nix-command --extra-experimental-features flakes develop --command 'make' +# nix --extra-experimental-features nix-command \ +# --extra-experimental-features flakes develop --command 'make' diff --git a/spikes/kattis-add-find-all.c b/spikes/kattis-add-find-all.c new file mode 100644 index 0000000..f2f353a --- /dev/null +++ b/spikes/kattis-add-find-all.c @@ -0,0 +1,100 @@ + +#include +#include +#include +#include + +#define N(array) (sizeof(array) / sizeof(*array)) + +// 0 1 2 3 4 5 6 7 8 9 +int a[10] = { 2, 4, 5, 7, 9, 11, 15, 17, 17, 19}; +int b[10] = {10, 11, 11, 14, 14, 19, 20, 23, 26, 29}; + +int c[20] = { + 15, 17, 19, 21, 22, 25, 26, 26, 27, 32, + 33, 33, 36, 39, 42, 44, 48, 49, 49, 49 +}; + +// [ 0] [ 1] [ 2] [ 3] [ 4] [ 5] [ 6] [ 7] [ 8] [ 9] +// 2 4 5 7 9 11 15 17 17 19 +// -------------------------------------------------- +// [ 0] 10 | 12 14 (15) (17) (19) (21) (25) (27) (27) 29 + +// [ 1] 11 | 13 (15) 16 28 20 (22) (26) 28 28 30 + +// [ 2] 11 | 13 (15) 16 18 20 (22) (26) 28 28 30 + +// [ 3] 14 | 16 18 (19) (21) 23 (25) 29 31 31 (33) + +// [ 4] 14 | 16 18 (19) (21) 23 (25) 29 31 31 (33) + +// [ 5] 19 |(21) 23 24 (26) 28 30 34 (36) (36) 38 + +// [ 6] 20 |(22) 24 (25) (27) 29 31 38 40 40 (42) + +// [ 7] 23 |(25) (27) 28 30 (32) 34 38 40 40 (42) + +// [ 8] 26 | 28 30 31 (33) 35 37 41 43 43 45 + +// [ 9] 29 | 31 (33) 34 (36) 38 40 (44) 46 46 (48) + +int main() +{ + puts("hello, world!"); + + for (int ci = 0; ci < 20; ci++) + { + bool found[10][10] = {}; + + int goal = c[ci]; + + bool again = true; + + while (again) + { + again = false; + + int ai = 0, bi = 9; + + while (ai < 10 && bi >= 0) + { + int sum = found[ai][bi] ? 0 : a[ai] + b[bi]; + + if (sum < goal) + { + ai++; + } + else if (sum > goal) + { + bi--; + } + else + { + assert(a[ai] + b[bi] == c[ci]); + + printf("a[%2i] + b[%2i] == c[%2i] " + "(%2i + %2i == %2i)\n", + ai, bi, ci, a[ai], b[bi], c[ci]); + + found[ai][bi] = true; + again = true; + + bi--; + } + } + } + } + + return 0; +} + + + + + + + + + + + diff --git a/spikes/kattis-add.c b/spikes/kattis-add.c new file mode 100644 index 0000000..9c463bd --- /dev/null +++ b/spikes/kattis-add.c @@ -0,0 +1,94 @@ + +#include +#include +#include +#include + +#define N(array) (sizeof(array) / sizeof(*array)) + +// 0 1 2 3 4 5 6 7 8 9 +int a[10] = { 2, 4, 5, 7, 9, 11, 15, 17, 17, 19}; +int b[10] = {10, 11, 11, 14, 14, 19, 20, 23, 26, 29}; + +int c[20] = { + 15, 17, 19, 21, 22, 25, 26, 26, 27, 32, + 33, 33, 36, 39, 42, 44, 48, 49, 49, 49 +}; + +// [ 0] [ 1] [ 2] [ 3] [ 4] [ 5] [ 6] [ 7] [ 8] [ 9] +// 2 4 5 7 9 11 15 17 17 19 +// -------------------------------------------------- +// [ 0] 10 | 12 14 15 (17) 19 21 25 27 27 29 + +// [ 1] 11 | 13 15 16 28 20 22 26 28 28 30 + +// [ 2] 11 | 13 (15) 16 18 20 22 26 28 28 30 + +// [ 3] 14 | 16 18 19 21 23 25 29 31 31 33 + +// [ 4] 14 | 16 18 (19) 21 23 25 29 31 31 33 + +// [ 5] 19 |(21) 23 24 (26) 28 30 34 36 36 38 + +// [ 6] 20 |(22) 24 25 27 29 31 38 40 40 (42) + +// [ 7] 23 |(25) (27) 28 30 32 34 38 40 40 (42) + +// [ 8] 26 | 28 30 31 33 35 37 41 43 43 45 + +// [ 9] 29 | 31 (33) 34 (36) 38 40 (44) 46 46 (48) + +int main() +{ + puts("hello, world!"); + + for (int ci = 0; ci < 20; ci++) + { + int goal = c[ci]; + + int ai = 0, bi = 9; + + while (1) + { + int sum = a[ai] + b[bi]; + + if (sum < goal) + { + ai++; + + if (ai == 10) + break; + } + else if (sum > goal) + { + if (bi == 0) + break; + + bi--; + } + else + { + assert(a[ai] + b[bi] == c[ci]); + + printf("a[%2i] + b[%2i] == c[%2i] " + "(%2i + %2i == %2i)\n", + ai, bi, ci, a[ai], b[bi], c[ci]); + + break; + } + } + } + + return 0; +} + + + + + + + + + + + diff --git a/spikes/kattis-subtract.c b/spikes/kattis-subtract.c new file mode 100644 index 0000000..506840b --- /dev/null +++ b/spikes/kattis-subtract.c @@ -0,0 +1,85 @@ + +#include +#include +#include +#include + +// in this one, 'a' is fixed and we're trying to find a 'b' and 'c' to +// satisify the equation: `a + b = c` + +// which we're re-writing as: + // `a = c - b` + +int a = 7; +/*int a = 11;*/ + +// 0 1 2 3 4 5 6 7 8 9 +int b[10] = {10, 11, 11, 14, 14, 19, 20, 23, 26, 29}; + +int c[20] = { + 15, 17, 19, 21, 22, 25, 26, 26, 27, 32, + 33, 33, 36, 39, 42, 44, 48, 49, 49, 49 +}; + +int main() +{ + puts("hello, world!"); + + bool found[10][20] = {}; + + int passes = 0; + + bool again = true; + + while (again) + { + passes++; + again = false; + + int bi = 0, ci = 0; + + while (bi < 10 && ci < 20) + { + int diff = found[bi][ci] ? INT_MIN : c[ci] - b[bi]; + + if (a < diff) + { + bi++; + } + else if (diff < a) + { + ci++; + } + else + { + assert(a + b[bi] == c[ci]); + + printf("a + b[%2i] == c[%2i] " + "(%2i + %2i == %2i)\n", + bi, ci, a, b[bi], c[ci]); + + found[bi][ci] = true; + again = true; + + // From now on, this cell will be seen as "too low" + // so we'll take that path like it's too high. + bi++; + } + } + } + + printf("passes = %i\n", passes); + + return 0; +} + + + + + + + + + + + diff --git a/spikes/linear-add.c b/spikes/linear-add.c new file mode 100644 index 0000000..0f434be --- /dev/null +++ b/spikes/linear-add.c @@ -0,0 +1,172 @@ + +#include +#include +#include +#include + +#define N(array) (sizeof(array) / sizeof(*array)) + +// 0 1 2 3 4 5 6 7 8 9 +int a[10] = { 2, 4, 5, 7, 9, 11, 15, 17, 17, 19}; +int b[10] = {10, 11, 11, 14, 14, 19, 20, 23, 26, 29}; + +int c[20] = { + 15, 17, 19, 21, 22, 25, 26, 26, 27, 32, + 33, 33, 36, 39, 42, 44, 48, 49, 49, 49 +}; + +// [ 0] [ 1] [ 2] [ 3] [ 4] [ 5] [ 6] [ 7] [ 8] [ 9] +// 2 4 5 7 9 11 15 17 17 19 +// -------------------------------------------------- +// [ 0] 10 | 12 14 (15) (17) (19) (21) (25) (27) (27) 29 + +// [ 1] 11 | 13 (15) 16 28 20 (22) (26) 28 28 30 + +// [ 2] 11 | 13 (15) 16 18 20 (22) (26) 28 28 30 + +// [ 3] 14 | 16 18 (19) (21) 23 (25) 29 31 31 (33) + +// [ 4] 14 | 16 18 (19) (21) 23 (25) 29 31 31 (33) + +// [ 5] 19 |(21) 23 24 (26) 28 30 34 (36) (36) 38 + +// [ 6] 20 |(22) 24 (25) (27) 29 31 38 40 40 (42) + +// [ 7] 23 |(25) (27) 28 30 (32) 34 38 40 40 (42) + +// [ 8] 26 | 28 30 31 (33) 35 37 41 43 43 45 + +// [ 9] 29 | 31 (33) 34 (36) 38 40 (44) 46 46 (48) + +int sums[10 * 10]; + +bool queued[10 * 10]; + +struct { + int data[10 * 10]; + int n; +} heap; + +void append(int e) +{ + int index = heap.n++, new_index; + + while (index > 0 && sums[heap.data[new_index = (index - 1) / 2]] > sums[e]) + { + heap.data[index] = heap.data[new_index]; + + index = new_index; + } + + heap.data[index] = e; +} + +int pop(void) +{ + assert(heap.n > 0); + + int retval = heap.data[0]; + + heap.data[0] = heap.data[heap.n-- - 1]; + + int index = 0; + + again: + { + int left = index * 2 + 1; + int right = index * 2 + 2; + + int smallest = index; + + if (left < heap.n && sums[heap.data[left]] < sums[heap.data[index]]) + smallest = left; + + if (right < heap.n && sums[heap.data[right]] < sums[heap.data[smallest]]) + smallest = right; + + if (smallest != index) + { + int tmp = heap.data[index]; + heap.data[index] = heap.data[smallest]; + heap.data[smallest] = tmp; + + index = smallest; + + goto again; + } + } + + return retval; +} + + +int main() +{ + puts("hello, world!"); + + int ci = 0; + + sums[0] = a[0] + b[0]; + queued[0] = true; + append(0); + + while (heap.n && ci < 20) + { + int sum = sums[heap.data[0]], ce = c[ci]; + + // printf("sum = %i, ce = %i\n", sum, ce); + + if (sum < ce) + { + next_sum: ; + + int xy = pop(); + + if (xy % 10 + 1 < 10 && !queued[xy + 1]) + { + int nxy = xy + 1; + sums[nxy] = a[nxy % 10] + b[nxy / 10]; + queued[nxy] = true; + append(nxy); + } + + if (xy + 10 < 100 && !queued[xy + 10]) + { + int nxy = xy + 10; + sums[nxy] = a[nxy % 10] + b[nxy / 10]; + queued[nxy] = true; + append(nxy); + } + } + else if (sum > ce) + { + ci++; + } + else + { + int xy = heap.data[0]; + + int ai = xy % 10, bi = xy / 10; + + assert(a[ai] + b[bi] == c[ci]); + + printf("a[%2i] + b[%2i] == c[%2i] (%2i + %2i == %2i)\n", + ai, bi, ci, a[ai], b[bi], c[ci]); + + goto next_sum; + } + } + + return 0; +} + + + + + + + + + + + diff --git a/spikes/quadrant-or-1.c b/spikes/quadrant-or-1.c new file mode 100644 index 0000000..a992d12 --- /dev/null +++ b/spikes/quadrant-or-1.c @@ -0,0 +1,37 @@ + +#include +#include + +void search( + int mask, + int ai, int bi, + int findme) +{ + if (mask) + { + if (findme & mask) + { + search(mask >> 1, ai, bi | mask, findme); + search(mask >> 1, ai | mask, bi, findme); + search(mask >> 1, ai | mask, bi | mask, findme); + } + else + { + search(mask >> 1, ai, bi, findme); + } + } + else + { + assert((ai | bi) == findme); + + printf("0b%04b | 0b%04b == 0b%04b " + "(%2i | %2i == %2i)\n", ai, bi, findme, ai, bi, findme); + } +} + +int main() +{ + search(0b1000, 0, 0, 11); + + return 0; +} diff --git a/spikes/quadrant-or-2.c b/spikes/quadrant-or-2.c new file mode 100644 index 0000000..aa6d69f --- /dev/null +++ b/spikes/quadrant-or-2.c @@ -0,0 +1,220 @@ + +#include +#include + +#ifdef ZDEBUG + #define zprintf(fmt, ...) printf(fmt, ## __VA_ARGS__); +#else + #define zprintf(...) ; +#endif + +// 0 1 2 3 4 5 6 7 8 9 +int a[10] = { 2, 4, 5, 7, 9, 11, 15, 17, 17, 19}; +int b[10] = {10, 11, 11, 14, 14, 19, 20, 23, 26, 29}; + +// [ 0] [ 1] [ 2] [ 3] [ 4] [ 5] [ 6] [ 7] [ 8] [ 9] +// 2 4 5 7 9 11 15 17 17 19 +// -------------------------------------------------- +// [ 0] 10 | 10 14 15 15 11 11 15 27 27 27 + +// [ 1] 11 | 11 15 15 15 11 11 15 27 27 27 + +// [ 2] 11 | 11 15 15 15 11 11 15 27 27 27 + +// [ 3] 14 | 14 14 15 15 15 15 15 31 31 31 + +// [ 4] 14 | 14 14 15 15 15 15 15 31 31 31 + +// [ 5] 19 | 19 (23) (23) (23) 27 27 31 19 19 19 + +// [ 6] 20 | 22 20 21 (23) 29 31 31 21 21 (23) + +// [ 7](23)|(23) (23) (23) (23) 31 31 31 (23) (23) (23) + +// [ 8] 26 | 26 30 31 31 27 27 31 27 27 27 + +// [ 9] 29 | 31 29 29 31 29 31 31 29 29 31 + +int binary( + int mask, + int *array, + int i, int n) +{ + while (n > 1) + { + int m = n / 2; + + if (array[i + m] & mask) + n = m; + else + i += m, n = n - m; + } + + return (array[i] & mask) ? i : i + 1; +} + +void search( + int mask, + int ai, int an, + int bi, int bn, + int findme, + int calldepth) +{ + zprintf("%*s" "search():" "\n", calldepth++, ""); + + zprintf("%*s" "mask = 0b%05b" "\n", calldepth, "", mask); + + zprintf("%*s" "findme = 0b%05b" "\n", calldepth, "", findme); + + zprintf("%*s" "ai = %i" "\n", calldepth, "", ai); + zprintf("%*s" "an = %i" "\n", calldepth, "", an); + + zprintf("%*s" "bi = %i" "\n", calldepth, "", bi); + zprintf("%*s" "bn = %i" "\n", calldepth, "", bn); + + if (mask) + { + int asplit = binary(mask, a + ai, 0, an); + int bsplit = binary(mask, b + bi, 0, bn); + + zprintf("%*s" "asplit = %i" "\n", calldepth, "", asplit); + zprintf("%*s" "bsplit = %i" "\n", calldepth, "", bsplit); + + assert((asplit == an) || (a[ai + asplit] & mask)); + assert((bsplit == bn) || (b[bi + bsplit] & mask)); + + if (mask & findme) + { + zprintf("%*s" "one path" "\n", calldepth, ""); + + // 0 ... (asplit - 1) | asplit ... (an - 1) + // --------------------- ------------------- + // 0 | | | + // ... | first quadrant. | second quadrant | + // (bsplit - 1) | | | + // --- ---------------------- ------------------- + // bsplit | | | + // ... | third quadrant | fourth quadrant | + // (bn - 1) | | | + // --- | | | + // ---------------------- ------------------- + + // second quadrant. + if (asplit < an && 0 < bsplit) + { + zprintf("%*s" "entering second quadrant." "\n", calldepth, ""); + + search( + mask >> 1, + ai + asplit, an - asplit, + bi, bsplit, + findme, + calldepth); + } + else + { + zprintf("%*s" "empty second quadrant." "\n", calldepth, ""); + } + + // third quadrant. + if (0 < asplit && bsplit < bn) + { + zprintf("%*s" "entering third quadrant." "\n", calldepth, ""); + + search( + mask >> 1, + ai, asplit, + bi + bsplit, bn - bsplit, + findme, + calldepth); + } + else + { + zprintf("%*s" "empty third quadrant." "\n", calldepth, ""); + } + + // fourth quadrant. + if (asplit < an && bsplit < bn) + { + zprintf("%*s" "entering fourth quadrant." "\n", calldepth, ""); + + search( + mask >> 1, + ai + asplit, an - asplit, + bi + bsplit, bn - bsplit, + findme, + calldepth); + } + else + { + zprintf("%*s" "empty fourth quadrant." "\n", calldepth, ""); + } + } + else + { + zprintf("%*s" "zero path" "\n", calldepth, ""); + + // first quadrant. + if (0 < asplit && 0 < bsplit) + { + zprintf("%*s" "entering first quadrant." "\n", calldepth, ""); + + search( + mask >> 1, + ai, asplit, + bi, bsplit, + findme, + calldepth); + } + else + { + zprintf("%*s" "empty first quadrant." "\n", calldepth, ""); + } + } + } + else for (int i = 0; i < an; i++) + { + for (int j = 0; j < bn; j++) + { + assert((a[ai + i] | b[bi + j]) == findme); + + printf("%2i [%2i] (0b%05b) | %2i [%2i] " + "(0b%05b) == %2i (0b%05b)" "\n", + a[ai + i], ai + i, a[ai + i], + b[bi + j], bi + j, b[bi + j], + findme, findme); + } + } + + calldepth--; +} + +int main() +{ + search( + 16, + 0, 10, + 0, 10, + 23, + 0); + + return 0; +} + + + + + + + + + + + + + + + + + + diff --git a/spikes/quadrant-reverse-or-with-lists.c b/spikes/quadrant-reverse-or-with-lists.c new file mode 100644 index 0000000..81b11c6 --- /dev/null +++ b/spikes/quadrant-reverse-or-with-lists.c @@ -0,0 +1,341 @@ + +#include +#include +#include + +#ifdef ZDEBUG + #define zprintf(fmt, ...) printf(fmt, ## __VA_ARGS__); +#else + #define zprintf(...) ; +#endif + +#define N (256) + +#define M (255) + +struct sparselist { + int headtails[N], next[N], head; + + bool in[N]; +} b, c; + +void init(struct sparselist* this) +{ + this->head = -1; + + for (int i = 0; i < N; i++) + { + this->headtails[i] = -1; + + this->next[i] = -1; + + this->in[i] = false; + } +} + +void print(struct sparselist* this) +{ + puts("print():"); + + for (int i = 0; i < N; i++) + { + if (this->headtails[i] != -1) + { + printf(" " "headtails[%3i (0b%08b)] = %i" "\n", i, i, this->headtails[i]); + } + } + + printf("head = %i\n", this->head); + + for (int index = this->head; index != -1; index = this->next[index]) + { + printf(" " "index = %i\n", index); + } +} + +void insert(struct sparselist* this, int index) +{ + assert(!this->in[index]); + + int head = index & 1 ? index & ~(index & -index) : index, prevhead = -1; + + while (this->headtails[head] == -1 || index < this->headtails[head]) + { + this->headtails[head] = index; + prevhead = head, head = head & ~(head & -head); + } + + if (this->headtails[head] < index) + { + if (prevhead == -1) + { + assert(this->headtails[head] == head); + + assert(this->in[head]); + + this->next[head] = index; + } + else + { + int tophalftail = this->headtails[prevhead - 1]; + + assert(tophalftail != -1); + + this->next[tophalftail] = index; + } + } + else + { + this->head = index; + } + + int n = ~index & M; + int tail = index & 1 ? index : index | (n & -n), prevtail = -1; + + while (this->headtails[tail] == -1 || this->headtails[tail] < index) + { + this->headtails[tail] = index; + prevtail = tail, tail = tail | (n = ~tail & M, n & -n); + } + + if (index < this->headtails[tail]) + { + if (prevtail == -1) + { + assert(this->headtails[tail] == tail); + + assert(this->in[tail]); + + this->next[index] = tail; + } + else + { + int bottomhalfhead = this->headtails[prevtail + 1]; + + assert(bottomhalfhead != -1); + + this->next[index] = bottomhalfhead; + } + } + else + { + this->next[index] = -1; + } + + this->in[index] = true; +} + +int a = 17; + +void search( + int mask, + int bheadindex, int btailindex, + int cheadindex, int ctailindex, + int calldepth) +{ + zprintf("%*s" "quadrant_search():" "\n", calldepth++, ""); + + zprintf("%*s" "mask = 0b%05b" "\n", calldepth, "", mask); + + zprintf("%*s" "bheadindex = %i" "\n", calldepth, "", bheadindex); + zprintf("%*s" "btailindex = %i" "\n", calldepth, "", btailindex); + + zprintf("%*s" "cheadindex = %i" "\n", calldepth, "", cheadindex); + zprintf("%*s" "ctailindex = %i" "\n", calldepth, "", ctailindex); + + if (mask) + { + // 0 ... (bsplit - 1) | bsplit ... (an - 1) + // --------------------- ------------------- + // 0 | | | + // ... | first quadrant. | second quadrant | + // (csplit - 1) | | | + // --- ---------------------- ------------------- + // csplit | | | + // ... | third quadrant | fourth quadrant | + // (cn - 1) | | | + // --- | | | + // ---------------------- ------------------- + + if (mask & a) + { + zprintf("%*s" "one case" "\n", calldepth, ""); + + // third quadrant + int q3_btailindex = btailindex & ~mask; + int q3_cheadindex = cheadindex | mask; + + zprintf("%*s" "q3_btailindex = %i" "\n", calldepth, "", q3_btailindex); + zprintf("%*s" "q3_cheadindex = %i" "\n", calldepth, "", q3_cheadindex); + + if (true + && b.headtails[q3_btailindex] != -1 + && c.headtails[q3_cheadindex] != -1) + { + zprintf("%*s" "entering third quadrant." "\n", calldepth, ""); + + search( + mask >> 1, + bheadindex, q3_btailindex, + q3_cheadindex, ctailindex, + calldepth); + } + else + { + zprintf("%*s" "empty third quadrant." "\n", calldepth, ""); + } + + // fourth quadrant + int q4_bheadindex = bheadindex | mask; + int q4_cheadindex = cheadindex | mask; + + if (true + && b.headtails[q4_bheadindex] != -1 + && c.headtails[q4_cheadindex] != -1) + { + zprintf("%*s" "entering fourth quadrant." "\n", calldepth, ""); + + search( + mask >> 1, + q4_bheadindex, btailindex, + q4_cheadindex, ctailindex, + calldepth); + } + else + { + zprintf("%*s" "empty fourth quadrant." "\n", calldepth, ""); + } + } + else + { + zprintf("%*s" "zero case" "\n", calldepth, ""); + + // first quadrant + int q1_btailindex = btailindex & ~mask; + int q1_ctailindex = ctailindex & ~mask; + + zprintf("%*s" "q1_btailindex = %i" "\n", calldepth, "", q1_btailindex); + zprintf("%*s" "q1_ctailindex = %i" "\n", calldepth, "", q1_ctailindex); + + if (true + && b.headtails[q1_btailindex] != -1 + && c.headtails[q1_ctailindex] != -1) + { + zprintf("%*s" "entering first quadrant." "\n", calldepth, ""); + + search( + mask >> 1, + bheadindex, q1_btailindex, + cheadindex, q1_ctailindex, + calldepth); + } + else + { + zprintf("%*s" "empty first quadrant." "\n", calldepth, ""); + } + + // fourth quadrant + int q4_bheadindex = bheadindex | mask; + int q4_cheadindex = cheadindex | mask; + + if (true + && b.headtails[q4_bheadindex] != -1 + && c.headtails[q4_cheadindex] != -1) + { + zprintf("%*s" "entering fourth quadrant." "\n", calldepth, ""); + + search( + mask >> 1, + q4_bheadindex, btailindex, + q4_cheadindex, ctailindex, + calldepth); + } + else + { + zprintf("%*s" "empty fourth quadrant." "\n", calldepth, ""); + } + } + } + else + { + assert(bheadindex == btailindex); + assert(cheadindex == ctailindex); + + int be = b.headtails[bheadindex]; + + int ce = c.headtails[cheadindex]; + + if (be == bheadindex && ce == cheadindex && (a | be) == ce) + { + assert(b.in[be]); + assert(c.in[ce]); + + printf("%2i (0b%05b) | %2i (0b%05b) == %2i (0b%05b)" "\n", + a, a, be, be, ce, ce); + } + } + + calldepth--; +} + +int main() +{ + puts("hello, world!"); + + init(&b); + insert(&b, 10); + insert(&b, 11); + insert(&b, 14); + insert(&b, 19); + insert(&b, 20); + insert(&b, 23); + insert(&b, 26); + insert(&b, 29); + + #ifdef ZDEBUG + print(&b); + #endif + + init(&c); + insert(&c, 15); + insert(&c, 17); + insert(&c, 19); + insert(&c, 21); + insert(&c, 22); + insert(&c, 25); + insert(&c, 26); + insert(&c, 27); + insert(&c, 32); + insert(&c, 33); + insert(&c, 36); + insert(&c, 39); + insert(&c, 42); + insert(&c, 44); + insert(&c, 48); + insert(&c, 49); + + #ifdef ZDEBUG + print(&c); + #endif + + search(128, 0, 255, 0, 255, 0); + + return 0; +} + + + + + + + + + + + + + + + + + diff --git a/spikes/quadrant-reverse-or.c b/spikes/quadrant-reverse-or.c new file mode 100644 index 0000000..d5fc971 --- /dev/null +++ b/spikes/quadrant-reverse-or.c @@ -0,0 +1,271 @@ + +#include +#include + +#ifdef ZDEBUG + #define zprintf(fmt, ...) printf(fmt, ## __VA_ARGS__); +#else + #define zprintf(...) ; +#endif + +int a = 17; + +// 0 1 2 3 4 5 6 7 8 9 +int b[10] = {10, 11, 11, 14, 14, 19, 20, 23, 26, 29}; + +int c[20] = { +// 0 1 2 3 4 5 6 7 8 9 + 15, 17, 19, 21, 22, 25, 26, 26, 27, 32, + +// 10 11 12 13 14 15 16 17 18 19 + 33, 33, 36, 39, 42, 44, 48, 49, 49, 49 +}; + +// [ 0] [ 1] [ 2] [ 3] [ 4] [ 5] [ 6] [ 7] [ 8] [ 9] +// 10 11 11 14 14 19 20 23 26 29 +// -------------------------------------------------- +// [ 0] 15 | 5 4 4 1 1 12 11 8 5 2 + +// [ 1] 17 | 17 16 16 17 17 0 1 0 1 0 + +// [ 2] 19 | 17 16 16 17 17 (0) 3 0 1 2 + +// [ 3] 21 | 21 20 20 17 17 4 (1) 0 5 0 + +// [ 4] 22 | 20 20 20 16 16 4 2 0 4 2 + +// [ 5] 25 | 17 16 16 17 17 8 9 8 1 0 + +// [ 6] 26 | 16 16 16 16 16 8 10 8 0 2 + +// [ 7] 26 | 16 16 16 16 16 8 10 8 0 2 + +// [ 8] 27 |(17) (16) (16) 17 17 8 11 8 ( 1) 2 + +// [ 9] 32 | 32 32 32 32 32 32 32 32 32 32 + +// [10] 33 | 33 32 32 33 33 32 33 32 33 32 + +// [11] 33 | 33 32 32 33 33 32 33 32 33 32 + +// [12] 36 | 36 36 36 32 32 36 32 32 36 32 + +// [13] 39 | 37 36 36 33 33 36 35 32 37 34 + +// [14] 42 | 32 32 32 32 32 40 42 40 32 34 + +// [15] 44 | 36 36 36 32 32 44 40 40 36 32 + +// [16] 48 | 48 48 48 48 48 32 32 32 32 32 + +// [17] 49 | 49 48 48 49 49 32 33 32 33 32 + +// [18] 49 | 49 48 48 49 49 32 33 32 33 32 + +// [19] 49 | 49 48 48 49 49 32 33 32 33 32 + +int binary( + int mask, + int *array, + int i, int n) +{ + while (n > 1) + { + int m = n / 2; + + if (array[i + m] & mask) + n = m; + else + i += m, n = n - m; + } + + return (array[i] & mask) ? i : i + 1; +} + +void quadrant_search( + int mask, + int bi, int bn, + int ci, int cn, + int calldepth) +{ + zprintf("%*s" "quadrant_search():" "\n", calldepth++, ""); + + zprintf("%*s" "mask = 0b%05b" "\n", calldepth, "", mask); + + zprintf("%*s" "bi = %i" "\n", calldepth, "", bi); + zprintf("%*s" "bn = %i" "\n", calldepth, "", bn); + + zprintf("%*s" "ci = %i" "\n", calldepth, "", ci); + zprintf("%*s" "cn = %i" "\n", calldepth, "", cn); + + if (mask) + { + int bsplit = binary(mask, b + bi, 0, bn); + int csplit = binary(mask, c + ci, 0, cn); + + zprintf("%*s" "bsplit = %i" "\n", calldepth, "", bsplit); + zprintf("%*s" "csplit = %i" "\n", calldepth, "", csplit); + + assert((bsplit == bn) || (b[bi + bsplit] & mask)); + assert((csplit == cn) || (c[ci + csplit] & mask)); + + // 0 ... (bsplit - 1) | bsplit ... (an - 1) + // --------------------- ------------------- + // 0 | | | + // ... | first quadrant. | second quadrant | + // (csplit - 1) | | | + // --- ---------------------- ------------------- + // csplit | | | + // ... | third quadrant | fourth quadrant | + // (cn - 1) | | | + // --- | | | + // ---------------------- ------------------- + + if (mask & a) + { + zprintf("%*s" "one case" "\n", calldepth, ""); + + // third quadrant + if (0 < bsplit && csplit < cn) + { + zprintf("%*s" "entering third quadrant." "\n", calldepth, ""); + + quadrant_search( + mask >> 1, + bi, bsplit, + ci + csplit, cn - csplit, + calldepth); + } + else + { + zprintf("%*s" "empty third quadrant." "\n", calldepth, ""); + } + + // fourth quadrant + if (bsplit < bn && csplit < cn) + { + zprintf("%*s" "entering fourth quadrant." "\n", calldepth, ""); + + quadrant_search( + mask >> 1, + bi + bsplit, bn - bsplit, + ci + csplit, cn - csplit, + calldepth); + } + else + { + zprintf("%*s" "empty fourth quadrant." "\n", calldepth, ""); + } + } + else + { + zprintf("%*s" "zero case" "\n", calldepth, ""); + + // first quadrant + if (0 < bsplit && 0 < csplit) + { + zprintf("%*s" "entering first quadrant." "\n", calldepth, ""); + + quadrant_search( + mask >> 1, + bi, bsplit, + ci, csplit, + calldepth); + } + else + { + zprintf("%*s" "empty first quadrant." "\n", calldepth, ""); + } + + // fourth quadrant + if (bsplit < bn && csplit < cn) + { + zprintf("%*s" "entering fourth quadrant." "\n", calldepth, ""); + + quadrant_search( + mask >> 1, + bi + bsplit, bn - bsplit, + ci + csplit, cn - csplit, + calldepth); + } + else + { + zprintf("%*s" "empty fourth quadrant." "\n", calldepth, ""); + } + } + } + else for (int i = 0; i < bn; i++) + { + for (int j = 0; j < cn; j++) + { + assert((a | b[bi + i]) == c[ci + j]); + + printf("%2i (0b%05b) | %2i [%2i] " + "(0b%05b) == %2i [%2i] (0b%05b)" "\n", + a, a, + b[bi + i], bi + i, b[bi + i], + c[ci + j], ci + j, c[ci + j]); + } + } + + calldepth--; +} + +void brute_force_search(int bn, int cn) +{ + for (int bi = 0; bi < bn; bi++) + { + for (int ci = 0; ci < cn; ci++) + { + if ((a | b[bi]) == c[ci]) + { + printf("%2i (0b%05b) | %2i [%2i] " + "(0b%05b) == %2i [%2i] (0b%05b)" "\n", + a, a, + b[bi], bi, b[bi], + c[ci], ci, c[ci]); + } + } + } +} + +int main() +{ + puts("divide-and-conquer:"); + + quadrant_search(32, 0, 10, 0, 20, 0); + + puts(""); + + puts("brute-force:"); + brute_force_search(10, 20); + + return 0; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spikes/sorted-sparse-list-insert.c b/spikes/sorted-sparse-list-insert.c new file mode 100644 index 0000000..61c1d1c --- /dev/null +++ b/spikes/sorted-sparse-list-insert.c @@ -0,0 +1,242 @@ + +#include +#include +#include + +#define N (256) + +#define M (255) + +int headtails[N], next[N], globalhead = -1; + +bool in[N]; + +void init() +{ + for (int i = 0; i < N; i++) + { + headtails[i] = -1; + + next[i] = -1; + + in[i] = false; + } +} + +void print() +{ + puts("print():"); + + for (int i = 0; i < N; i++) + { + if (headtails[i] != -1) + { + printf(" " "headtails[%3i (0b%08b)] = %i" "\n", i, i, headtails[i]); + } + } + + printf("globalhead = %i\n", globalhead); + + for (int index = globalhead; index != -1; index = next[index]) + { + printf(" " "index = %i\n", index); + } +} + +void insert(int index) +{ + printf("insert():" "\n"); + + assert(!in[index]); + + printf(" " "index = %i (0b%08b)" "\n", index, index); + + int head = index & 1 ? index & ~(index & -index) : index, prevhead = -1; + + printf(" " "head = %i (0b%08b)" "\n", head, head); + + // while they're blank or we beat them: + while (headtails[head] == -1 || index < headtails[head]) + { + headtails[head] = index; + + printf(" " "headtails[%i] = %i" "\n", head, index); + + prevhead = head, head = head & ~(head & -head); + + printf(" " "head = %i (0b%08b)" "\n", head, head); + } + + // there should be only two reasons why we're stopped: + // - because we hit the limits of the list + // - because we found someone who beat us. + + if (headtails[head] < index) + { + printf(" " "hit someone with a better head" "\n"); + + printf(" " "prevhead = %i (0b%08b)" "\n", prevhead, prevhead); + + if (prevhead == -1) + { + // if we got beat imeedately, connect to them. + + assert(headtails[head] == head); + + assert(in[head]); + + next[head] = index; + + printf(" " "next[%i] = %i" "\n", head, next[head]); + } + else + { + // we must be coming out of the bottom half + + // and if we lost, then we know there must be elements in the + // first half that should come before us. + + // and that we should connect to their tail. + + // so the top-half's tail's "next" should point to us. + + // and we also know that the top-half's tail comes right before + // our previous's head. + + int tophalftail = headtails[prevhead - 1]; + + printf(" " "tophalftail = %i" "\n", tophalftail); + + assert(tophalftail != -1); + + next[tophalftail] = index; + + printf(" " "next[%i] = %i" "\n", tophalftail, next[tophalftail]); + } + } + else + { + printf(" " "hit the lower limit of the list" "\n"); + + globalhead = index; + + printf(" " "globalhead = %i" "\n", globalhead); + } + + int n = ~index & M; + int tail = index & 1 ? index : index | (n & -n), prevtail = -1; + + printf(" " "tail = %i (0b%08b)" "\n", tail, tail); + + // while they're blank: + while (headtails[tail] == -1 || headtails[tail] < index) + { + headtails[tail] = index; + + printf(" " "headtails[%i] = %i" "\n", tail, index); + + prevtail = tail, tail = tail | (n = ~tail & M, n & -n); + + printf(" " "tail = %i (0b%08b)" "\n", tail, tail); + } + + // there should be only two reasons why we're stopped: + // - because we hit the limits of the list + // - because we found someone who beat us. + + if (index < headtails[tail]) + { + printf(" " "hit someone with a better tail" "\n"); + + printf(" " "prevtail = %i (0b%08b)" "\n", prevtail, prevtail); + + if (prevtail == -1) + { + // if we got beat imeedately, connect to them. + + assert(headtails[tail] == tail); + + assert(in[tail]); + + next[index] = tail; + + printf(" " "next[%i] = %i" "\n", index, next[index]); + } + else + { + // we must be coming out of the top half + + // and if we lost, then we know there must be elements in the + // second half that should come after us. + + // and that we should connect to their head. + + // so we should point to the bottom half's "head" + + // and we also know that the bottom half's haed comes right before + // our previous's tail. + + int bottomhalfhead = headtails[prevtail + 1]; + + printf(" " "bottomhalfhead = %i" "\n", bottomhalfhead); + + assert(bottomhalfhead != -1); + + next[index] = bottomhalfhead; + + printf(" " "next[%i] = %i" "\n", index, next[index]); + } + } + else + { + printf(" " "hit the lower limit of the list" "\n"); + + next[index] = -1; + + printf(" " "next[%i] = %i" "\n", index, next[index]); + } + + in[index] = true; +} + +int main() +{ + puts("hello, world!"); + + init(); + + print(); + + insert(42); print(); + +/* insert(200); print();*/ + +/* insert(128); print();*/ + + insert(224); print(); + +/* insert(1); print();*/ +/* */ +/* insert(255); print();*/ + + insert(96); print(); + + insert(97); print(); + + insert(98); print(); + + insert(99); print(); + + return 0; +} + + + + + + + + + + +