aocc22

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

common.c (2961B)


      1 #include "common.h"
      2 
      3 monkis parse_monkis(char **lines, size_t nlines, int mods) {
      4   monkis r;
      5   size_t i, j;
      6   uint64_t t;
      7 
      8   r.mod = malloc(nlines * sizeof(*r.mod));
      9 
     10   r.n = 0;
     11   r.nitems = 0;
     12   for (i = 0; i < nlines; i++) {
     13     if (lines[i][0] == 'M')
     14       r.n++;
     15     else if (strlen(lines[i]) > 2) {
     16       if (lines[i][2] == 'S') {
     17         char *p = lines[i];
     18         while ((p = sread_next_u64(&t, p)) != NULL)
     19           r.nitems++;
     20       } else if (lines[i][2] == 'T') {
     21         sread_next_u64(&(r.mod[r.n - 1]), lines[i]);
     22       }
     23     }
     24   }
     25 
     26   r.mod = realloc(r.mod, r.n * sizeof(*r.mod));
     27 
     28   r.rmod = malloc(r.n * sizeof(*r.rmod));
     29   memcpy(r.rmod, r.mod, r.n * sizeof(*r.rmod));
     30   if (!mods)
     31     for (i = 0; i < r.n; i++)
     32       r.mod[i] = UINT64_MAX;
     33 
     34   r.fnext = malloc(r.n * sizeof(*r.fnext));
     35   r.tnext = malloc(r.n * sizeof(*r.tnext));
     36   r.heads = malloc(r.n * sizeof(*r.heads));
     37 
     38   r.inspections = calloc(r.n, sizeof(*r.inspections));
     39 
     40   r.items = malloc(r.nitems * r.n * sizeof(*r.items));
     41 
     42   size_t cm = 0, ci = 0;
     43   for (i = 0; i < nlines; i++) {
     44     if (strlen(lines[i]) > 2) {
     45       if (lines[i][4] == 'I') {
     46         sread_next_u64(&t, lines[i]);
     47         if (lines[i][7] == 't')
     48           r.tnext[cm] = t;
     49         else
     50           r.fnext[cm] = t;
     51       } else if (lines[i][2] == 'S') {
     52         SIMPLEQ_INIT(&r.heads[cm]);
     53         char *p = lines[i];
     54         while ((p = sread_next_u64(&t, p)) != NULL) {
     55           struct entry *new_entry = malloc(sizeof(*new_entry));
     56           new_entry->index = ci;
     57           SIMPLEQ_INSERT_TAIL(&r.heads[cm], new_entry, entries);
     58           for (j = 0; j < r.n; j++)
     59             r.items[ci * r.n + j] = t % r.mod[j];
     60           ci++;
     61         }
     62       }
     63     } else {
     64       cm++;
     65     }
     66   }
     67   return r;
     68 }
     69 
     70 void mmonkey(monkis m, size_t i) {
     71   uint64_t *tmp;
     72   struct entry *np;
     73   size_t j;
     74 
     75   while (!SIMPLEQ_EMPTY(&m.heads[i])) {
     76     m.inspections[i]++;
     77     np = SIMPLEQ_FIRST(&m.heads[i]);
     78     SIMPLEQ_REMOVE_HEAD(&m.heads[i], entries);
     79     tmp = &(m.items[np->index * m.n]);
     80     for (j = 0; j < m.n; j++)
     81       tmp[j] = (m.operate)(tmp[j], i) % m.mod[j];
     82 
     83     size_t new_index = (tmp[i] % m.rmod[i]) == 0 ? m.tnext[i] : m.fnext[i];
     84 
     85     SIMPLEQ_INSERT_TAIL(&m.heads[new_index], np, entries);
     86   }
     87 }
     88 
     89 void mround(monkis m) {
     90   size_t i;
     91   for (i = 0; i < m.n; i++)
     92     mmonkey(m, i);
     93 }
     94 
     95 uint64_t get_result(monkis m) {
     96   uint64_t tmax[2] = {0, 0};
     97 
     98   size_t i;
     99   for (i = 0; i < m.n; i++) {
    100     if (m.inspections[i] > tmax[0])
    101       tmax[0] = m.inspections[i];
    102     if (tmax[0] > tmax[1])
    103       tmax[0] ^= tmax[1] ^= tmax[0] ^= tmax[1];
    104   }
    105 
    106   return tmax[0] * tmax[1];
    107 }
    108 
    109 void let_the_monkis_out(monkis m) {
    110   free(m.mod);
    111   free(m.tnext);
    112   free(m.fnext);
    113 
    114   free(m.items);
    115 
    116   size_t i;
    117   struct entry *t;
    118   for (i = 0; i < m.n; i++) {
    119     while (!SIMPLEQ_EMPTY(&m.heads[i])) {
    120       t = SIMPLEQ_FIRST(&m.heads[i]);
    121       SIMPLEQ_REMOVE_HEAD(&m.heads[i], entries);
    122       free(t);
    123     }
    124   }
    125   free(m.heads);
    126 }