aocc23

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

uppgb.c (2463B)


      1 #include "common.h"
      2 
      3 static inline uint64_t hash(char *s) {
      4   uint64_t v = 0;
      5   char *cp = s;
      6 
      7   while (*cp != '\0' && *cp != '-' && *cp != '=') {
      8     v = (17 * (v + ((uint64_t)*cp))) & 0xff;
      9     cp++;
     10   }
     11 
     12   return v;
     13 }
     14 
     15 static inline stack_str parse(char *line) {
     16   char *cp = line;
     17 
     18   stack_str stack;
     19   stack_str_init(&stack);
     20 
     21   while (*cp != '\0' && *cp != '\n') {
     22     stack_str_push(&stack, cp);
     23     while (*cp != '\0' && *cp != '\n' && *cp != ',') {
     24       cp++;
     25     }
     26     cp++;
     27   }
     28 
     29   return stack;
     30 }
     31 
     32 static inline char opn(char *s) {
     33   char *c = s;
     34   while (*c != '-' && *c != '=')
     35     c++;
     36 
     37   return *c;
     38 }
     39 
     40 static inline int cmp(char *s, char *t) {
     41   char *cs = s;
     42   char *ct = t;
     43 
     44   while (*cs != '-' && *cs != '=' && *ct != '-' && *ct != '=') {
     45     if (*cs != *ct)
     46       return 1;
     47     cs++;
     48     ct++;
     49   }
     50 
     51   if (*cs == '=' && *ct == '-')
     52     return 0;
     53 
     54   if (*cs != *ct)
     55     return 1;
     56 
     57   return 0;
     58 }
     59 
     60 typedef TAILQ_HEAD(listhead, entry) lhead_t;
     61 
     62 typedef struct entry {
     63   char *s;
     64   uint64_t fl;
     65   TAILQ_ENTRY(entry) entries;
     66 } entry_t;
     67 
     68 static inline void doop(char op, char *s, lhead_t *box) {
     69   if (op == '-') {
     70     entry_t *np;
     71     TAILQ_FOREACH(np, box, entries) {
     72       if (cmp(np->s, s) == 0) {
     73         // remove np from list
     74         TAILQ_REMOVE(box, np, entries);
     75         free(np);
     76         return;
     77       }
     78     }
     79   } else {
     80     uint64_t fl;
     81     sread_next_u64(&fl, s);
     82     entry_t *np;
     83     TAILQ_FOREACH(np, box, entries) {
     84       if (cmp(np->s, s) == 0) {
     85         // CHANGE np
     86         np->s = s;
     87         np->fl = fl;
     88         return;
     89       }
     90     }
     91 
     92     // was not in list, add it to the end
     93     entry_t *ne = malloc(sizeof(entry_t));
     94     ne->s = s;
     95     ne->fl = fl;
     96     TAILQ_INSERT_TAIL(box, ne, entries);
     97   }
     98 }
     99 
    100 static inline uint64_t boxval(lhead_t *box) {
    101   entry_t *np;
    102   uint64_t slot = 1;
    103   uint64_t v = 0;
    104 
    105   TAILQ_FOREACH(np, box, entries) {
    106     v += slot * (np->fl);
    107     slot++;
    108   }
    109 
    110   return v;
    111 }
    112 
    113 int main(int argc, char **argv) {
    114   char **lines;
    115   size_t i;
    116   readlines(&lines, "input");
    117 
    118   stack_str ops = parse(lines[0]);
    119 
    120   // initialize dlinked lists
    121   lhead_t lls[256];
    122   for (i = 0; i < 256; i++) {
    123     TAILQ_INIT(&lls[i]);
    124   }
    125 
    126   // operational state
    127   for (i = 0; i < ops.nmemb; i++) {
    128     uint64_t box = hash(ops.data[i]);
    129     doop(opn(ops.data[i]), ops.data[i], &lls[box]);
    130   }
    131 
    132   // count sum
    133   uint64_t summa = 0;
    134   for (i = 0; i < 256; i++) {
    135     summa += (i + 1) * boxval(&lls[i]);
    136   }
    137 
    138   printf("%llu\n", summa);
    139 }