aocc22

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

uppgb.c (5687B)


      1 #include "common.h"
      2 
      3 #define SEC 30ULL
      4 #define NOTCOMPUTED UINT64_MAX
      5 #define NONBR SIZE_MAX
      6 
      7 #define ASIZE ((uint64_t)('Z' - 'A' + 1))
      8 #define MAP_SIZE (ASIZE * ASIZE)
      9 
     10 typedef struct {
     11   size_t n;
     12   size_t m;
     13 
     14   size_t nv;
     15   uint64_t *v; // store computed values
     16 
     17   uint64_t *flows;
     18   size_t *nzflows; // maps position to index of nonzero flow (in e.g. state)
     19   size_t **nbrs;
     20 } valves;
     21 
     22 static inline size_t statelen(valves v) { return v.m + 2; }
     23 
     24 static inline size_t statemax(valves v) { return ((v.n) * (v.n) << v.m) - 1; }
     25 
     26 static inline char *goto_nbrs(char *s) {
     27   size_t i = 0, c = 0;
     28   while (c != 9) {
     29     if (s[i] == ' ')
     30       c++;
     31     i++;
     32   }
     33   return &(s[i]);
     34 }
     35 
     36 static inline size_t map_index(char *x) {
     37   return ASIZE * ((uint64_t)(x[0] - 'A')) + ((uint64_t)(x[1] - 'A'));
     38 }
     39 
     40 void init_valves(valves *v, char **lines, const size_t n) {
     41   v->n = n;
     42   v->m = 0;
     43 
     44   v->flows = malloc((v->n) * sizeof(*(v->flows)));
     45   v->nzflows = malloc((v->n) * sizeof(*(v->nzflows)));
     46   v->nbrs = malloc((v->n) * sizeof(*(v->nbrs)));
     47 
     48   size_t i, j;
     49   size_t map[MAP_SIZE];
     50   for (i = 0; i < MAP_SIZE; i++)
     51     map[i] = SIZE_MAX;
     52   for (i = 0; i < n; i++) {
     53     char *line = lines[i];
     54     map[map_index(&line[6])] = i;
     55   }
     56 
     57   for (i = 0; i < n; i++) {
     58     char *line = lines[i];
     59 
     60     char *flowstr = &line[23];
     61     uint64_t flow;
     62     sread_next_u64(&flow, flowstr);
     63     v->flows[i] = flow;
     64     if (flow != 0) {
     65       v->nzflows[i] = v->m;
     66       v->m++;
     67     } else {
     68       v->nzflows[i] = SIZE_MAX;
     69     }
     70 
     71     v->nbrs[i] = malloc((v->n) * sizeof(*(v->nbrs[i])));
     72     char *nbrs = goto_nbrs(line);
     73     char *cn = nbrs;
     74     j = 0;
     75     while (cn[0] != '\n' && cn[0] != '\0') {
     76       assert(cn[0] <= 'Z' && cn[0] >= 'A');
     77       assert(cn[1] <= 'Z' && cn[1] >= 'A');
     78       v->nbrs[i][j] = map[map_index(cn)];
     79       if (strlen(cn) < 4) {
     80         j++;
     81         break;
     82       }
     83       j++;
     84       cn = &cn[4];
     85     }
     86     while (j < v->n) {
     87       v->nbrs[i][j] = NONBR;
     88       j++;
     89     }
     90   }
     91 
     92   v->nv = statemax(*v) + 1;
     93   v->v = malloc((v->nv) * sizeof(*(v->v)));
     94 }
     95 
     96 size_t f(const uint8_t *state, const valves *v) {
     97   size_t r = ((unsigned long)state[0]) * (v->n) + (unsigned long)state[1];
     98   size_t i;
     99   for (i = 0; i < v->m; i++) {
    100     r <<= 1;
    101     if (state[i + 2])
    102       r++;
    103   }
    104   return r;
    105 }
    106 
    107 void f_inv(uint8_t *state, const size_t y, const valves *v) {
    108   size_t i;
    109   size_t slen = statelen(*v);
    110 
    111   size_t x = y;
    112 
    113   for (i = 1; i <= v->m; i++) {
    114     if ((x & 0x01) != 0) {
    115       state[slen - i] = 1;
    116     } else {
    117       state[slen - i] = 0;
    118     }
    119     x >>= 1;
    120   }
    121 
    122   assert(x < (v->n) * (v->n));
    123 
    124   state[1] = (uint8_t)(x % (v->n));
    125   state[0] = (uint8_t)(x / (v->n));
    126 }
    127 
    128 uint8_t *init_starting_state(valves v) {
    129   uint8_t *r = malloc(statelen(v));
    130 
    131   r[0] = 0; // posituon AA == 0
    132   r[1] = 0; // elephant position same
    133 
    134   size_t i;
    135   for (i = 2; i < v.m + 2; i++)
    136     r[i] = 0; // no valves on
    137 
    138   return r;
    139 }
    140 
    141 static inline uint64_t stateflow(uint64_t b, const valves *v) {
    142   uint64_t r = 0;
    143   size_t i;
    144   for (i = 0; i < v->n; i++) {
    145     if (v->flows[i] != 0 && (b & (0x1 << v->nzflows[i])) != 0) {
    146       r += v->flows[i];
    147     }
    148   }
    149   return r;
    150 }
    151 
    152 void print_state(const uint8_t *state, const valves *v) {
    153   printf("%u : %u : ", state[0], state[1]);
    154   size_t i;
    155   for (i = 0; i < v->m; i++) {
    156     printf("%u ", state[i + 2]);
    157   }
    158   printf("\n");
    159 }
    160 
    161 static inline uint64_t vss(size_t s, valves *v) {
    162   return 0x01 << (v->m - s - 1);
    163 }
    164 
    165 static inline uint64_t fss(uint64_t py, uint64_t pe, uint64_t b, valves *v) {
    166   uint64_t r = py * (v->n) + pe;
    167   size_t i;
    168   for (i = 0; i < v->m; i++) {
    169     r <<= 1;
    170     if ((b & vss(i, v)) != 0)
    171       r++;
    172   }
    173   return r;
    174 }
    175 
    176 uint64_t *compute_level(valves *v, int level) {
    177   size_t i, j;
    178   uint64_t b;
    179   uint64_t *new = malloc((v->nv) * sizeof(*new));
    180 
    181   if (level <= 0) {
    182     for (i = 0; i < v->nv; i++)
    183       new[i] = 0;
    184   } else {
    185     size_t blim = (1 << v->m);
    186     for (i = 0; i < v->n; i++) {   // you pos
    187       for (j = 0; j < v->n; j++) { // E pos
    188         for (b = 0; b < blim; b++) {
    189           uint64_t best = 0;
    190           if (v->flows[i] != 0 && v->flows[j] != 0) {
    191             best = v->v[fss(
    192                 i, j, (b | (0x01 << v->nzflows[i]) | (0x01 << v->nzflows[j])),
    193                 v)];
    194           }
    195 
    196           uint64_t bprim;
    197           size_t k = 0, l;
    198           uint64_t t;
    199           if (v->flows[i] != 0) {
    200             k = 0;
    201             bprim = b | (0x01 << v->nzflows[i]);
    202             while (v->nbrs[j][k] != NONBR) {
    203               t = v->v[fss(i, v->nbrs[j][k], bprim, v)];
    204               if (t > best)
    205                 best = t;
    206               k++;
    207             }
    208           }
    209 
    210           if (v->flows[j] != 0) {
    211             bprim = b | (0x01 << v->nzflows[j]);
    212             k = 0;
    213             while (v->nbrs[i][k] != NONBR) {
    214               t = v->v[fss(v->nbrs[i][k], j, bprim, v)];
    215               if (t > best)
    216                 best = t;
    217               k++;
    218             }
    219           }
    220 
    221           k = 0;
    222           while (v->nbrs[i][k] != NONBR) {
    223             l = 0;
    224             while (v->nbrs[j][l] != NONBR) {
    225               t = v->v[fss(v->nbrs[i][k], v->nbrs[j][l], b, v)];
    226               if (t > best)
    227                 best = t;
    228               l++;
    229             }
    230             k++;
    231           }
    232 
    233           new[fss(i, j, b, v)] = stateflow(b, v) + best;
    234         }
    235       }
    236     }
    237   }
    238 
    239   return new;
    240 }
    241 
    242 int main(int argc, char **argv) {
    243   char **lines;
    244   valves v;
    245   size_t nlines = readlines(&lines, "sinput");
    246 
    247   init_valves(&v, lines, nlines);
    248   uint64_t *r;
    249   size_t i;
    250   for (i = 0; i < 27; i++) {
    251     printf("--- LEVEL %zu ---\n", i);
    252     r = compute_level(&v, i);
    253     free(v.v);
    254     v.v = r;
    255   }
    256 
    257   printf("%llu\n", v.v[fss(0, 0, 0, &v)]);
    258 }