summaryrefslogtreecommitdiff
path: root/truth_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'truth_table.c')
-rw-r--r--truth_table.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/truth_table.c b/truth_table.c
new file mode 100644
index 0000000..9ae9463
--- /dev/null
+++ b/truth_table.c
@@ -0,0 +1,77 @@
+#include "truth_table.h"
+
+int intpow(int b, int e) {
+ int acc = 1;
+ for (int i = 0; i < e; i++) {
+ acc *= b;
+ }
+ return acc;
+}
+
+struct expr_input_iter expr_input_iter_init(struct truth_table *tt) {
+ return (struct expr_input_iter){
+ .src = tt,
+ .acc = 0,
+ .count = 0,
+ };
+}
+
+int32_t expr_input_iter_next(struct expr_input_iter *self) {
+ uint32_t bak = self->acc;
+ if (self->count > self->src->lines_count-1) return -1;
+ for (int i = self->src->letters_count - 1; i >= 0; i--) {
+ uint8_t idx = self->src->letters[i] - 'a';
+ self->acc ^= 1 << idx;
+ if (self->acc & (1 << idx)) break;
+ }
+ self->count++;
+ return bak;
+}
+
+struct truth_table *truth_table_create(node *root, uint32_t letters_bitfield) {
+ struct truth_table *tt = calloc(1, sizeof(struct truth_table));
+ char letters[27] = {0};
+ char letters_needle = 0;
+ for (char i = 0; i <= ('z'-'a'); i++) {
+ if (letters_bitfield & (1 << i)) {
+ letters[letters_needle] = 'a'+i;
+ letters_needle++;
+ }
+ }
+ tt->letters = malloc(letters_needle * sizeof(char));
+ strncpy(tt->letters, letters, letters_needle);
+ tt->letters_count = letters_needle;
+ tt->lines_count = intpow(2,tt->letters_count);
+ tt->lines = malloc(tt->lines_count * sizeof(uint32_t));
+
+ struct expr_input_iter inp_iter = expr_input_iter_init(tt);
+ for (int i = 0; i < tt->lines_count; i++) {
+ int32_t input = expr_input_iter_next(&inp_iter);
+ uint8_t output = eval_tree(root, input);
+ tt->lines[i] = input | (output << 26);
+ }
+
+ return tt;
+}
+
+void truth_table_destroy(struct truth_table *tt) {
+ free(tt->lines);
+ free(tt->letters);
+ free(tt);
+}
+
+void truth_table_fprint(FILE *stream, struct truth_table *tt) {
+ fprintf(stream, "\t%s | S\n\t", tt->letters);
+ for (int i = 0; i < (tt->letters_count + 4); i++) putc('-', stream);
+ putc('\n', stream);
+ for (int i = 0; i < tt->lines_count; i++) {
+ putc('\t', stream);
+ uint32_t line = tt->lines[i];
+ for (int j = 0; j < tt->letters_count; j++) {
+ int actual_idx = tt->letters[j] - 'a';
+ putc((line & (1 << actual_idx))? '1' : '0', stream);
+ }
+ fprintf(stream, " | %c\n", (line & (1 << 26))? '1' : '0');
+ }
+}
+