advent2023

Advent of Code 2023 solutions
git clone git://bsandro.tech/advent2023
Log | Files | Refs | LICENSE

commit e584643b1730db34a12cc42cc47f34b48aa9de36
parent 5f889027bb1ee05d04ee549c8c05641f21c6e01e
Author: bsandro <email@bsandro.tech>
Date:   Sat,  9 Dec 2023 03:57:14 +0200

day 08 p2

Diffstat:
Mday08/puzzle.c | 121++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 93 insertions(+), 28 deletions(-)

diff --git a/day08/puzzle.c b/day08/puzzle.c @@ -43,9 +43,44 @@ Node * find_node(Node *first, char name[4]) { typedef struct Anode { Node *start; - int znodes[]; + uint64_t znode; } Anode; +typedef struct Item { + Node *node; + uint64_t steps; + struct Item *next; +} Item; +Item * new_item() { + Item *item = malloc(sizeof(Item)); + memset(item, 0, sizeof(Item)); + return item; +} +Item * find_item(Item *items, Node *node) { + Item *item = items; + while (item!=NULL) { + if (item->node == node) return item; + item = item->next; + } + return NULL; +} +void print_items(Item *items) { + Item *item = items; + while (item!=NULL) { + printf("%s[%" PRIu64 "] -> ", item->node->name, item->steps); + item = item->next; + } + printf("\n"); +} +void free_items(Item *items) { + Item *item = items; + while (item!=NULL) { + Item *n = item->next; + free(item); + item = n; + } +} + bool check_z_nodes(Anode *anodes, size_t len) { for (size_t i=0; i<len; ++i) { if (anodes[i].start->name[2]!='Z') { @@ -63,6 +98,14 @@ void print_nodes(Node *first) { } } +static uint64_t gcd(uint64_t a, uint64_t b) { + return b==0 ? a : gcd(b, a%b); +} + +static uint64_t lcm(uint64_t a, uint64_t b) { + return (a*b)/gcd(a,b); +} + void puzzle(const char *filename, long long *result1, long long *result2) { FILE *infile = fopen(filename, "r"); if (infile == NULL) { @@ -99,16 +142,16 @@ void puzzle(const char *filename, long long *result1, long long *result2) { // starting nodes for p.2 if (node->name[2]=='A') { ++anodes_len; - anodes = realloc(anodes, anodes_len*sizeof(Anode*)); + anodes = realloc(anodes, anodes_len*sizeof(Anode)); anodes[anodes_len-1].start = node; - //anodes[anodes_len-1].znodes = NULL; + anodes[anodes_len-1].znode = 0; } } ++line_num; bzero(buf, STR_LEN); } - int steps = 0; + uint64_t steps = 0; int il = strlen(instructions); // p.1 Node *n = find_node(nodes, "AAA"); @@ -129,40 +172,62 @@ void puzzle(const char *filename, long long *result1, long long *result2) { *result1 = steps; break; } - if (steps==INT_MAX) { + if (steps==UINT64_MAX) { printf("steps overflow\n"); break; } } // p.2 - steps = 0; - while (1) { - char instr = instructions[steps % il]; - if (instr!='L'&&instr!='R') { - printf("illegal instruction %c\n", instr); - break; - } - for (size_t i=0; i<anodes_len; ++i) { - Node *n = anodes[i]; - Node *nn = find_node(nodes, instr=='L'?n->left:n->right); - if (nn==NULL) { - printf("node %s was not found\n", instr=='L'?n->left:n->right); - return; + // fill anodes with znode + for (size_t i=0; i<anodes_len; ++i) { + steps = 0; + Node *n = anodes[i].start; + //printf("filling anode %s\n", n->name); + Item *hist = NULL; + Item *hist_last = NULL; + Node *z = NULL; + Node *w = NULL; + while (1) { + char instr = instructions[steps%il]; + n = find_node(nodes, instr=='L'?n->left:n->right); + //printf("checking %s\n", n->name); + if (n->name[2]=='Z') { + if (z!=NULL&&n!=z) { + printf("z nodes are different\n"); + } + anodes[i].znode = steps+1; + z = n; + } + if (find_item(hist, n)==NULL) { + Item *it = new_item(); + it->node = n; + it->steps = steps; + if (hist==NULL) hist=it; + if (hist_last!=NULL) hist_last->next=it; + hist_last=it; + } else if (w==NULL) { + //printf("anode %s wrapped up on %s (%" PRIu64 ")\n", anodes[i].start->name, n->name, steps+1); + w = n; + //free_items(hist); + //break; + } + ++steps; + if (z!=NULL) { + free_items(hist); + break; + } + if (steps==UINT64_MAX) { + break; } - anodes[i] = nn; - } - ++steps; - if (check_z_nodes(anodes, anodes_len)) { - *result2 = steps; - break; - } - if (steps==INT_MAX) { - printf("steps overflow\n"); - break; } } + *result2 = anodes[0].znode; + for (size_t i=1; i<anodes_len; ++i) { + *result2 = lcm(*result2, anodes[i].znode); + } + // mutiny! ignoring feof/ferror. fclose(infile); (void)result2;