aocc23

Advent of Code 2023
git clone git://www.tkruger.se/aocc23.git
Log | Files | Refs | README

uppga.c (2540B)


      1 #include "common.h"
      2 
      3 // linear search for indices is really, really terrible,
      4 // but I just want to get to part b now...
      5 static inline size_t coi(size_t c, cond_t **co, size_t ncond) {
      6   size_t i;
      7   for (i = 0; i < ncond; i++) {
      8     if (co[i][0].from == c)
      9       return i;
     10   }
     11   return SIZE_MAX;
     12 }
     13 
     14 typedef struct {
     15   uint64_t v[4];
     16 } part_t;
     17 
     18 static inline int part_satisfies(part_t x, cond_t c) {
     19   switch (c.cond) {
     20   case '<':
     21     return x.v[c.entry] < (uint64_t)c.bound;
     22   case '>':
     23     return x.v[c.entry] > (uint64_t)c.bound;
     24   default:
     25     assert(c.cond == '=');
     26     return x.v[c.entry] == (uint64_t)c.bound;
     27   }
     28 }
     29 
     30 static inline int check_part_recurse(part_t x, cond_t **co, size_t ncond,
     31                                      size_t current, size_t accepted,
     32                                      size_t rejected) {
     33   if (current == accepted)
     34     return 1;
     35   if (current == rejected)
     36     return 0;
     37 
     38   size_t cnt = coi(current, co, ncond);
     39 
     40   size_t j = 0;
     41   while (co[cnt][j].bound != -1) {
     42     if (part_satisfies(x, co[cnt][j])) {
     43       return check_part_recurse(x, co, ncond, co[cnt][j].to, accepted,
     44                                 rejected);
     45     }
     46     j++;
     47   }
     48   return check_part_recurse(x, co, ncond, co[cnt][j].to, accepted, rejected);
     49 }
     50 
     51 static inline int check_part(part_t x, cond_t **co, size_t nconds,
     52                              size_t accepted, size_t rejected, size_t in) {
     53   return check_part_recurse(x, co, nconds, in, accepted, rejected);
     54 }
     55 
     56 int main(int argc, char **argv) {
     57   char **lines;
     58   size_t nlines = readlines(&lines, "input");
     59   size_t i, nconds;
     60 
     61   cond_t *co[nlines];
     62   for (i = 0; i < nlines; i++)
     63     co[i] = malloc(sizeof(*co[i]) * 512);
     64 
     65   dict_t names;
     66   dict_init(&names);
     67   stack_u64 *v = parse(&names, &nconds, co, lines, nlines);
     68 
     69   //  print_dict(&names);
     70 
     71   sd accepted_sd, rejected_sd, in_sd;
     72   sd_init_str(&accepted_sd, "A");
     73   sd_init_str(&rejected_sd, "R");
     74   sd_init_str(&in_sd, "in");
     75   size_t accepted = *(size_t *)dict_lookup(&names, accepted_sd);
     76   size_t rejected = *(size_t *)dict_lookup(&names, rejected_sd);
     77   size_t in = *(size_t *)dict_lookup(&names, in_sd);
     78 
     79   uint64_t add = 0;
     80   for (i = 0; i < v[0].nmemb; i++) {
     81     part_t tpart;
     82     tpart.v[0] = v[0].data[i];
     83     tpart.v[1] = v[1].data[i];
     84     tpart.v[2] = v[2].data[i];
     85     tpart.v[3] = v[3].data[i];
     86     if (check_part(tpart, co, nconds, accepted, rejected, in)) {
     87       add += tpart.v[0] + tpart.v[1] + tpart.v[2] + tpart.v[3];
     88     }
     89   }
     90 
     91   for (i = 0; i < nlines; i++)
     92     free(co[i]);
     93 
     94   printf("%llu\n", add);
     95 }