From: Mart Lubbers Date: Mon, 20 Dec 2021 10:38:14 +0000 (+0100) Subject: day 18 X-Git-Url: https://git.martlubbers.net/?a=commitdiff_plain;h=3f719e53a93064f75711d41ac38d0ae163354cf7;p=advent21.git day 18 --- diff --git a/18a.c b/18a.c index 719c3f0..acec8d3 100644 --- a/18a.c +++ b/18a.c @@ -4,52 +4,149 @@ #include struct number { - int depth; int number; + int depth; + struct number *prev; + struct number *next; }; -int parse_number(struct number numbers[]) +void print_number(struct number *head) +{ + for (struct number *e = head; e != NULL; e = e->next) + printf("(%d,%d) ", e->number, e->depth); + printf("\n"); +} + +struct number *parse_comp(struct number *prev, int *depth) { - int ns = 0; - int depth = 0; int c = getchar(); - while ((c = getchar()) != '\n') { - switch(c) { - case '[': - depth++; - break; - case ']': - depth--; - break; - case ',': - break; - default: - if (isdigit(c)) - numbers[ns++] = (struct number){.depth=depth, .number=c-'0'}; - else - printf("halp\n"); - break; - } + if (isdigit(c)) { + struct number *r = malloc(sizeof(struct number)); + r->next = NULL; + r->prev = prev; + if (prev != NULL) + prev->next = r; + r->number = c-'0'; + r->depth = *depth; + return r; + } else if (c == ',') { + return parse_comp(prev, depth); + } else if (c == '[') { + *depth = *depth+1; + return parse_comp(prev, depth); + } else if (c == ']') { + *depth = *depth-1; + return parse_comp(prev, depth); + } else if (c != '\n' && c != EOF) { + printf("unknown character: '%c': %d\n", c, c); } - return ns; + return NULL; } -void print_number(struct number n[], int ns) +struct number *parse_number() { - int olddepth = 0; - for (int i = 0; i olddepth) - printf("["); - else if (n[i].depth < olddepth) - printf("]"); - printf("%d ", n[i].number); - olddepth = n[i].depth; + int depth = 0; + struct number *head = parse_comp(NULL, &depth); + if (head == NULL) + return NULL; + struct number *e = head; + while ((e = parse_comp(e, &depth)) != NULL) + ; + return head; +} + +void add_number(struct number *sum, struct number *oper) +{ + //increase depth of sum + struct number *e = sum; + for (; e->next != NULL; e = e->next) + e->depth++; + //append + e->next = oper; + oper->prev = e; + //increase depth of oper + for (; e != NULL; e = e->next) + e->depth++; +} + +bool explode_number(struct number *e) +{ + if (e->depth <= 4) + return false; + struct number *l = e; + struct number *r = e->next; + if (l->prev != NULL) + l->prev->number += l->number; + if (r->next != NULL) + r->next->number += r->number; + l->number = 0; + l->depth--; + l->next = r->next; + if (l->next != NULL) + l->next->prev = l; + if (l->prev != NULL) + e = l->prev; + free(r); + return true; +} + +bool split_number(struct number *e) +{ + if (e->number < 10) + return false; + struct number *i = malloc(sizeof(struct number)); + i->number = e->number/2 + (e->number%2); + i->depth = e->depth+1; + i->prev = e; + i->next = e->next; + e->next = i; + e->number = e->number/2; + e->depth = e->depth+1; + return true; +} + +void reduce_number(struct number *n) +{ + bool appliedaction; + do { + appliedaction = false; + for (struct number *e = n; e != NULL && !appliedaction; e = e->next) + appliedaction |= explode_number(e); + for (struct number *e = n; e != NULL && !appliedaction; e = e->next) + appliedaction |= split_number(e); + } while (appliedaction); +} + +int magnitude_number(struct number *n) +{ + int maxdepth = 4; + while (n->next != NULL) { + for (struct number *e = n; e != NULL; e = e->next) { + if (e->depth == maxdepth) { + struct number *l = e; + struct number *r = e->next; + l->depth--; + l->number = l->number*3 + r->number*2; + l->next = r->next; + if (r->next != NULL) + r->next->prev = l; + free(r); + } + } + maxdepth--; } + int r = n->number; + free(n); + return r; } int main () { - struct number n[100]; - int ns = parse_number(n); - print_number(n, ns); + struct number *sum = parse_number(); + struct number *oper; + while ((oper = parse_number()) != NULL) { + add_number(sum, oper); + reduce_number(sum); + } + printf("%d\n", magnitude_number(sum)); } diff --git a/18b.c b/18b.c new file mode 100644 index 0000000..490b038 --- /dev/null +++ b/18b.c @@ -0,0 +1,185 @@ +#include +#include +#include +#include + +struct number { + int number; + int depth; + struct number *prev; + struct number *next; +}; + +void print_number(struct number *head) +{ + for (struct number *e = head; e != NULL; e = e->next) + printf("(%d,%d) ", e->number, e->depth); + printf("\n"); +} + +struct number *parse_comp(struct number *prev, int *depth) +{ + int c = getchar(); + if (isdigit(c)) { + struct number *r = malloc(sizeof(struct number)); + r->next = NULL; + r->prev = prev; + if (prev != NULL) + prev->next = r; + r->number = c-'0'; + r->depth = *depth; + return r; + } else if (c == ',') { + return parse_comp(prev, depth); + } else if (c == '[') { + *depth = *depth+1; + return parse_comp(prev, depth); + } else if (c == ']') { + *depth = *depth-1; + return parse_comp(prev, depth); + } else if (c != '\n' && c != EOF) { + printf("unknown character: '%c': %d\n", c, c); + } + return NULL; +} + +struct number *parse_number() +{ + int depth = 0; + struct number *head = parse_comp(NULL, &depth); + if (head == NULL) + return NULL; + struct number *e = head; + while ((e = parse_comp(e, &depth)) != NULL) + ; + return head; +} + +void add_number(struct number *sum, struct number *oper) +{ + //increase depth of sum + struct number *e = sum; + for (; e->next != NULL; e = e->next) + e->depth++; + //append + e->next = oper; + oper->prev = e; + //increase depth of oper + for (; e != NULL; e = e->next) + e->depth++; +} + +bool explode_number(struct number *e) +{ + if (e->depth <= 4) + return false; + struct number *l = e; + struct number *r = e->next; + if (l->prev != NULL) + l->prev->number += l->number; + if (r->next != NULL) + r->next->number += r->number; + l->number = 0; + l->depth--; + l->next = r->next; + if (l->next != NULL) + l->next->prev = l; + if (l->prev != NULL) + e = l->prev; + free(r); + return true; +} + +bool split_number(struct number *e) +{ + if (e->number < 10) + return false; + struct number *i = malloc(sizeof(struct number)); + i->number = e->number/2 + (e->number%2); + i->depth = e->depth+1; + i->prev = e; + i->next = e->next; + e->next = i; + e->number = e->number/2; + e->depth = e->depth+1; + return true; +} + +void reduce_number(struct number *n) +{ + bool appliedaction; + do { + appliedaction = false; + for (struct number *e = n; e != NULL && !appliedaction; e = e->next) + appliedaction |= explode_number(e); + for (struct number *e = n; e != NULL && !appliedaction; e = e->next) + appliedaction |= split_number(e); + } while (appliedaction); +} + +int magnitude_number(struct number *n) +{ + int maxdepth = 4; + while (n->next != NULL) { + for (struct number *e = n; e != NULL; e = e->next) { + if (e->depth == maxdepth) { + struct number *l = e; + struct number *r = e->next; + l->depth--; + l->number = l->number*3 + r->number*2; + l->next = r->next; + if (r->next != NULL) + r->next->prev = l; + free(r); + } + } + maxdepth--; + } + int r = n->number; + free(n); + return r; +} + +struct number *copy_number(struct number *n) +{ + struct number *copy = malloc(sizeof(struct number)); + copy->number = n->number; + copy->depth = n->depth; + copy->prev = NULL; + copy->next = NULL; + struct number *prev = copy; + for (struct number *e = n->next; e != NULL; e = e->next) { + struct number *c = malloc(sizeof(struct number)); + c->depth = e->depth; + c->number = e->number; + c->next = NULL; + c->prev = prev; + if (prev != NULL) + prev->next = c; + prev = c; + } + return copy; +} + +int main () +{ + int nnumber = 0; + struct number *numbers[100] = {0}; + while ((numbers[nnumber] = parse_number()) != NULL) + nnumber++; + + int maxmagnitude = 0; + for (int i = 0; i maxmagnitude) + maxmagnitude = magnitude; + } + } + printf("%d\n", maxmagnitude); +} diff --git a/18e.txt b/18e.txt new file mode 100644 index 0000000..61b0df6 --- /dev/null +++ b/18e.txt @@ -0,0 +1,2 @@ +[[[[4,3],4],4],[7,[[8,4],9]]] +[1,1] diff --git a/18e2.txt b/18e2.txt new file mode 100644 index 0000000..f430960 --- /dev/null +++ b/18e2.txt @@ -0,0 +1,2 @@ +[[[[[9,8],1],2],3],4] + diff --git a/18e3.txt b/18e3.txt new file mode 100644 index 0000000..41c8d15 --- /dev/null +++ b/18e3.txt @@ -0,0 +1 @@ +[7,[6,[5,[4,[3,2]]]]] diff --git a/18e4.txt b/18e4.txt new file mode 100644 index 0000000..9f59172 --- /dev/null +++ b/18e4.txt @@ -0,0 +1 @@ +[[6,[5,[4,[3,2]]]],1] diff --git a/18e5.txt b/18e5.txt new file mode 100644 index 0000000..f212f83 --- /dev/null +++ b/18e5.txt @@ -0,0 +1,4 @@ +[1,1] +[2,2] +[3,3] +[4,4] diff --git a/18e6.txt b/18e6.txt new file mode 100644 index 0000000..d1c17ef --- /dev/null +++ b/18e6.txt @@ -0,0 +1 @@ +[[[[3,0],[5,3]],[4,4]],[5,5]] diff --git a/18e7.txt b/18e7.txt new file mode 100644 index 0000000..85acce5 --- /dev/null +++ b/18e7.txt @@ -0,0 +1,6 @@ +[1,1] +[2,2] +[3,3] +[4,4] +[5,5] +[6,6] diff --git a/18e8.txt b/18e8.txt new file mode 100644 index 0000000..70e9071 --- /dev/null +++ b/18e8.txt @@ -0,0 +1,10 @@ +[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]] +[7,[[[3,7],[4,3]],[[6,3],[8,8]]]] +[[2,[[0,8],[3,4]]],[[[6,7],1],[7,[1,6]]]] +[[[[2,4],7],[6,[0,5]]],[[[6,8],[2,8]],[[2,1],[4,5]]]] +[7,[5,[[3,8],[1,4]]]] +[[2,[2,2]],[8,[8,1]]] +[2,9] +[1,[[[9,3],9],[[9,0],[0,7]]]] +[[[5,[7,4]],7],1] +[[[[4,2],2],6],[8,7]] diff --git a/Makefile b/Makefile index a350a35..b6f6074 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ CFLAGS:=-Wall -Wextra -O3 LFLAGS:=-f -BINARIES:=$(filter-out 18a 18b 19a 19b,$(foreach num,$(shell seq -f '%02.0f' 1 20),$(num)a $(num)b)) +BINARIES:=$(filter-out 19a 19b,$(foreach num,$(shell seq -f '%02.0f' 1 20),$(num)a $(num)b)) -all: +all: $(BINARIES) clean: $(RM) *.o a.out $(BINARIES)