aocc23

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

uppga.c (2789B)


      1 #include "common.h"
      2 
      3 typedef struct {
      4   size_t na;
      5   size_t nb;
      6 } pos_t;
      7 
      8 static inline pos_t compute_nbrs(size_t row, size_t col, char **lines,
      9                                  size_t nrows, size_t ncols) {
     10   pos_t r;
     11 
     12   switch (lines[row][col]) {
     13   case '|':
     14     if (row == 0 || row == nrows - 1) {
     15       r.na = SIZE_MAX;
     16       r.nb = SIZE_MAX;
     17     } else {
     18       r.na = (row - 1) * ncols + col;
     19       r.nb = (row + 1) * ncols + col;
     20     }
     21     break;
     22   case '-':
     23     if (col == 0 || col == ncols - 1) {
     24       r.na = SIZE_MAX;
     25       r.nb = SIZE_MAX;
     26     } else {
     27       r.na = row * ncols + col - 1;
     28       r.nb = row * ncols + col + 1;
     29     }
     30     break;
     31   case 'F':
     32     if (col == ncols - 1 || row == nrows - 1) {
     33       r.na = SIZE_MAX;
     34       r.nb = SIZE_MAX;
     35     } else {
     36       r.na = row * ncols + col + 1;
     37       r.nb = (row + 1) * ncols + col;
     38     }
     39     break;
     40   case '7':
     41     if (col == 0 || row == nrows - 1) {
     42       r.na = SIZE_MAX;
     43       r.nb = SIZE_MAX;
     44     } else {
     45       r.na = row * ncols + col - 1;
     46       r.nb = (row + 1) * ncols + col;
     47     }
     48     break;
     49   case 'L':
     50     if (col == ncols - 1 || row == 0) {
     51       r.na = SIZE_MAX;
     52       r.nb = SIZE_MAX;
     53     } else {
     54       r.na = (row - 1) * ncols + col;
     55       r.nb = row * ncols + col + 1;
     56     }
     57     break;
     58   case 'J':
     59     if (col == 0 || row == 0) {
     60       r.na = SIZE_MAX;
     61       r.nb = SIZE_MAX;
     62     } else {
     63       r.na = (row - 1) * ncols + col;
     64       r.nb = row * ncols + col - 1;
     65     }
     66     break;
     67   default: // S or .
     68     r.na = SIZE_MAX;
     69     r.nb = SIZE_MAX;
     70   }
     71 
     72   return r;
     73 }
     74 
     75 static inline size_t traverse(size_t start, size_t next, pos_t *ns) {
     76   size_t head = next;
     77   size_t tail = start;
     78   size_t steps = 0;
     79 
     80   if (ns[head].na != tail && ns[head].nb != tail) {
     81     return SIZE_MAX;
     82   }
     83 
     84   while (head != start && ns[head].na != SIZE_MAX) {
     85     size_t tmp = head;
     86     if (ns[head].na == tail) {
     87       head = ns[head].nb;
     88     } else {
     89       head = ns[head].na;
     90     }
     91     tail = tmp;
     92     steps++;
     93   }
     94 
     95   if (head == start)
     96     return steps;
     97 
     98   return SIZE_MAX;
     99 }
    100 
    101 int main(int argc, char **argv) {
    102   char **lines;
    103   size_t i, j;
    104   size_t nlines = readlines(&lines, "input");
    105 
    106   size_t ncols = strlen(lines[0]) - 1;
    107 
    108   size_t start;
    109   pos_t ns[nlines * ncols];
    110   for (i = 0; i < nlines; i++) {
    111     for (j = 0; j < ncols; j++) {
    112       ns[i * ncols + j] = compute_nbrs(i, j, lines, nlines, ncols);
    113       if (lines[i][j] == 'S') {
    114         start = i * ncols + j;
    115       }
    116     }
    117   }
    118 
    119   size_t r;
    120   if ((r = traverse(start, start + 1, ns)) != SIZE_MAX) {
    121     printf("%zu\n", (r + 1) / 2);
    122   } else if ((r = traverse(start, start - 1, ns)) != SIZE_MAX) {
    123     printf("%zu\n", (r + 1) / 2);
    124   } else if ((r = traverse(start, start + ncols, ns)) != SIZE_MAX) {
    125     printf("%zu\n", (r + 1) / 2);
    126   } else {
    127     printf("bad\n");
    128   }
    129 }