Compare commits
21 commits
main
...
dev-assign
| Author | SHA1 | Date | |
|---|---|---|---|
| 154b1b38bf | |||
| 21c7967f44 | |||
| 6529ab9818 | |||
| 08b5f47426 | |||
| 3213e1deac | |||
| 15a09a1506 | |||
| 1b9fe3b44a | |||
| ff78073433 | |||
| 7f012a32c8 | |||
| 6f326a9bcb | |||
| 8152650e06 | |||
| 99e5f2d8e6 | |||
| 6b8ff52061 | |||
| 90068e62fa | |||
| 82db0d4e03 | |||
| d9556aeae9 | |||
| 105e9306a4 | |||
| 1097f2c2d8 | |||
| 27bef1109d | |||
| 82a102c421 | |||
| cb1738376d |
43 changed files with 6548 additions and 1365 deletions
14
.gitignore
vendored
14
.gitignore
vendored
|
|
@ -1,5 +1,19 @@
|
||||||
|
|
||||||
|
bin
|
||||||
|
|
||||||
|
.simplifications.bin
|
||||||
|
.~lock.stats.ods#
|
||||||
|
stats.ods
|
||||||
|
|
||||||
|
|
||||||
simplifications.bin
|
simplifications.bin
|
||||||
|
|
||||||
.simplifier-*.bin
|
.simplifier-*.bin
|
||||||
|
|
||||||
|
.direnv/
|
||||||
|
|
||||||
|
typescript
|
||||||
|
|
||||||
|
vgcore.*
|
||||||
|
|
||||||
|
*~
|
||||||
|
|
|
||||||
18
buildtypes/debug.txt
Normal file
18
buildtypes/debug.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
-g
|
||||||
|
|
||||||
|
-D _GNU_SOURCE
|
||||||
|
|
||||||
|
-D ZDEBUG=1
|
||||||
|
|
||||||
|
-D DEBUG_BUILD
|
||||||
|
|
||||||
|
-I .
|
||||||
|
|
||||||
|
-Werror -Wall -Wextra -Wstrict-prototypes -Wfatal-errors
|
||||||
|
|
||||||
|
-Wno-unused
|
||||||
|
|
||||||
|
-lreadline
|
||||||
|
-lm
|
||||||
|
|
||||||
14
buildtypes/release.txt
Normal file
14
buildtypes/release.txt
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
-D _GNU_SOURCE
|
||||||
|
|
||||||
|
-D ZDEBUG=0
|
||||||
|
|
||||||
|
-I .
|
||||||
|
|
||||||
|
-O3
|
||||||
|
|
||||||
|
-Werror -Wall -Wextra -Wstrict-prototypes -Wfatal-errors
|
||||||
|
|
||||||
|
-lreadline
|
||||||
|
-lm
|
||||||
|
|
||||||
18
buildtypes/test-multithreaded.txt
Normal file
18
buildtypes/test-multithreaded.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
-g
|
||||||
|
|
||||||
|
-D _GNU_SOURCE
|
||||||
|
|
||||||
|
-D TEST_BUILD
|
||||||
|
|
||||||
|
-D MULTITHREADED_BUILD
|
||||||
|
|
||||||
|
-I .
|
||||||
|
|
||||||
|
-Werror -Wall -Wextra -Wstrict-prototypes -Wfatal-errors
|
||||||
|
|
||||||
|
-Wno-unused
|
||||||
|
|
||||||
|
-lreadline
|
||||||
|
-lm
|
||||||
|
|
||||||
18
buildtypes/test.txt
Normal file
18
buildtypes/test.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
-g
|
||||||
|
|
||||||
|
-D _GNU_SOURCE
|
||||||
|
|
||||||
|
-D ZDEBUG=0
|
||||||
|
|
||||||
|
-D TEST_BUILD
|
||||||
|
|
||||||
|
-I .
|
||||||
|
|
||||||
|
-Werror -Wall -Wextra -Wstrict-prototypes -Wfatal-errors
|
||||||
|
|
||||||
|
-Wno-unused
|
||||||
|
|
||||||
|
-lreadline
|
||||||
|
-lm
|
||||||
|
|
||||||
41
calculate_assignment_simplifications.c
Normal file
41
calculate_assignment_simplifications.c
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <defines.h>
|
||||||
|
|
||||||
|
#include <cmdln.h>
|
||||||
|
|
||||||
|
#include "simplifications.h"
|
||||||
|
#include "calculate_simplifications.h"
|
||||||
|
#include "calculate_assignment_simplifications.h"
|
||||||
|
|
||||||
|
void calculate_assignment_simplifications(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps)
|
||||||
|
{
|
||||||
|
ENTER;
|
||||||
|
|
||||||
|
struct cmdln_flags flag_no_assign = *flags;
|
||||||
|
|
||||||
|
flag_no_assign.use_operators.assignment = false;
|
||||||
|
|
||||||
|
for (int a = 0; a < N; a++)
|
||||||
|
{
|
||||||
|
simps->with_vars[a] = \
|
||||||
|
calculate_simplifications(
|
||||||
|
/* cmdln flags: */ &flag_no_assign,
|
||||||
|
/* have extra variable? */ true,
|
||||||
|
/* extra variable value: */ a);
|
||||||
|
}
|
||||||
|
|
||||||
|
simps->main = calculate_simplifications(flags, false, 0);
|
||||||
|
|
||||||
|
EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
11
calculate_assignment_simplifications.h
Normal file
11
calculate_assignment_simplifications.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
struct cmdln_flags;
|
||||||
|
struct simplifications;
|
||||||
|
|
||||||
|
void calculate_assignment_simplifications(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps);
|
||||||
|
|
||||||
|
#endif
|
||||||
637
calculate_simplifications.c
Normal file
637
calculate_simplifications.c
Normal file
|
|
@ -0,0 +1,637 @@
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <cmdln.h>
|
||||||
|
|
||||||
|
#include <print.h>
|
||||||
|
|
||||||
|
#ifdef MULTITHREADED_BUILD
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "calculate_simplifications.h"
|
||||||
|
|
||||||
|
void helper(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps,
|
||||||
|
bool have_extra_variable,
|
||||||
|
uint16_t A)
|
||||||
|
{
|
||||||
|
ENTER;
|
||||||
|
|
||||||
|
struct row* row = have_extra_variable ? &simps->with_vars[A] : &simps->main;
|
||||||
|
|
||||||
|
// init 'row->data':
|
||||||
|
{
|
||||||
|
for (int i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
row->data[i].kind = ek_unreachable;
|
||||||
|
|
||||||
|
row->data[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);
|
||||||
|
|
||||||
|
uint16_t retval = todo.data[0];
|
||||||
|
|
||||||
|
todo.reverse[retval] = -1;
|
||||||
|
|
||||||
|
uint16_t moving = todo.data[todo.n-- - 1];
|
||||||
|
|
||||||
|
int cost = row->data[moving].cost;
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
again:
|
||||||
|
{
|
||||||
|
int left = index * 2 + 1;
|
||||||
|
int right = index * 2 + 2;
|
||||||
|
|
||||||
|
uint16_t smallest = moving;
|
||||||
|
|
||||||
|
if (left < todo.n && row->data[todo.data[left]].cost < cost)
|
||||||
|
smallest = todo.data[left];
|
||||||
|
|
||||||
|
if (right < todo.n && row->data[todo.data[right]].cost < row->data[smallest].cost)
|
||||||
|
smallest = todo.data[right];
|
||||||
|
|
||||||
|
if (smallest == moving)
|
||||||
|
{
|
||||||
|
todo.data[index] = moving;
|
||||||
|
|
||||||
|
todo.reverse[moving] = index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int new = todo.reverse[smallest];
|
||||||
|
|
||||||
|
todo.data[index] = smallest;
|
||||||
|
|
||||||
|
todo.reverse[smallest] = index;
|
||||||
|
|
||||||
|
index = new;
|
||||||
|
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(uint16_t truthtable, int cost)
|
||||||
|
{
|
||||||
|
assert(todo.reverse[truthtable] == -1);
|
||||||
|
|
||||||
|
int index = todo.n++, new_index;
|
||||||
|
|
||||||
|
while (index > 0 && row->data[todo.data[new_index = (index - 1) / 2]].cost > cost)
|
||||||
|
{
|
||||||
|
todo.data[index] = todo.data[new_index];
|
||||||
|
|
||||||
|
todo.reverse[todo.data[new_index]] = index;
|
||||||
|
|
||||||
|
index = new_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
todo.data[index] = truthtable;
|
||||||
|
|
||||||
|
todo.reverse[truthtable] = index;
|
||||||
|
|
||||||
|
row->data[truthtable].cost = cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(uint16_t truthtable, int cost)
|
||||||
|
{
|
||||||
|
assert(todo.reverse[truthtable] != -1);
|
||||||
|
|
||||||
|
assert(cost < row->data[truthtable].cost);
|
||||||
|
|
||||||
|
int index =todo. reverse[truthtable], new_index;
|
||||||
|
|
||||||
|
while (index > 0 && row->data[todo.data[new_index = (index - 1) / 2]].cost > cost)
|
||||||
|
{
|
||||||
|
todo.data[index] = todo.data[new_index];
|
||||||
|
|
||||||
|
todo.reverse[todo.data[new_index]] = index;
|
||||||
|
|
||||||
|
index = new_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
todo.data[index] = truthtable;
|
||||||
|
todo.reverse[truthtable] = index;
|
||||||
|
|
||||||
|
row->data[truthtable].cost = cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a list of the "done" truthtables
|
||||||
|
struct {
|
||||||
|
int headtails[N], next[N], head;
|
||||||
|
|
||||||
|
// for debugging:
|
||||||
|
#if ZDEBUG
|
||||||
|
bool in[N];
|
||||||
|
#endif
|
||||||
|
} done = {};
|
||||||
|
|
||||||
|
// init 'done':
|
||||||
|
{
|
||||||
|
done.head = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
done.headtails[i] = -1;
|
||||||
|
|
||||||
|
#if ZDEBUG
|
||||||
|
done.in[i] = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(int index)
|
||||||
|
{
|
||||||
|
#if ZDEBUG
|
||||||
|
assert(!done.in[index]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#if ZDEBUG
|
||||||
|
assert(done.in[tail]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
done.next[index] = tail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int bottomhalfhead = done.headtails[prevtail + 1];
|
||||||
|
|
||||||
|
assert(bottomhalfhead != -1);
|
||||||
|
|
||||||
|
done.next[index] = bottomhalfhead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
done.next[index] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ZDEBUG
|
||||||
|
done.in[index] = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
append(W, 0), row->data[W].kind = ek_W;
|
||||||
|
append(X, 0), row->data[X].kind = ek_X;
|
||||||
|
append(Y, 0), row->data[Y].kind = ek_Y;
|
||||||
|
append(Z, 0), row->data[Z].kind = ek_Z;
|
||||||
|
|
||||||
|
append(0, 1), row->data[0].kind = ek_0;
|
||||||
|
append(M, 1), row->data[M].kind = ek_1;
|
||||||
|
|
||||||
|
if (have_extra_variable && todo.reverse[A] == -1)
|
||||||
|
{
|
||||||
|
append(A, 0), row->data[A].kind = ek_A;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable terminal autowrap:
|
||||||
|
if (!ZDEBUG && flags->verbose && flags->print_with_color)
|
||||||
|
{
|
||||||
|
printf("\e[?7l");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int iterations = 1; todo.n && iterations <= N; iterations++)
|
||||||
|
{
|
||||||
|
uint16_t truthtable = pop();
|
||||||
|
|
||||||
|
insert(truthtable);
|
||||||
|
|
||||||
|
int cost = row->data[truthtable].cost;
|
||||||
|
|
||||||
|
if (flags->verbose)
|
||||||
|
{
|
||||||
|
if (!ZDEBUG && flags->print_with_color)
|
||||||
|
{
|
||||||
|
printf("\e[2K");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%i of %i (%.2f%%): [%i] ",
|
||||||
|
iterations, N, (100.0 * iterations / N), cost);
|
||||||
|
|
||||||
|
if (have_extra_variable)
|
||||||
|
{
|
||||||
|
printf("a = 0b%016b, ", A);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(flags, simps, row, truthtable);
|
||||||
|
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
if (!ZDEBUG && flags->print_with_color)
|
||||||
|
{
|
||||||
|
printf("\e[1A");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// consider NOT:
|
||||||
|
if (flags->use_operators.not)
|
||||||
|
{
|
||||||
|
uint16_t not_truthtable = ~truthtable & M;
|
||||||
|
|
||||||
|
int not_cost = cost + 1;
|
||||||
|
|
||||||
|
if (not_cost < row->data[not_truthtable].cost)
|
||||||
|
{
|
||||||
|
if (todo.reverse[not_truthtable] == -1)
|
||||||
|
{
|
||||||
|
append(not_truthtable, not_cost);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
update(not_truthtable, not_cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
row->data[not_truthtable].kind = ek_not;
|
||||||
|
row->data[not_truthtable].left = truthtable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BINARY_OPERATOR(ekind, function) \
|
||||||
|
{ \
|
||||||
|
for (int i = done.head; i != -1; i = done.next[i]) \
|
||||||
|
{ \
|
||||||
|
{ \
|
||||||
|
uint16_t bin_truthtable = function(truthtable, i) & M; \
|
||||||
|
\
|
||||||
|
int bin_cost = 1 + cost + row->data[i].cost; \
|
||||||
|
\
|
||||||
|
if (bin_cost < row->data[bin_truthtable].cost) \
|
||||||
|
{ \
|
||||||
|
if (todo.reverse[bin_truthtable] == -1) \
|
||||||
|
append(bin_truthtable, bin_cost); \
|
||||||
|
else \
|
||||||
|
update(bin_truthtable, bin_cost); \
|
||||||
|
\
|
||||||
|
row->data[bin_truthtable].kind = ekind; \
|
||||||
|
row->data[bin_truthtable].left = truthtable; \
|
||||||
|
row->data[bin_truthtable].right = i; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
{ \
|
||||||
|
uint16_t bin_truthtable = function(i, truthtable) & M; \
|
||||||
|
\
|
||||||
|
int bin_cost = 1 + cost + row->data[i].cost; \
|
||||||
|
\
|
||||||
|
if (bin_cost < row->data[bin_truthtable].cost) \
|
||||||
|
{ \
|
||||||
|
if (todo.reverse[bin_truthtable] == -1) \
|
||||||
|
append(bin_truthtable, bin_cost); \
|
||||||
|
else \
|
||||||
|
update(bin_truthtable, bin_cost); \
|
||||||
|
\
|
||||||
|
row->data[bin_truthtable].kind = ekind; \
|
||||||
|
row->data[bin_truthtable].left = i; \
|
||||||
|
row->data[bin_truthtable].right = truthtable; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OR(a, b) ((a) | (b))
|
||||||
|
#define AND(a, b) ((a) & (b))
|
||||||
|
|
||||||
|
#define ORN(a, b) (~(a) | (b))
|
||||||
|
#define NOR(a, b) ~( (a) | (b))
|
||||||
|
#define ANDN(a, b) (~(a) & (b))
|
||||||
|
#define NAND(a, b) ~( (a) & (b))
|
||||||
|
#define XOR(a, b) (( a) ^ (b))
|
||||||
|
#define NXOR(a, b) ~( (a) ^ (b))
|
||||||
|
|
||||||
|
#define LT(a, b) ((~a) & (b))
|
||||||
|
#define LTE(a, b) ((~a) | (b))
|
||||||
|
#define GT(a, b) (( a) & ~(b))
|
||||||
|
#define GTE(a, b) (( a) | ~(b))
|
||||||
|
|
||||||
|
if (flags->use_operators.or)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_or, OR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.and)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_and, AND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.orn)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_orn, ORN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.nor)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_nor, NOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.andn)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_andn, ANDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.nand)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_nand, NAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.xor)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_xor, XOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.nxor)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_nxor, NXOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.lt)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_lt, LT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.lte)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_lte, LTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.gt)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_gt, GT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.gte)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_gte, GTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.ternary)
|
||||||
|
{
|
||||||
|
for (int i = done.head; i != -1; i = done.next[i])
|
||||||
|
{
|
||||||
|
for (int j = done.head; j != -1; j = done.next[j])
|
||||||
|
{
|
||||||
|
int ternary_cost = 1 + cost + row->data[i].cost + row->data[j].cost;
|
||||||
|
|
||||||
|
#define TERNARY(C, T, F) \
|
||||||
|
{ \
|
||||||
|
uint16_t ternary_truthtable = \
|
||||||
|
((C) & (T)) | (~(C) & (F)); \
|
||||||
|
\
|
||||||
|
if (ternary_cost < row->data[ternary_truthtable].cost) \
|
||||||
|
{ \
|
||||||
|
if (todo.reverse[ternary_truthtable] == -1) \
|
||||||
|
{ \
|
||||||
|
append(ternary_truthtable, ternary_cost); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
update(ternary_truthtable, ternary_cost); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
row->data[ternary_truthtable].kind = ek_ternary; \
|
||||||
|
row->data[ternary_truthtable].cond = (C); \
|
||||||
|
row->data[ternary_truthtable].left = (T); \
|
||||||
|
row->data[ternary_truthtable].right = (F); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
TERNARY(truthtable, i, j);
|
||||||
|
TERNARY(i, truthtable, j);
|
||||||
|
TERNARY(i, j, truthtable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.assignment)
|
||||||
|
{
|
||||||
|
assert(row == &simps->main);
|
||||||
|
|
||||||
|
for (int t = 0; t < N; t++)
|
||||||
|
{
|
||||||
|
int using_me_cost = simps->with_vars[truthtable].data[t].cost;
|
||||||
|
|
||||||
|
if (using_me_cost < INT_MAX)
|
||||||
|
{
|
||||||
|
int assign_cost = cost + 1 + using_me_cost;
|
||||||
|
|
||||||
|
if (assign_cost < simps->main.data[t].cost)
|
||||||
|
{
|
||||||
|
if (todo.reverse[t] == -1)
|
||||||
|
{
|
||||||
|
append(t, assign_cost);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
update(t, assign_cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
row->data[t].kind = ek_assignment;
|
||||||
|
row->data[t].left = truthtable;
|
||||||
|
row->data[t].right = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear progress line, enable terminal autowrap:
|
||||||
|
if (!ZDEBUG && flags->verbose && flags->print_with_color)
|
||||||
|
{
|
||||||
|
printf("\e[2K"), printf("\e[?7h");
|
||||||
|
}
|
||||||
|
|
||||||
|
EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculate_simplifications(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps)
|
||||||
|
{
|
||||||
|
ENTER;
|
||||||
|
|
||||||
|
if (flags->use_operators.assignment)
|
||||||
|
{
|
||||||
|
struct cmdln_flags flag_no_assign = *flags;
|
||||||
|
|
||||||
|
flag_no_assign.use_operators.assignment = false;
|
||||||
|
|
||||||
|
#ifdef MULTITHREADED_BUILD
|
||||||
|
{
|
||||||
|
int num_cores = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
|
||||||
|
zprintf("num_cores = %i" "\n", num_cores);
|
||||||
|
|
||||||
|
assert(0 < num_cores && num_cores < 100);
|
||||||
|
|
||||||
|
struct cmdln_flags flag_no_verbose = flag_no_assign;
|
||||||
|
|
||||||
|
if (!flags->quiet && flags->verbose)
|
||||||
|
{
|
||||||
|
printf(""
|
||||||
|
"note: the usual verbosity is disabled in the "
|
||||||
|
"multithreaded section" "\n"
|
||||||
|
"");
|
||||||
|
|
||||||
|
flag_no_verbose.verbose = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int starts[num_cores];
|
||||||
|
|
||||||
|
void* runner(void* _start)
|
||||||
|
{
|
||||||
|
const int* start = _start;
|
||||||
|
|
||||||
|
for (int a = *start; a < N; a += num_cores)
|
||||||
|
{
|
||||||
|
if (flags->verbose)
|
||||||
|
{
|
||||||
|
printf("a = 0b%016b" "\n", a);
|
||||||
|
}
|
||||||
|
|
||||||
|
helper(
|
||||||
|
/* cmdln flags: */ &flag_no_verbose,
|
||||||
|
/* simplifications */ simps,
|
||||||
|
/* have extra variable? */ true,
|
||||||
|
/* extra variable value: */ a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t handles[num_cores];
|
||||||
|
|
||||||
|
for (int i = 0; i < num_cores; i++)
|
||||||
|
{
|
||||||
|
starts[i] = i;
|
||||||
|
|
||||||
|
pthread_create(
|
||||||
|
/* handle */ &handles[i],
|
||||||
|
/* attributes: */ NULL,
|
||||||
|
/* start_routine: */ runner,
|
||||||
|
/* arg: */ &starts[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_cores; i++)
|
||||||
|
{
|
||||||
|
pthread_join(
|
||||||
|
/* handle: */ handles[i],
|
||||||
|
/* return value: */ (void*[1]){});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
for (int a = 0; a < N; a++)
|
||||||
|
{
|
||||||
|
helper(
|
||||||
|
/* cmdln flags: */ &flag_no_assign,
|
||||||
|
/* simplifications */ simps,
|
||||||
|
/* have extra variable? */ true,
|
||||||
|
/* extra variable value: */ a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
helper(
|
||||||
|
/* cmdln flags: */ flags,
|
||||||
|
/* simplifications */ simps,
|
||||||
|
/* have extra variable? */ false,
|
||||||
|
/* extra variable value: */ 0);
|
||||||
|
|
||||||
|
EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
13
calculate_simplifications.h
Normal file
13
calculate_simplifications.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <expr.h>
|
||||||
|
|
||||||
|
#include <simplifications.h>
|
||||||
|
|
||||||
|
struct cmdln_flags;
|
||||||
|
|
||||||
|
|
||||||
|
void calculate_simplifications(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps);
|
||||||
214
cmdln.c
Normal file
214
cmdln.c
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "cmdln.h"
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
struct cmdln_flags parse_args(int argc, char* const* argv)
|
||||||
|
{
|
||||||
|
struct cmdln_flags flags = {};
|
||||||
|
|
||||||
|
flags.argv0 = argv[0];
|
||||||
|
|
||||||
|
bool unset_operators = true;
|
||||||
|
|
||||||
|
bool unset_print_with_color = true;
|
||||||
|
|
||||||
|
for (int opt; (opt = getopt(argc, argv, "pyqmvc:eEo:C:B")) != -1; )
|
||||||
|
{
|
||||||
|
switch (opt)
|
||||||
|
{
|
||||||
|
case 'p':
|
||||||
|
{
|
||||||
|
flags.print_all_and_quit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'y':
|
||||||
|
{
|
||||||
|
flags.assume_yes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
{
|
||||||
|
flags.quiet = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
{
|
||||||
|
flags.print_max_operators_needed_and_quit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
{
|
||||||
|
flags.verbose = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
{
|
||||||
|
flags.command = optarg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
{
|
||||||
|
flags.use_operators.ternary = true;
|
||||||
|
}
|
||||||
|
// fallthrough
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
{
|
||||||
|
flags.use_operators.not = true;
|
||||||
|
flags.use_operators.or = true;
|
||||||
|
flags.use_operators.and = true;
|
||||||
|
|
||||||
|
flags.use_operators.orn = true;
|
||||||
|
flags.use_operators.nor = true;
|
||||||
|
|
||||||
|
flags.use_operators.andn = true;
|
||||||
|
flags.use_operators.nand = true;
|
||||||
|
|
||||||
|
flags.use_operators. xor = true;
|
||||||
|
flags.use_operators.nxor = true;
|
||||||
|
|
||||||
|
unset_operators = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
{
|
||||||
|
unset_operators = false;
|
||||||
|
|
||||||
|
for (char* moving; (moving = strtok_r(NULL, ",", &optarg)); )
|
||||||
|
{
|
||||||
|
if (!strcmp(moving, "not") || !strcmp(moving, "!"))
|
||||||
|
{
|
||||||
|
flags.use_operators.not = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "or") || !strcmp(moving, "||"))
|
||||||
|
{
|
||||||
|
flags.use_operators.or = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "orn") || !strcmp(moving, "|!"))
|
||||||
|
{
|
||||||
|
flags.use_operators.orn = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "nor") || !strcmp(moving, "!|"))
|
||||||
|
{
|
||||||
|
flags.use_operators.nor = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "and") || !strcmp(moving, "&&"))
|
||||||
|
{
|
||||||
|
flags.use_operators.and = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "andn") || !strcmp(moving, "&!"))
|
||||||
|
{
|
||||||
|
flags.use_operators.andn = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "nand") || !strcmp(moving, "!&"))
|
||||||
|
{
|
||||||
|
flags.use_operators.nand = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "xor") || !strcmp(moving, "!="))
|
||||||
|
{
|
||||||
|
flags.use_operators.xor = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "nxor") || !strcmp(moving, "=="))
|
||||||
|
{
|
||||||
|
flags.use_operators.nxor = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "lt") || !strcmp(moving, "<"))
|
||||||
|
{
|
||||||
|
flags.use_operators.lt = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "lte") || !strcmp(moving, "<="))
|
||||||
|
{
|
||||||
|
flags.use_operators.lte = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "gt") || !strcmp(moving, ">"))
|
||||||
|
{
|
||||||
|
flags.use_operators.gt = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "gte") || !strcmp(moving, ">="))
|
||||||
|
{
|
||||||
|
flags.use_operators.gte = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "ternary") || !strcmp(moving, "?:"))
|
||||||
|
{
|
||||||
|
flags.use_operators.ternary = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "assign") || !strcmp(moving, "="))
|
||||||
|
{
|
||||||
|
flags.use_operators.assignment = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(!"TODO");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
{
|
||||||
|
unset_print_with_color = false;
|
||||||
|
|
||||||
|
if (!strcmp(optarg, "yes") || !strcmp(optarg, "on"))
|
||||||
|
{
|
||||||
|
flags.print_with_color = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(optarg, "no") || !strcmp(optarg, "off"))
|
||||||
|
{
|
||||||
|
flags.print_with_color = false;
|
||||||
|
}
|
||||||
|
else if (!strcmp(optarg, "auto"))
|
||||||
|
{
|
||||||
|
flags.print_with_color = isatty(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(!"TODO");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
{
|
||||||
|
flags.force_rebuild = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
assert(!"TODO");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unset_operators)
|
||||||
|
{
|
||||||
|
flags.use_operators.not = true;
|
||||||
|
flags.use_operators.or = true;
|
||||||
|
flags.use_operators.and = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unset_print_with_color)
|
||||||
|
{
|
||||||
|
flags.print_with_color = isatty(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
42
cmdln.h
Normal file
42
cmdln.h
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct cmdln_flags
|
||||||
|
{
|
||||||
|
const char* argv0;
|
||||||
|
|
||||||
|
const char* command;
|
||||||
|
|
||||||
|
struct use_operators {
|
||||||
|
bool not;
|
||||||
|
|
||||||
|
bool or, orn, nor;
|
||||||
|
|
||||||
|
bool and, andn, nand;
|
||||||
|
|
||||||
|
bool xor, nxor;
|
||||||
|
|
||||||
|
bool lt, lte, gt, gte;
|
||||||
|
|
||||||
|
bool ternary;
|
||||||
|
|
||||||
|
bool assignment;
|
||||||
|
} use_operators;
|
||||||
|
|
||||||
|
bool print_all_and_quit;
|
||||||
|
|
||||||
|
bool print_max_operators_needed_and_quit;
|
||||||
|
|
||||||
|
bool assume_yes;
|
||||||
|
|
||||||
|
bool verbose;
|
||||||
|
|
||||||
|
bool print_with_color;
|
||||||
|
|
||||||
|
bool force_rebuild;
|
||||||
|
|
||||||
|
bool quiet;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cmdln_flags parse_args(int argc, char* const* argv);
|
||||||
|
|
||||||
4
debug.c
Normal file
4
debug.c
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
int debug_depth = 0;
|
||||||
|
|
||||||
|
|
||||||
35
debug.h
Normal file
35
debug.h
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
#ifdef DEBUG_BUILD
|
||||||
|
extern int debug_depth;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_BUILD
|
||||||
|
#define ZDEBUG 1
|
||||||
|
#else
|
||||||
|
#define ZDEBUG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_BUILD
|
||||||
|
#define zprintf(fmt, ...) printf("%*s" fmt, debug_depth, "", ## __VA_ARGS__);
|
||||||
|
#else
|
||||||
|
#define zprintf(...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_BUILD
|
||||||
|
#define ENTER \
|
||||||
|
{ zprintf("%s():" "\n", __PRETTY_FUNCTION__); debug_depth++; }
|
||||||
|
|
||||||
|
#define EXIT \
|
||||||
|
{ zprintf("return" "\n"); debug_depth--; }
|
||||||
|
#else
|
||||||
|
#define ENTER ;
|
||||||
|
|
||||||
|
#define EXIT ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TODO \
|
||||||
|
assert(!"TODO");
|
||||||
|
|
||||||
|
#define CHECK \
|
||||||
|
assert(!"CHECK");
|
||||||
|
|
||||||
9
defines.h
Normal file
9
defines.h
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#define W 0b0101010101010101
|
||||||
|
#define X 0b0011001100110011
|
||||||
|
#define Y 0b0000111100001111
|
||||||
|
#define Z 0b0000000011111111
|
||||||
|
#define M 0b1111111111111111
|
||||||
|
|
||||||
|
#define N (65536)
|
||||||
|
|
||||||
500
evaluate.c
Normal file
500
evaluate.c
Normal file
|
|
@ -0,0 +1,500 @@
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <defines.h>
|
||||||
|
|
||||||
|
#include "evaluate.h"
|
||||||
|
|
||||||
|
uint16_t evaluate(const char* text)
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
tk_uninitialized,
|
||||||
|
|
||||||
|
tk_0,
|
||||||
|
tk_1,
|
||||||
|
|
||||||
|
tk_w,
|
||||||
|
tk_x,
|
||||||
|
tk_y,
|
||||||
|
tk_z,
|
||||||
|
|
||||||
|
tk_oparen,
|
||||||
|
tk_cparen,
|
||||||
|
|
||||||
|
tk_emark,
|
||||||
|
tk_emarkequals,
|
||||||
|
tk_emarkvbar,
|
||||||
|
tk_emarkampersand,
|
||||||
|
|
||||||
|
tk_equalsequals,
|
||||||
|
|
||||||
|
tk_vbarvbar,
|
||||||
|
tk_vbaremark,
|
||||||
|
|
||||||
|
tk_qmark,
|
||||||
|
|
||||||
|
tk_less_than,
|
||||||
|
tk_less_than_eq,
|
||||||
|
|
||||||
|
tk_greater_than,
|
||||||
|
tk_greater_than_eq,
|
||||||
|
|
||||||
|
tk_ampersandemark,
|
||||||
|
tk_ampersandampersand,
|
||||||
|
|
||||||
|
tk_colon,
|
||||||
|
|
||||||
|
tk_EOF,
|
||||||
|
} tokenkind = tk_uninitialized;
|
||||||
|
|
||||||
|
const char* moving = text;
|
||||||
|
|
||||||
|
void next_token(void)
|
||||||
|
{
|
||||||
|
while (*moving && *moving == ' ')
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
tokenkind = tk_EOF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '0':
|
||||||
|
tokenkind = tk_0, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '1':
|
||||||
|
tokenkind = tk_1, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
tokenkind = tk_w, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
tokenkind = tk_x, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'y':
|
||||||
|
tokenkind = tk_y, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'z':
|
||||||
|
tokenkind = tk_z, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '(':
|
||||||
|
tokenkind = tk_oparen, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ')':
|
||||||
|
tokenkind = tk_cparen, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
tokenkind = tk_qmark, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ':':
|
||||||
|
tokenkind = tk_colon, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// either '||' or '|!':
|
||||||
|
case '|':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '|':
|
||||||
|
tokenkind = tk_vbarvbar, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '!':
|
||||||
|
tokenkind = tk_vbaremark, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
puts("syntax error");
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// either '&&' or '&!':
|
||||||
|
case '&':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '&':
|
||||||
|
tokenkind = tk_ampersandampersand, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '!':
|
||||||
|
tokenkind = tk_ampersandemark, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
puts("syntax error");
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// either '!' or '!=' or '!&' or '!|'
|
||||||
|
case '!':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
tokenkind = tk_emarkequals, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '|':
|
||||||
|
tokenkind = tk_emarkvbar, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
tokenkind = tk_emarkampersand, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
tokenkind = tk_emark;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '<':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
tokenkind = tk_less_than_eq, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
tokenkind = tk_less_than;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '>':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
tokenkind = tk_greater_than_eq, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
tokenkind = tk_greater_than;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// could only be '==':
|
||||||
|
case '=':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
tokenkind = tk_equalsequals, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
puts("syntax error");
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(!"TODO");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
uint16_t parse_root(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_ternary(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_ors(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_ands(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_equals(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_compares(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_prefix(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_primary(void)
|
||||||
|
{
|
||||||
|
uint16_t retval;
|
||||||
|
|
||||||
|
switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_0:
|
||||||
|
retval = 0, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_1:
|
||||||
|
retval = M, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_w:
|
||||||
|
retval = W, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_x:
|
||||||
|
retval = X, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_y:
|
||||||
|
retval = Y, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_z:
|
||||||
|
retval = Z, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_oparen:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
retval = parse_root();
|
||||||
|
|
||||||
|
if (tokenkind != tk_cparen)
|
||||||
|
{
|
||||||
|
assert(!"NOPE");
|
||||||
|
}
|
||||||
|
|
||||||
|
next_token();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(!"TODO");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenkind == tk_emark)
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
return ~parse_prefix();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return parse_primary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t left = parse_prefix();
|
||||||
|
|
||||||
|
again: switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_less_than:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = (~left & parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_less_than_eq:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = (~left | parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_greater_than_eq:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ( left | ~parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_greater_than:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ( left & ~parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t left = parse_compares();
|
||||||
|
|
||||||
|
again: switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_equalsequals:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ~(left ^ parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_emarkequals:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = left ^ parse_equals();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t left = parse_equals();
|
||||||
|
|
||||||
|
again: switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_ampersandampersand:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = left & parse_equals();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_ampersandemark:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ~left & parse_equals();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_emarkampersand:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ~(left & parse_equals());
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t left = parse_ands();
|
||||||
|
|
||||||
|
again: switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_vbarvbar:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = left | parse_ands();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_vbaremark:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = (~left | parse_ands()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_emarkvbar:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ~(left | parse_ands()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t cond = parse_ors();
|
||||||
|
|
||||||
|
if (tokenkind == tk_qmark)
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
uint16_t left = parse_ors();
|
||||||
|
|
||||||
|
if (tokenkind != tk_colon)
|
||||||
|
{
|
||||||
|
puts("syntax error!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
uint16_t right = parse_ternary();
|
||||||
|
|
||||||
|
return (cond & left) | (~cond & right);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parse_ternary();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t truthtable = parse_root();
|
||||||
|
|
||||||
|
if (tokenkind != tk_EOF)
|
||||||
|
{
|
||||||
|
puts("syntax error!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return truthtable;
|
||||||
|
}
|
||||||
|
|
||||||
5
evaluate.h
Normal file
5
evaluate.h
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint16_t evaluate(const char* text);
|
||||||
|
|
||||||
62
expr.h
Normal file
62
expr.h
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
#ifndef STRUCT_EXPR
|
||||||
|
#define STRUCT_EXPR
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum ekind
|
||||||
|
{
|
||||||
|
ek_unreachable,
|
||||||
|
|
||||||
|
ek_0,
|
||||||
|
ek_1,
|
||||||
|
ek_W,
|
||||||
|
ek_X,
|
||||||
|
ek_Y,
|
||||||
|
ek_Z,
|
||||||
|
|
||||||
|
// very special:
|
||||||
|
ek_A,
|
||||||
|
|
||||||
|
ek_not,
|
||||||
|
ek_or,
|
||||||
|
ek_and,
|
||||||
|
|
||||||
|
ek_orn,
|
||||||
|
ek_nor,
|
||||||
|
|
||||||
|
ek_andn,
|
||||||
|
ek_nand,
|
||||||
|
|
||||||
|
ek_xor,
|
||||||
|
ek_nxor,
|
||||||
|
|
||||||
|
ek_lt,
|
||||||
|
ek_lte,
|
||||||
|
ek_gt,
|
||||||
|
ek_gte,
|
||||||
|
|
||||||
|
ek_ternary,
|
||||||
|
|
||||||
|
// also very special.
|
||||||
|
// 'left' is the variable's truthtable
|
||||||
|
// to print the requested truthtable
|
||||||
|
// look a the relavent lookup.
|
||||||
|
ek_assignment,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct expr
|
||||||
|
{
|
||||||
|
enum ekind kind;
|
||||||
|
|
||||||
|
uint16_t cond, left, right;
|
||||||
|
|
||||||
|
int cost;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -36,15 +36,16 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1749664469,
|
"lastModified": 1750838302,
|
||||||
"narHash": "sha256-Ar3r6cmQVKVoEy/TWAKq8WuGqZibRjMt5oZRvkn+2Bk=",
|
"narHash": "sha256-aVkL3/yu50oQzi2YuKo0ceiCypVZpZXYd2P2p1FMJM4=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "3fa008da69980bd61324ad9e3a825022f0b736f1",
|
"rev": "7284e2decc982b81a296ab35aa46e804baaa1cfe",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-25.05",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
35
flake.nix
35
flake.nix
|
|
@ -2,10 +2,10 @@
|
||||||
# vim: set sw=2 ts=2 et: #
|
# vim: set sw=2 ts=2 et: #
|
||||||
|
|
||||||
{
|
{
|
||||||
description = "An example project using flutter";
|
description = "description";
|
||||||
|
|
||||||
inputs.nixpkgs = { url = "github:NixOS/nixpkgs"; };
|
|
||||||
|
|
||||||
|
inputs.nixpkgs = { url = "github:NixOS/nixpkgs?ref=nixos-25.05"; };
|
||||||
|
|
||||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
|
||||||
inputs.flake-compat = {
|
inputs.flake-compat = {
|
||||||
|
|
@ -19,17 +19,42 @@
|
||||||
inherit system;
|
inherit system;
|
||||||
|
|
||||||
config.allowUnfree = true;
|
config.allowUnfree = true;
|
||||||
};
|
}; in {
|
||||||
in {
|
|
||||||
devShells.default =
|
devShells.default =
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
gcc
|
gcc
|
||||||
|
gcc.man
|
||||||
gnumake
|
gnumake
|
||||||
readline.dev
|
readline.dev
|
||||||
python3
|
python3
|
||||||
|
valgrind
|
||||||
|
linux-manual
|
||||||
|
man-pages
|
||||||
|
man-pages-posix
|
||||||
|
|
||||||
|
# for my sake:
|
||||||
|
gedit
|
||||||
|
libreoffice
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
231
get_cached_simplifications.c
Normal file
231
get_cached_simplifications.c
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <defines.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <cmdln.h>
|
||||||
|
|
||||||
|
#include "calculate_assignment_simplifications.h"
|
||||||
|
#include "get_cached_simplifications.h"
|
||||||
|
#include "calculate_simplifications.h"
|
||||||
|
|
||||||
|
static struct path { char data[PATH_MAX]; } get_path(
|
||||||
|
const struct cmdln_flags* flags)
|
||||||
|
{
|
||||||
|
struct path path = {};
|
||||||
|
|
||||||
|
strcat(path.data, ".simplifier-cache-64GB");
|
||||||
|
|
||||||
|
if (flags->use_operators.not)
|
||||||
|
strcat(path.data, "-not");
|
||||||
|
|
||||||
|
if (flags->use_operators.or)
|
||||||
|
strcat(path.data, "-or");
|
||||||
|
|
||||||
|
if (flags->use_operators.orn)
|
||||||
|
strcat(path.data, "-orn");
|
||||||
|
|
||||||
|
if (flags->use_operators.nor)
|
||||||
|
strcat(path.data, "-nor");
|
||||||
|
|
||||||
|
if (flags->use_operators.and)
|
||||||
|
strcat(path.data, "-and");
|
||||||
|
|
||||||
|
if (flags->use_operators.andn)
|
||||||
|
strcat(path.data, "-andn");
|
||||||
|
|
||||||
|
if (flags->use_operators.nand)
|
||||||
|
strcat(path.data, "-nand");
|
||||||
|
|
||||||
|
if (flags->use_operators.xor)
|
||||||
|
strcat(path.data, "-xor");
|
||||||
|
|
||||||
|
if (flags->use_operators.nxor)
|
||||||
|
strcat(path.data, "-nxor");
|
||||||
|
|
||||||
|
if (flags->use_operators.lt)
|
||||||
|
strcat(path.data, "-lt");
|
||||||
|
|
||||||
|
if (flags->use_operators.lte)
|
||||||
|
strcat(path.data, "-lte");
|
||||||
|
|
||||||
|
if (flags->use_operators.gt)
|
||||||
|
strcat(path.data, "-gt");
|
||||||
|
|
||||||
|
if (flags->use_operators.gte)
|
||||||
|
strcat(path.data, "-gte");
|
||||||
|
|
||||||
|
if (flags->use_operators.ternary)
|
||||||
|
strcat(path.data, "-ternary");
|
||||||
|
|
||||||
|
if (flags->use_operators.assignment)
|
||||||
|
strcat(path.data, "-assignment");
|
||||||
|
|
||||||
|
strcat(path.data, ".bin");
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct simplifications* get_cached_simplifications(const struct cmdln_flags* flags)
|
||||||
|
{
|
||||||
|
ENTER;
|
||||||
|
|
||||||
|
struct path path = get_path(flags);
|
||||||
|
|
||||||
|
bool rebuild = flags->force_rebuild;
|
||||||
|
|
||||||
|
if (!rebuild)
|
||||||
|
{
|
||||||
|
int fd = open(path.data, O_RDONLY);
|
||||||
|
|
||||||
|
if (fd > 0)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
else if (errno == ENOENT)
|
||||||
|
{
|
||||||
|
rebuild = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TODO;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rebuild)
|
||||||
|
{
|
||||||
|
#ifndef DEBUG_BUILD
|
||||||
|
if (!flags->quiet)
|
||||||
|
{
|
||||||
|
puts(""
|
||||||
|
"I'll have to build up my cache of simplifications" "\n"
|
||||||
|
"I'll only have to do this once." "\n"
|
||||||
|
"\n"
|
||||||
|
"This may take a while." "\n"
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flags->quiet && !flags->verbose)
|
||||||
|
{
|
||||||
|
puts("Re-run with '-v' to watch progress");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flags->quiet && !flags->assume_yes)
|
||||||
|
{
|
||||||
|
puts("");
|
||||||
|
puts("Any input to start:"), getchar();
|
||||||
|
puts("Started.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int fd = open(".", O_TMPFILE | O_RDWR, 0664);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
TODO;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftruncate(fd, sizeof(struct simplifications)) < 0)
|
||||||
|
{
|
||||||
|
TODO;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ptr = mmap(
|
||||||
|
/* addr: */ NULL,
|
||||||
|
/* len: */ sizeof(struct simplifications),
|
||||||
|
/* prot: */ PROT_WRITE | PROT_READ,
|
||||||
|
/* flags: */ MAP_SHARED,
|
||||||
|
/* fd: */ fd,
|
||||||
|
/* offset: */ 0);
|
||||||
|
|
||||||
|
if (ptr == MAP_FAILED)
|
||||||
|
{
|
||||||
|
TODO;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate_simplifications(flags, ptr);
|
||||||
|
|
||||||
|
// flush mmap:
|
||||||
|
if (munmap(ptr, sizeof(struct simplifications)) < 0)
|
||||||
|
{
|
||||||
|
TODO;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char buffer[PATH_MAX];
|
||||||
|
|
||||||
|
snprintf(buffer, PATH_MAX, "/proc/self/fd/%d", fd);
|
||||||
|
|
||||||
|
if (unlink(path.data) < 0 && errno != ENOENT)
|
||||||
|
{
|
||||||
|
printf("unlink(%s): %m" "\n", path.data);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkat(AT_FDCWD, buffer, AT_FDCWD, path.data, AT_SYMLINK_FOLLOW) < 0)
|
||||||
|
{
|
||||||
|
printf("linkat(%s): %m" "\n", path.data);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fd = open(path.data, O_RDONLY);
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
TODO;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ptr = mmap(
|
||||||
|
/* addr: */ NULL,
|
||||||
|
/* len: */ sizeof(struct simplifications),
|
||||||
|
/* prot: */ PROT_READ,
|
||||||
|
/* flags: */ MAP_PRIVATE,
|
||||||
|
/* fd: */ fd,
|
||||||
|
/* offset: */ 0);
|
||||||
|
|
||||||
|
if (ptr == MAP_FAILED)
|
||||||
|
{
|
||||||
|
TODO;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
EXIT;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
7
get_cached_simplifications.h
Normal file
7
get_cached_simplifications.h
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
// #include <expr.h>
|
||||||
|
|
||||||
|
struct cmdln_flags;
|
||||||
|
|
||||||
|
struct simplifications* get_cached_simplifications(const struct cmdln_flags* flags);
|
||||||
|
|
||||||
73
makefile
73
makefile
|
|
@ -1,27 +1,64 @@
|
||||||
|
|
||||||
# vim: noexpandtab tabstop=4 :
|
# vim: noexpandtab tabstop=4 :
|
||||||
|
|
||||||
|
buildtype ?= release
|
||||||
|
|
||||||
|
optionset = buildtypes/${buildtype}.txt
|
||||||
|
|
||||||
|
prefix = bin/${buildtype}
|
||||||
|
|
||||||
|
default: ${prefix}/bsimp
|
||||||
|
|
||||||
|
.PRECIOUS: %/
|
||||||
|
|
||||||
|
%/:
|
||||||
|
@mkdir -p $@
|
||||||
|
|
||||||
|
srcs += calculate_simplifications.c calculate_assignment_simplifications.c
|
||||||
|
srcs += cmdln.c evaluate.c debug.c
|
||||||
|
srcs += get_cached_simplifications.c main.c print.c
|
||||||
|
|
||||||
|
${prefix}/%.o ${prefix}/%.d: %.c ${optionset} | ${prefix}/%/
|
||||||
|
@echo "compiling (${buildtype}) ${*}.c ..."
|
||||||
|
@gcc -c @${optionset} $< -MD -MF ${prefix}/${*}.d -o ${prefix}/${*}.o
|
||||||
|
|
||||||
|
objs = $(patsubst %.c,${prefix}/%.o,${srcs})
|
||||||
|
|
||||||
|
${prefix}/bsimp: ${optionset} ${objs} | bin/
|
||||||
|
@echo "linking (${buildtype})"
|
||||||
|
@gcc @${optionset} ${objs} -o $@
|
||||||
|
|
||||||
args =
|
args =
|
||||||
|
|
||||||
cc = gcc
|
run: ${prefix}/bsimp
|
||||||
|
|
||||||
cppflags += -D _GNU_SOURCE
|
|
||||||
#cppflags += -D ZDEBUG
|
|
||||||
|
|
||||||
cflags = -Werror -Wall -Wextra -Wstrict-prototypes -Wfatal-errors
|
|
||||||
|
|
||||||
cflags += -O3
|
|
||||||
|
|
||||||
cflags += -Wno-unused
|
|
||||||
|
|
||||||
ldflags += -lreadline
|
|
||||||
|
|
||||||
/tmp/4-variable-simplifier: main.c
|
|
||||||
$(cc) $(cppflags) $(cflags) $< -o $@ $(ldflags)
|
|
||||||
|
|
||||||
run: /tmp/4-variable-simplifier
|
|
||||||
$< $(args)
|
$< $(args)
|
||||||
|
|
||||||
|
valrun: ${prefix}/bsimp
|
||||||
|
valgrind --max-stackframe=2031768 \
|
||||||
|
--exit-on-first-error=yes --error-exitcode=1 -- $< ${args}
|
||||||
|
|
||||||
|
PREFIX ?= ${HOME}
|
||||||
|
|
||||||
|
install: ${PREFIX}/bin/bsimp
|
||||||
|
|
||||||
|
${PREFIX}/bin/bsimp: bin/release/bsimp | ${PREFIX}/bin/
|
||||||
|
cp -vau $< $@
|
||||||
|
|
||||||
|
include $(patsubst %.c,${prefix}/%.d,${srcs})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# nix --extra-experimental-features nix-command --extra-experimental-features flakes develop --command 'make'
|
|
||||||
|
|
||||||
|
|
|
||||||
6
nix-make.sh
Executable file
6
nix-make.sh
Executable file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -ev
|
||||||
|
nix --extra-experimental-features nix-command \
|
||||||
|
--extra-experimental-features flakes \
|
||||||
|
develop \
|
||||||
|
--command "make" "$@"
|
||||||
241
print.c
Normal file
241
print.c
Normal file
|
|
@ -0,0 +1,241 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <cmdln.h>
|
||||||
|
|
||||||
|
#include <expr.h>
|
||||||
|
|
||||||
|
#include "simplifications.h"
|
||||||
|
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
static void helper(
|
||||||
|
const struct simplifications* simps,
|
||||||
|
const struct row* row,
|
||||||
|
uint16_t truthtable,
|
||||||
|
bool print_with_color,
|
||||||
|
int depth)
|
||||||
|
{
|
||||||
|
#define LITERAL_ESCAPE "\e[38;2;200;200;100m"
|
||||||
|
#define VARIABLE_ESCAPE "\e[38;2;100;100;200m"
|
||||||
|
#define RESET_ESCAPE "\e[0m"
|
||||||
|
|
||||||
|
static const char* const operator_colors[10] = {
|
||||||
|
"\e[38;2;204;0;0m",
|
||||||
|
"\e[38;2;204;122;0m",
|
||||||
|
"\e[38;2;163;204;0m",
|
||||||
|
"\e[38;2;40;204;0m",
|
||||||
|
"\e[38;2;0;204;81m",
|
||||||
|
"\e[38;2;0;204;204m",
|
||||||
|
"\e[38;2;0;81;204m",
|
||||||
|
"\e[38;2;40;0;204m",
|
||||||
|
"\e[38;2;163;0;204m",
|
||||||
|
"\e[38;2;204;0;122m",
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct expr* e = &row->data[truthtable];
|
||||||
|
|
||||||
|
switch (e->kind)
|
||||||
|
{
|
||||||
|
case ek_unreachable:
|
||||||
|
{
|
||||||
|
assert(!"NOPE");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ek_0:
|
||||||
|
{
|
||||||
|
printf(print_with_color ? LITERAL_ESCAPE "0" RESET_ESCAPE : "0");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ek_1:
|
||||||
|
{
|
||||||
|
printf(print_with_color ? LITERAL_ESCAPE "1" RESET_ESCAPE : "1");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ek_W:
|
||||||
|
{
|
||||||
|
printf(print_with_color ? VARIABLE_ESCAPE "w" RESET_ESCAPE : "w");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ek_X:
|
||||||
|
{
|
||||||
|
printf(print_with_color ? VARIABLE_ESCAPE "x" RESET_ESCAPE : "x");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ek_Y:
|
||||||
|
{
|
||||||
|
printf(print_with_color ? VARIABLE_ESCAPE "y" RESET_ESCAPE : "y");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ek_Z:
|
||||||
|
{
|
||||||
|
printf(print_with_color ? VARIABLE_ESCAPE "z" RESET_ESCAPE : "z");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ek_A:
|
||||||
|
{
|
||||||
|
printf(print_with_color ? VARIABLE_ESCAPE "a" RESET_ESCAPE : "a");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ek_not:
|
||||||
|
{
|
||||||
|
const char* start = print_with_color ? operator_colors[depth % 10] : "";
|
||||||
|
const char* end = print_with_color ? RESET_ESCAPE : "";
|
||||||
|
|
||||||
|
printf("%s(!%s", start, end);
|
||||||
|
|
||||||
|
helper(simps, row, e->left, print_with_color, depth + 1);
|
||||||
|
|
||||||
|
printf("%s)%s", start, end);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BINARY_OPERATOR(kind, operatorstring) \
|
||||||
|
case kind: \
|
||||||
|
{ \
|
||||||
|
const char *start = "", *end = ""; \
|
||||||
|
\
|
||||||
|
if (print_with_color) \
|
||||||
|
{ \
|
||||||
|
start = operator_colors[depth % 10]; \
|
||||||
|
\
|
||||||
|
end = RESET_ESCAPE; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
printf("%s(%s", start, end); \
|
||||||
|
\
|
||||||
|
helper(simps, row, e->left, print_with_color, depth + 1); \
|
||||||
|
\
|
||||||
|
printf("%s%s%s", start, operatorstring, end); \
|
||||||
|
\
|
||||||
|
helper(simps, row, e->right, print_with_color, depth + 1); \
|
||||||
|
\
|
||||||
|
printf("%s)%s", start, end); \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
BINARY_OPERATOR(ek_or, " || ");
|
||||||
|
BINARY_OPERATOR(ek_orn, " |! ");
|
||||||
|
BINARY_OPERATOR(ek_nor, " !| ");
|
||||||
|
|
||||||
|
BINARY_OPERATOR(ek_and, " && ");
|
||||||
|
BINARY_OPERATOR(ek_andn, " &! ");
|
||||||
|
BINARY_OPERATOR(ek_nand, " !& ");
|
||||||
|
|
||||||
|
BINARY_OPERATOR(ek_xor, " != ");
|
||||||
|
BINARY_OPERATOR(ek_nxor, " == ");
|
||||||
|
|
||||||
|
BINARY_OPERATOR(ek_lt, " < ");
|
||||||
|
BINARY_OPERATOR(ek_lte, " <= ");
|
||||||
|
BINARY_OPERATOR(ek_gt, " > ");
|
||||||
|
BINARY_OPERATOR(ek_gte, " >= ");
|
||||||
|
|
||||||
|
#undef BINARY_OPERATOR
|
||||||
|
|
||||||
|
case ek_ternary:
|
||||||
|
{
|
||||||
|
const char *start = "", *end = "";
|
||||||
|
|
||||||
|
if (print_with_color)
|
||||||
|
{
|
||||||
|
start = operator_colors[depth % 10];
|
||||||
|
|
||||||
|
end = RESET_ESCAPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s(%s", start, end);
|
||||||
|
helper(simps, row, e->cond, print_with_color, depth + 1);
|
||||||
|
printf(" %s?%s ", start, end);
|
||||||
|
helper(simps, row, e->left, print_with_color, depth + 1);
|
||||||
|
printf(" %s:%s ", start, end);
|
||||||
|
helper(simps, row, e->right, print_with_color, depth + 1);
|
||||||
|
printf("%s)%s", start, end);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ek_assignment:
|
||||||
|
{
|
||||||
|
assert(row == &simps->main);
|
||||||
|
|
||||||
|
const char *start = "", *end = "";
|
||||||
|
|
||||||
|
if (print_with_color)
|
||||||
|
{
|
||||||
|
start = operator_colors[depth % 10];
|
||||||
|
|
||||||
|
end = RESET_ESCAPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s(%s", start, end);
|
||||||
|
|
||||||
|
printf("%s", print_with_color ? VARIABLE_ESCAPE "a" RESET_ESCAPE : "a");
|
||||||
|
|
||||||
|
printf(" ");
|
||||||
|
|
||||||
|
printf("%s=%s", start, end);
|
||||||
|
|
||||||
|
printf(" ");
|
||||||
|
|
||||||
|
helper(simps, row, e->left, print_with_color, depth + 1);
|
||||||
|
|
||||||
|
printf("%s, %s", start, end);
|
||||||
|
|
||||||
|
helper(simps, &simps->with_vars[e->left], e->right,
|
||||||
|
print_with_color, depth + 1);
|
||||||
|
|
||||||
|
printf("%s)%s", start, end);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
const struct simplifications* simps,
|
||||||
|
const struct row* row,
|
||||||
|
uint16_t truthtable)
|
||||||
|
{
|
||||||
|
helper(simps, row, truthtable, flags->print_with_color, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
18
print.h
Normal file
18
print.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <defines.h>
|
||||||
|
|
||||||
|
#include <expr.h>
|
||||||
|
|
||||||
|
struct cmdln_flags;
|
||||||
|
struct simplifications;
|
||||||
|
struct row;
|
||||||
|
|
||||||
|
void print(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
const struct simplifications* simps,
|
||||||
|
const struct row* row,
|
||||||
|
uint16_t truthtable);
|
||||||
|
|
||||||
|
|
||||||
17
simplifications.h
Normal file
17
simplifications.h
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
#ifndef STRUCT_SIMPLIFICATIONS
|
||||||
|
#define STRUCT_SIMPLIFICATIONS
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
#include "expr.h"
|
||||||
|
|
||||||
|
struct simplifications
|
||||||
|
{
|
||||||
|
struct row {
|
||||||
|
struct expr data[N];
|
||||||
|
} main, with_vars[N];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
1986
spikes/5.c
Normal file
1986
spikes/5.c
Normal file
File diff suppressed because it is too large
Load diff
199
spikes/assignment.py
Executable file
199
spikes/assignment.py
Executable file
|
|
@ -0,0 +1,199 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from heapq import heappush, heappop
|
||||||
|
|
||||||
|
X = 0b01010101
|
||||||
|
Y = 0b00110011
|
||||||
|
Z = 0b00001111
|
||||||
|
M = 0b11111111
|
||||||
|
|
||||||
|
B = 1 << 3
|
||||||
|
N = 1 << B
|
||||||
|
|
||||||
|
def calc_simps(A = None):
|
||||||
|
# truthtable -> ('var', name)
|
||||||
|
# truthtable -> ('not', inner truthtable)
|
||||||
|
# truthtable -> (binary op, left truthtable, right truthtable)
|
||||||
|
lookup = dict();
|
||||||
|
|
||||||
|
# truthtable -> cost
|
||||||
|
costs = dict();
|
||||||
|
|
||||||
|
todo = set();
|
||||||
|
|
||||||
|
def initial(exp, truthtable):
|
||||||
|
lookup[truthtable] = exp;
|
||||||
|
costs[truthtable] = 0;
|
||||||
|
todo.add(truthtable);
|
||||||
|
|
||||||
|
initial(('var', 'x'), X);
|
||||||
|
initial(('var', 'y'), Y);
|
||||||
|
initial(('var', 'z'), Z);
|
||||||
|
initial(('lit', '0'), 0);
|
||||||
|
initial(('lit', '1'), M);
|
||||||
|
|
||||||
|
if (A is not None):
|
||||||
|
initial(('var', 'a'), A);
|
||||||
|
|
||||||
|
done = list();
|
||||||
|
|
||||||
|
for iteration in range(1, N + 1):
|
||||||
|
mytruthtable = min(todo, key = lambda x: (costs[x], x));
|
||||||
|
|
||||||
|
mycost = costs[mytruthtable];
|
||||||
|
|
||||||
|
todo.remove(mytruthtable);
|
||||||
|
|
||||||
|
# consider NOT:
|
||||||
|
not_cost = mycost + 1
|
||||||
|
not_truthtable = ~mytruthtable & M;
|
||||||
|
if (not_truthtable not in costs) or (not_cost < costs[not_truthtable]):
|
||||||
|
todo.add(not_truthtable);
|
||||||
|
|
||||||
|
lookup[not_truthtable] = ("not", mytruthtable);
|
||||||
|
|
||||||
|
costs[not_truthtable] = not_cost;
|
||||||
|
|
||||||
|
# consider OR:
|
||||||
|
for othertruthtable in done:
|
||||||
|
or_cost = 1 + mycost + costs[othertruthtable];
|
||||||
|
|
||||||
|
or_truthtable = mytruthtable | othertruthtable;
|
||||||
|
|
||||||
|
if (or_truthtable not in costs) or (or_cost < costs[or_truthtable]):
|
||||||
|
todo.add(or_truthtable);
|
||||||
|
|
||||||
|
lookup[or_truthtable] = ("or", mytruthtable, othertruthtable);
|
||||||
|
|
||||||
|
costs[or_truthtable] = or_cost;
|
||||||
|
|
||||||
|
# consider AND:
|
||||||
|
for othertruthtable in done:
|
||||||
|
and_cost = 1 + mycost + costs[othertruthtable];
|
||||||
|
|
||||||
|
and_truthtable = mytruthtable & othertruthtable;
|
||||||
|
|
||||||
|
if (and_truthtable not in costs) or (and_cost < costs[and_truthtable]):
|
||||||
|
todo.add(and_truthtable);
|
||||||
|
|
||||||
|
lookup[and_truthtable] = ("and", mytruthtable, othertruthtable);
|
||||||
|
|
||||||
|
costs[and_truthtable] = and_cost;
|
||||||
|
|
||||||
|
# consider XOR:
|
||||||
|
if 0:
|
||||||
|
for othertruthtable in done:
|
||||||
|
xor_cost = 1 + mycost + costs[othertruthtable];
|
||||||
|
|
||||||
|
xor_truthtable = mytruthtable ^ othertruthtable;
|
||||||
|
|
||||||
|
if (xor_truthtable not in costs) or (xor_cost < costs[xor_truthtable]):
|
||||||
|
todo.add(xor_truthtable);
|
||||||
|
|
||||||
|
lookup[xor_truthtable] = ("xor", mytruthtable, othertruthtable);
|
||||||
|
|
||||||
|
costs[xor_truthtable] = xor_cost;
|
||||||
|
|
||||||
|
done.append(mytruthtable);
|
||||||
|
|
||||||
|
assert(sorted(done) == sorted(costs));
|
||||||
|
|
||||||
|
return costs, lookup;
|
||||||
|
|
||||||
|
def etostr(lookup, expr):
|
||||||
|
match expr:
|
||||||
|
case ('lit', x):
|
||||||
|
return x;
|
||||||
|
case ('var', x):
|
||||||
|
return x;
|
||||||
|
case ('not', inner):
|
||||||
|
return "(!" + tostr(lookup, inner) + ")";
|
||||||
|
case ('or', left, right):
|
||||||
|
return "(" + tostr(lookup, left) + " || " + tostr(lookup, right) + ")";
|
||||||
|
case ('and', left, right):
|
||||||
|
return "(" + tostr(lookup, left) + " && " + tostr(lookup, right) + ")";
|
||||||
|
case ('xor', left, right):
|
||||||
|
return "(" + tostr(lookup, left) + " != " + tostr(lookup, right) + ")";
|
||||||
|
case _:
|
||||||
|
assert(not "TODO");
|
||||||
|
|
||||||
|
def tostr(lookup, truthtable):
|
||||||
|
return etostr(lookup, lookup[truthtable]);
|
||||||
|
|
||||||
|
zdcosts, zdlookup = calc_simps();
|
||||||
|
|
||||||
|
# now that we've figured out the zero-depth trees, we need to figure out which
|
||||||
|
# trees could be done faster with a variable. We need to go through every
|
||||||
|
# possible truthtable, considering them the new variable, building up a new
|
||||||
|
# table of what expressions are the cheapiest with that variable.
|
||||||
|
# Then, if that figured out for all of them, we could read down the columns
|
||||||
|
# figuring out the best answers for anything the user gives.
|
||||||
|
|
||||||
|
# truthtable -> cost
|
||||||
|
costs = zdcosts;
|
||||||
|
|
||||||
|
# truthtable -> variable truthtable
|
||||||
|
varlookup = {x: None for x in range(1 << B)};
|
||||||
|
|
||||||
|
all_costs = dict(); # variable truthtable -> truthtable -> cost
|
||||||
|
all_lookups = dict(); # variable truthtable -> truthtable -> expr
|
||||||
|
|
||||||
|
for A in range(0, 1 << B):
|
||||||
|
print(f"what if the variable was 0b{A:08b}?");
|
||||||
|
|
||||||
|
var_costs, var_lookup = calc_simps(A);
|
||||||
|
|
||||||
|
for t in range(0, 1 << B):
|
||||||
|
mycost = var_costs[t] + 1 + zdcosts[A];
|
||||||
|
|
||||||
|
if mycost < costs[t]:
|
||||||
|
varlookup[t] = A;
|
||||||
|
|
||||||
|
costs[t] = mycost;
|
||||||
|
|
||||||
|
all_costs[A] = var_costs;
|
||||||
|
|
||||||
|
all_lookups[A] = var_lookup;
|
||||||
|
|
||||||
|
for t in range(0, 1 << B):
|
||||||
|
line = f"0b{t:08b}: ";
|
||||||
|
|
||||||
|
line += f"[{costs[t]}] ";
|
||||||
|
|
||||||
|
if varlookup[t] is None:
|
||||||
|
line += tostr(zdlookup, t);
|
||||||
|
else:
|
||||||
|
line += "("
|
||||||
|
|
||||||
|
a = varlookup[t];
|
||||||
|
|
||||||
|
line += "a = " + tostr(zdlookup, a);
|
||||||
|
|
||||||
|
line += ", "
|
||||||
|
|
||||||
|
line += tostr(all_lookups[a], t);
|
||||||
|
|
||||||
|
line += ")"
|
||||||
|
|
||||||
|
line += " [before: " + tostr(zdlookup, t) + "]";
|
||||||
|
|
||||||
|
print(line);
|
||||||
|
|
||||||
|
print();
|
||||||
|
print(f"we can do anything in {max(costs.values())} operations");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
148
spikes/boolean-array-or-2.c
Normal file
148
spikes/boolean-array-or-2.c
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef ZDEBUG
|
||||||
|
#define zprintf(fmt, ...) printf(fmt, ## __VA_ARGS__);
|
||||||
|
#else
|
||||||
|
#define zprintf(...) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define N (256)
|
||||||
|
|
||||||
|
#define M (255)
|
||||||
|
|
||||||
|
struct boolist
|
||||||
|
{
|
||||||
|
int data[8][256];
|
||||||
|
};
|
||||||
|
|
||||||
|
void init(struct boolist* this)
|
||||||
|
{
|
||||||
|
memset(this, 0, sizeof(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(struct boolist* this, int e)
|
||||||
|
{
|
||||||
|
zprintf("insert(e = %i);\n", e);
|
||||||
|
|
||||||
|
if (!this->data[0][e])
|
||||||
|
{
|
||||||
|
for (int k = 0; k < 8 && !this->data[k][e >> k]++; k++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void search(
|
||||||
|
struct boolist* alist,
|
||||||
|
struct boolist* blist,
|
||||||
|
int k,
|
||||||
|
int ai, int bi,
|
||||||
|
int findme,
|
||||||
|
int calldepth)
|
||||||
|
{
|
||||||
|
zprintf("%*s" "search(k = %i, ai = %#b, bi = %#b, findme = %#b):" "\n", calldepth++, "", k, ai, bi, findme);
|
||||||
|
|
||||||
|
if (k >= 0)
|
||||||
|
{
|
||||||
|
// x | y | z
|
||||||
|
//-----------
|
||||||
|
// 0 | 0 | 0
|
||||||
|
// 0 | 1 | 1
|
||||||
|
// 1 | 0 | 1
|
||||||
|
// 1 | 1 | 1
|
||||||
|
|
||||||
|
if (findme & (1 << k))
|
||||||
|
{
|
||||||
|
// there are three cases that would make 'z' one:
|
||||||
|
zprintf("%*s" "one case" "\n", calldepth, "");
|
||||||
|
|
||||||
|
// x is 0 and y is 1:
|
||||||
|
if (alist->data[k][(ai >> k) + 0] && blist->data[k][(bi >> k) + 1])
|
||||||
|
{
|
||||||
|
search(alist, blist, k - 1, ai, bi + (1 << k), findme, calldepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// x is 1 and y is 0:
|
||||||
|
if (alist->data[k][(ai >> k) + 1] && blist->data[k][(bi >> k) + 0])
|
||||||
|
{
|
||||||
|
search(alist, blist, k - 1, ai + (1 << k), bi, findme, calldepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// x is 1 and y is 1:
|
||||||
|
if (alist->data[k][(ai >> k) + 1] && blist->data[k][(bi >> k) + 1])
|
||||||
|
{
|
||||||
|
search(alist, blist, k - 1, ai + (1 << k), bi + (1 << k), findme, calldepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zprintf("%*s" "zero case" "\n", calldepth, "");
|
||||||
|
|
||||||
|
// there's only one case when 'z' is zero: 'x' and 'y' both
|
||||||
|
// must be zero.
|
||||||
|
|
||||||
|
// check that both corrasponding quadrants are not empty first.
|
||||||
|
if (alist->data[k][(ai >> k) + 0] && blist->data[k][(bi >> k) + 0])
|
||||||
|
{
|
||||||
|
search(alist, blist, k - 1, ai, bi, findme, calldepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert((ai | bi) == findme);
|
||||||
|
|
||||||
|
printf("%2i (0b%05b) | %2i (0b%05b) == %2i (0b%05b)" "\n",
|
||||||
|
ai, ai, bi, bi, findme, findme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 main()
|
||||||
|
{
|
||||||
|
struct boolist alist, blist;
|
||||||
|
|
||||||
|
init(&alist), init(&blist);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
add(&alist, a[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
add(&blist, b[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
search(&alist, &blist, 7, 0, 0, 23, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
189
spikes/boolean-array-reverse-or.c
Normal file
189
spikes/boolean-array-reverse-or.c
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef ZDEBUG
|
||||||
|
#define zprintf(fmt, ...) printf(fmt, ## __VA_ARGS__);
|
||||||
|
#else
|
||||||
|
#define zprintf(...) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TODO \
|
||||||
|
assert(!"TODO");
|
||||||
|
|
||||||
|
#define N (256)
|
||||||
|
|
||||||
|
#define M (255)
|
||||||
|
|
||||||
|
struct boolist
|
||||||
|
{
|
||||||
|
int data[8][256];
|
||||||
|
};
|
||||||
|
|
||||||
|
void init(struct boolist* this)
|
||||||
|
{
|
||||||
|
memset(this, 0, sizeof(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(struct boolist* this, int e)
|
||||||
|
{
|
||||||
|
zprintf("insert(e = %i);\n", e);
|
||||||
|
|
||||||
|
if (!this->data[0][e])
|
||||||
|
{
|
||||||
|
for (int k = 0; k < 8 && !this->data[k][e >> k]++; k++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void search(
|
||||||
|
int a,
|
||||||
|
struct boolist* blist,
|
||||||
|
struct boolist* clist,
|
||||||
|
int k,
|
||||||
|
int bi, int ci,
|
||||||
|
int calldepth)
|
||||||
|
{
|
||||||
|
zprintf("%*s" "search(k = %i, bi = %#b, ci = %#b):" "\n",
|
||||||
|
calldepth++, "", k, bi, ci);
|
||||||
|
|
||||||
|
if (k >= 0)
|
||||||
|
{
|
||||||
|
// a | b | c
|
||||||
|
//-----------
|
||||||
|
// 0 | 0 | 0
|
||||||
|
// 0 | 1 | 1
|
||||||
|
// 1 | 0 | 1
|
||||||
|
// 1 | 1 | 1
|
||||||
|
|
||||||
|
if (a & (1 << k))
|
||||||
|
{
|
||||||
|
// there are three cases that would make 'z' one:
|
||||||
|
zprintf("%*s" "one case" "\n", calldepth, "");
|
||||||
|
|
||||||
|
// if the left operand is providing the one-ness, then the right
|
||||||
|
// operand can be whatever it wants, and the resultant must be one
|
||||||
|
|
||||||
|
// b == 0 and c == 1
|
||||||
|
if (blist->data[k][(bi >> k) + 0] && clist->data[k][(ci >> k) + 1])
|
||||||
|
{
|
||||||
|
search(a, blist, clist, k - 1, bi, ci + (1 << k), calldepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// b == 1 and c == 1
|
||||||
|
if (blist->data[k][(bi >> k) + 1] && clist->data[k][(ci >> k) + 1])
|
||||||
|
{
|
||||||
|
search(a, blist, clist, k - 1, bi + (1 << k), ci + (1 << k), calldepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zprintf("%*s" "zero case" "\n", calldepth, "");
|
||||||
|
|
||||||
|
// there two cases to consider then. If the left operand
|
||||||
|
// is not providing the one-ness, then it's up to the right operand
|
||||||
|
// to provide it if it's needed.
|
||||||
|
|
||||||
|
// b == 0 and c == 0
|
||||||
|
if (blist->data[k][(bi >> k) + 0] && clist->data[k][(ci >> k) + 0])
|
||||||
|
{
|
||||||
|
search(a, blist, clist, k - 1, bi, ci, calldepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// b == 1 and c == 1
|
||||||
|
if (blist->data[k][(bi >> k) + 1] && clist->data[k][(ci >> k) + 1])
|
||||||
|
{
|
||||||
|
search(a, blist, clist, k - 1, bi + (1 << k), ci + (1 << k), calldepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("%2i (0b%05b) | %2i (0b%05b) == %2i (0b%05b)" "\n",
|
||||||
|
a, a, bi, bi, ci, ci);
|
||||||
|
|
||||||
|
assert((a | bi) == ci);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 main()
|
||||||
|
{
|
||||||
|
struct boolist blist, clist;
|
||||||
|
|
||||||
|
init(&blist), init(&clist);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
add(&blist, b[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
add(&clist, c[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
search(a, &blist, &clist, 7, 0, 0, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
97
spikes/boolean-array.c
Normal file
97
spikes/boolean-array.c
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define N (256)
|
||||||
|
|
||||||
|
#define M (255)
|
||||||
|
|
||||||
|
struct boolist {
|
||||||
|
int data[8][256];
|
||||||
|
} list = {};
|
||||||
|
|
||||||
|
void add(int e)
|
||||||
|
{
|
||||||
|
printf("insert(e = %i);\n", e);
|
||||||
|
|
||||||
|
assert(!list.data[0][e]);
|
||||||
|
|
||||||
|
for (int k = 0; k < 8 && !list.data[k][e >> k]++; k++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void discard(int e)
|
||||||
|
{
|
||||||
|
printf("discard(e = %i);\n", e);
|
||||||
|
|
||||||
|
assert(list.data[0][e]);
|
||||||
|
|
||||||
|
for (int k = 0; k < 8 && !--list.data[k][e >> k]; k++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print()
|
||||||
|
{
|
||||||
|
puts("print():");
|
||||||
|
|
||||||
|
void walk(int k, int i)
|
||||||
|
{
|
||||||
|
if (k >= 0)
|
||||||
|
{
|
||||||
|
int* a = &list.data[k][i >> k];
|
||||||
|
|
||||||
|
if (a[0]) walk(k - 1, i);
|
||||||
|
|
||||||
|
if (a[1]) walk(k - 1, i + (1 << k));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" " "%i\n", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
walk(7, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
print();
|
||||||
|
|
||||||
|
add(42);
|
||||||
|
|
||||||
|
print();
|
||||||
|
|
||||||
|
add(101);
|
||||||
|
|
||||||
|
print();
|
||||||
|
|
||||||
|
discard(42);
|
||||||
|
|
||||||
|
print();
|
||||||
|
|
||||||
|
add(34);
|
||||||
|
|
||||||
|
print();
|
||||||
|
|
||||||
|
add(35);
|
||||||
|
|
||||||
|
print();
|
||||||
|
|
||||||
|
add(36);
|
||||||
|
|
||||||
|
print();
|
||||||
|
|
||||||
|
discard(35);
|
||||||
|
|
||||||
|
print();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
100
spikes/kattis-add-find-all.c
Normal file
100
spikes/kattis-add-find-all.c
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
94
spikes/kattis-add.c
Normal file
94
spikes/kattis-add.c
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
85
spikes/kattis-subtract.c
Normal file
85
spikes/kattis-subtract.c
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
172
spikes/linear-add.c
Normal file
172
spikes/linear-add.c
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -369,7 +369,7 @@ def calculate_simplifications(args, available_operators):
|
||||||
|
|
||||||
return costs, lookup
|
return costs, lookup
|
||||||
|
|
||||||
pathname = "simplifications.bin"
|
pathname = ".simplifications.bin"
|
||||||
|
|
||||||
def get_simplifications(args, available_operators):
|
def get_simplifications(args, available_operators):
|
||||||
available_operators = tuple(sorted(available_operators));
|
available_operators = tuple(sorted(available_operators));
|
||||||
37
spikes/quadrant-or-1.c
Normal file
37
spikes/quadrant-or-1.c
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
220
spikes/quadrant-or-2.c
Normal file
220
spikes/quadrant-or-2.c
Normal file
|
|
@ -0,0 +1,220 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
341
spikes/quadrant-reverse-or-with-lists.c
Normal file
341
spikes/quadrant-reverse-or-with-lists.c
Normal file
|
|
@ -0,0 +1,341 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
271
spikes/quadrant-reverse-or.c
Normal file
271
spikes/quadrant-reverse-or.c
Normal file
|
|
@ -0,0 +1,271 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
242
spikes/sorted-sparse-list-insert.c
Normal file
242
spikes/sorted-sparse-list-insert.c
Normal file
|
|
@ -0,0 +1,242 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
5
spikes/sorted-sparse-list-remove.c
Normal file
5
spikes/sorted-sparse-list-remove.c
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
// we need to implement this one
|
||||||
|
|
||||||
|
// should be fairly easy
|
||||||
|
|
||||||
Loading…
Reference in a new issue