aocc23

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

uppgb.c (2401B)


      1 #include "common.h"
      2 
      3 typedef struct {
      4   size_t identifier;
      5   uint64_t value;
      6 } adj_t;
      7 
      8 static inline int is_digit(char x) { return '0' <= x && x <= '9'; }
      9 
     10 static inline int update_adjacents(adj_t *adjs, const adj_t x) {
     11   if (x.identifier) {
     12     if (adjs[0].identifier == 0) {
     13       adjs[0] = x;
     14     } else if (adjs[0].identifier != x.identifier) {
     15       if (adjs[1].identifier != 0) {
     16         if (adjs[1].identifier != x.identifier) {
     17           return 0; // more than 2
     18         }
     19       } else {
     20         adjs[1] = x;
     21       }
     22     }
     23   }
     24 
     25   return 1;
     26 }
     27 
     28 static uint64_t gear_ratio(char **lines, const size_t i, const size_t j,
     29                            const size_t nrows, const size_t ncols,
     30                            adj_t *table) {
     31   if (lines[i][j] != '*')
     32     return 0;
     33 
     34   adj_t adjs[2];
     35   adjs[0].identifier = 0;
     36   adjs[1].identifier = 0;
     37 
     38   coordinate_t ns[9];
     39   nbrs(ns, i, j, nrows, ncols);
     40 
     41   size_t k = 0;
     42   while (is_defined(ns[k])) {
     43     if (!update_adjacents(adjs, table[ns[k].y * ncols + ns[k].x]))
     44       return 0;
     45     k++;
     46   }
     47 
     48   if (adjs[1].identifier != 0) {
     49     return adjs[0].value * adjs[1].value;
     50   }
     51 
     52   return 0;
     53 }
     54 
     55 static inline void make_tables(adj_t *table, char **lines, const size_t nrows,
     56                                const size_t ncols) {
     57   size_t count = 1;
     58   uint64_t nnum = 0;
     59   int innum = 0;
     60   size_t i, j;
     61   for (i = 0; i < nrows; i++) {
     62     for (j = 0; j < ncols; j++) {
     63       if (is_digit(lines[i][j])) {
     64         if (nnum == 0) {
     65           nnum = strtoull(&lines[i][j], NULL, 10);
     66         }
     67         table[i * ncols + j].value = nnum;
     68         table[i * ncols + j].identifier = count;
     69         innum = 1;
     70       } else if (innum) {
     71         count++;
     72         innum = 0;
     73         table[i * ncols + j].value = 0;
     74         table[i * ncols + j].identifier = 0;
     75         nnum = 0;
     76       } else {
     77         table[i * ncols + j].value = 0;
     78         table[i * ncols + j].identifier = 0;
     79       }
     80     }
     81   }
     82 }
     83 
     84 int main(int argc, char **argv) {
     85   char **lines;
     86   size_t nrows = readlines(&lines, "input");
     87   size_t ncols = strlen(lines[0]) - 1;
     88 
     89   adj_t table[nrows * ncols];
     90   make_tables(table, lines, nrows, ncols);
     91 
     92   size_t i, j;
     93   uint64_t ratsum = 0;
     94   for (i = 0; i < nrows; i++) {
     95     for (j = 0; j < ncols; j++) {
     96       uint64_t rat = gear_ratio(lines, i, j, nrows, ncols, table);
     97       if (rat > 0) {
     98         ratsum += rat;
     99       }
    100     }
    101   }
    102 
    103   printf("%llu\n", ratsum);
    104 }