diff --git a/2021/RESULTS.txt b/2021/RESULTS.txt index db91c1c..63fdce3 100644 --- a/2021/RESULTS.txt +++ b/2021/RESULTS.txt @@ -217,3 +217,15 @@ aoc-c : res=2850 aoc-c : res=1117 time: 0:00.00 real, 0.00 user, 0.00 sys context-switch: 1+1, page-faults: 0+95 + +========================================= +================= day18 ================= +========================================= + +aoc-c : res=3987 + time: 0:00.00 real, 0.00 user, 0.00 sys + context-switch: 0+1, page-faults: 0+98 + +aoc-c : res=4500 + time: 0:00.04 real, 0.03 user, 0.00 sys + context-switch: 1+1, page-faults: 0+97 diff --git a/2021/day18/Makefile b/2021/day18/Makefile index 9015b96..b036de5 100644 --- a/2021/day18/Makefile +++ b/2021/day18/Makefile @@ -25,7 +25,7 @@ LDLIB := -l$(LIB) export LD_LIBRARY_PATH = $(LIBDIR) CFLAGS += -std=gnu99 -#CFLAGS += -O2 +CFLAGS += -O2 CFLAGS += -g #CFLAGS += -pg CFLAGS += -Wall diff --git a/2021/day18/aoc-c.c b/2021/day18/aoc-c.c index 6e562df..e214330 100644 --- a/2021/day18/aoc-c.c +++ b/2021/day18/aoc-c.c @@ -19,12 +19,8 @@ #include "bits.h" #include "list.h" -#define POISON_VALUE -232323 -#define POISON_DEPTH 121212; - -#define PARENT 0 -#define LEFT 1 -#define RIGHT 2 +#define LEFT 0 +#define RIGHT 1 static pool_t *pool_nodes; @@ -34,12 +30,11 @@ static int nlines; typedef struct node { s64 val; - struct node *tree[3]; /* parent, left, right */ + struct node *tree[2]; /* left & right */ struct list_head leaf_list; /* head is tree root */ - u32 depth; } node_t; - +#ifdef DEBUG /* print leaves list */ static void leaves_print(node_t *root) @@ -54,117 +49,93 @@ static void leaves_print(node_t *root) /* print node tree */ -static void node_print(node_t *node) +static void node_print(node_t *node, int depth) { - if (!node->depth) + if (!depth) log_f(1, ""); if (!node->tree[LEFT]) { /* leaf */ log(1, "%ld", node->val); } else { log(1, "["); - node_print(node->tree[LEFT]); + node_print(node->tree[LEFT], depth + 1); log(1, ","); - node_print(node->tree[RIGHT]); + node_print(node->tree[RIGHT], depth + 1); log(1, "]"); } - if (!node->depth) { + if (!depth) { log(1, "\n"); leaves_print(node); } } +#endif static inline node_t *node_get() { node_t *node = pool_get(pool_nodes); - node->depth = POISON_DEPTH; - node->val = POISON_VALUE; node->tree[LEFT] = NULL; node->tree[RIGHT] = NULL; - node->tree[PARENT] = NULL; - INIT_LIST_HEAD(&node->leaf_list); return node; } +static inline void node_free(node_t *node) +{ + if (node->tree[LEFT]) { + node_free(node->tree[LEFT]); + node_free(node->tree[RIGHT]); + } + pool_add(pool_nodes, node); +} + /* split_node - split first node with value >= 10 * return: 1: finished */ static int node_split(node_t *node) { - int depth = node->depth; - static node_t *root; - - if (depth == 0) - root = node; - //if (node->depth == 0) - log_f(2, "entering node %p: val=%d left=%p right=%p\n", node, node->val, - node->tree[LEFT], node->tree[RIGHT]); - if (node->tree[LEFT]) { if (node_split(node->tree[LEFT]) || node_split(node->tree[RIGHT])) return 1; } else { if (node->val >= 10) { /* eligible leaf */ - //node_t *leaf_left = list_prev_entry(node, leaf_list); node_t *left, *right; - log_i(2, "splitting [%ld,%ld]\n", node->val); - /* create and populate new nodes */ left = node_get(); - left->depth = node->depth + 1; left->val = node->val / 2; right = node_get(); - right->depth = node->depth + 1; right->val = (node->val + 1) / 2; node->tree[LEFT] = left; node->tree[RIGHT] = right; - node->val = POISON_VALUE; /* add new nodes in leaves list, remove current one */ list_add(&node->tree[RIGHT]->leaf_list, &node->leaf_list); list_add(&node->tree[LEFT]->leaf_list, &node->leaf_list); list_del(&node->leaf_list); - log_i(2, "after split: \n\t"); - node_print(root); return 1; } } - if (node->depth == 0) { - log_f(2, "return:\n\t"); - node_print(node); - } return 0; } /* explode node - explode first node with level == 4 * return: 1: finished */ -static int node_explode(node_t *node) +static int node_explode(node_t *node, int depth) { - int depth = node->depth; static node_t *root; - if (depth == 0) { + if (depth == 0) root = node; - log_f(2, "entering node %p: val=%d left=%p right=%p\n", node, node->val, - node->tree[LEFT], node->tree[RIGHT]); - } if (depth == 4) { node_t *left = node->tree[LEFT], *right = node->tree[RIGHT]; - //struct list_head *tmp; /* skip leaves */ if (!left) return 0; - log_i(2, "exploding [%ld,%ld]\n", left->val, right->val); - //log_i(2, "zobu: "); - //node_print(root); - /* increment left leaf */ if (!list_is_first(&left->leaf_list, &root->leaf_list)) { node_t *tmpnode = list_prev_entry(left, leaf_list); @@ -176,43 +147,23 @@ static int node_explode(node_t *node) tmpnode->val += right->val; } - //log_i(2, "zobi: "); - //node_print(root); - /* remove leaves from list, and add current one */ - //tmp = list_entry(left, node_t, leaf_list); node->val = 0; list_add(&node->leaf_list, &left->leaf_list); - //log_i(2, "zoba: n=%p l=%p) ", &node->leaf_list, &left->leaf_list); - //node_print(root); - - //list_del(&left->leaf_list); - //list_del(left->leaf_list.prev); - - //list_del(&node->leaf_list->prev); - //tmp = list_prev_entry(node, leaf_list); - //log_i(2, "zoby: n=%p l=%p) ", &node->leaf_list, &left->leaf_list); list_del(&left->leaf_list); - //node->leaf_list.prev; - //log_i(2, "zobe: "); - //node_print(root); pool_add(pool_nodes, left); - list_del(&right->leaf_list); - //log_i(2, "zobo: "); - //node_print(root); pool_add(pool_nodes, right); /* remove childs links */ node->tree[LEFT] = NULL; node->tree[RIGHT] = NULL; - //log_i(2, "after reduce: "); - //node_print(root); return 1; } else { if (node->tree[LEFT]) { - if (node_explode(node->tree[LEFT]) || node_explode(node->tree[RIGHT])) + if (node_explode(node->tree[LEFT], depth + 1) || + node_explode(node->tree[RIGHT], depth + 1)) return 1; } } @@ -221,14 +172,8 @@ static int node_explode(node_t *node) static node_t *node_reduce(node_t *node) { - //log_f(2, ""); - //node_explode(node); - //node_explode(node); - //return node; while (1) { - log_f(2, "\t"); - node_print(node); - if (node_explode(node)) + if (node_explode(node, 0)) continue; if (node_split(node)) continue; @@ -237,101 +182,57 @@ static node_t *node_reduce(node_t *node) return node; } -/* promote/demode node - */ -static node_t *node_promote(node_t *node, int promote) -{ - node->depth += promote; - if (node->tree[LEFT]) { - node_promote(node->tree[LEFT], promote); - node_promote(node->tree[RIGHT], promote); - } - return node; -} - /* add 2 nodes */ static node_t *node_add(node_t *n1, node_t *n2) { node_t *head = pool_get(pool_nodes); - log_f(2, "\n"); - node_print(n1); - node_print(n2); - head->depth = 0; INIT_LIST_HEAD(&head->leaf_list); /* create new tree from the two */ - head->tree[LEFT] = node_promote(n1, 1); - head->tree[RIGHT] = node_promote(n2, 1); - n1->tree[PARENT] = head; - n2->tree[PARENT] = head; + head->tree[LEFT] = n1; + head->tree[RIGHT] = n2; - /* link leaves + /* link corresponding leaves */ - //head->leaf_list = n1->leaf_list; list_splice_tail(&n1->leaf_list, &head->leaf_list); list_splice_tail(&n2->leaf_list, &head->leaf_list); - //node_print(head); return head; } /* read node, from '[' to corresponding ']' */ -static node_t *node_read(char **p, int depth)//, node_t *parent) +static inline node_t *_node_read(char **p, int depth) { static node_t *root; node_t *node = node_get(); - node->depth = depth; - - if (!depth) { /* root node */ + if (!depth) { /* root node */ root = node; - //log_f(1, "%s\n", *p); + INIT_LIST_HEAD(&node->leaf_list); } - //log_f(2, "str=%s depth=%d\n", *p, depth); switch (**p) { case '[': (*p)++; - node->tree[LEFT] = node_read(p, depth+1); - node->tree[LEFT]->tree[PARENT] = node; - //log_i(2, "comma = %c\n", **p); + node->tree[LEFT] = _node_read(p, depth + 1); (*p)++; - node->tree[RIGHT] = node_read(p, depth+1); - node->tree[RIGHT]->tree[PARENT] = node; - //log_i(2, "closing = %c\n", **p); + node->tree[RIGHT] = _node_read(p, depth + 1); break; default: /* number */ - //log_i(2, "number = %c\n", **p); node->val = **p - '0'; list_add_tail(&node->leaf_list, &root->leaf_list); } (*p)++; - //if (!depth) { /* root node */ - // log_f(1, "%s\n", *p); - //} return node; } -/* read line, create a tree - */ -static node_t *read_line() +static inline node_t *node_read(char *p) { - node_t *head = NULL; - size_t alloc = 0; - char *buf, *p; - ssize_t buflen; - - if ((buflen = getline(&buf, &alloc, stdin)) > 0) { - p = buf; - buf[--buflen] = 0; - head = node_read(&p, 0); - } - free(buf); - //node_print(head); - return head; + char *tmp = p; + return _node_read(&tmp, 0); } /* read input @@ -345,6 +246,7 @@ static int read_lines() lines[nlines][--buflen] = 0; nlines++; } + free(lines[nlines]); /* EOF */ return nlines; } @@ -356,7 +258,7 @@ static void free_lines() free(lines[i]); } -static s64 node_magnitude(node_t *node) +static inline s64 node_magnitude(node_t *node) { if (!node->tree[LEFT]) return node->val; @@ -367,35 +269,33 @@ static s64 node_magnitude(node_t *node) static s64 part1() { node_t *head = NULL, *next = NULL; + s64 res; - head = node_read(lines + 0, 0); + head = node_read(lines[0]); for (int i = 1; i < nlines; ++i) { - next = node_read(lines + i, 0); + next = node_read(lines[i]); head = node_reduce(node_add(head, next)); } - node_print(head); - return node_magnitude(head); + res = node_magnitude(head); + node_free(head); + return res; } static s64 part2() { - node_t *l1 = NULL, *l2 = NULL; + node_t *list; s64 max = 0, cur; - char *tmp; for (int i = 0; i < nlines; ++i) { for (int j = 0; j < nlines; ++j) { if (j == i) continue; - tmp = lines[i]; - l1 = node_read(&tmp, 0); - tmp = lines[j]; - l2 = node_read(&tmp, 0); - cur = node_magnitude(node_reduce(node_add(l1, l2))); - if (cur > max) { - log(2, "NEW BEST: %s + %s\n", lines[i], lines[j]); + list = node_reduce(node_add(node_read(lines[i]), + node_read(lines[j]))); + cur = node_magnitude(list); + if (cur > max) max = cur; - } + node_free(list); } } return max; @@ -432,22 +332,7 @@ int main(int ac, char **av) exit(1); read_lines(); printf("%s : res=%ld\n", *av, part == 1? part1(): part2()); - exit(0); - node_t *n1, *n2, *n3, *n4; - n1 = read_line(); - n2 = read_line(); - //node_print(n1); - //node_print(n2); - n3 = node_add(n1, n2); - //node_print(n3); - n4 = node_reduce(n3); - node_print(n4); free_lines(); + pool_destroy(pool_nodes); exit(0); - //node_print(n1); - //node_print(n2); - n3 = node_add(n1, n2); - node_print(n3); - printf("%s : res=%ld\n", *av, part == 1? part1(): part2()); - exit (0); }