aoc

My solutions for the Advent of Code
git clone https://git.tronto.net/aoc
Download | Log | Files | Refs | README

19b.c (2385B)


      1 #include <inttypes.h>
      2 #include <stdbool.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #define N 1000
      8 #define MAX(x,y) ((x)>(y)?(x):(y))
      9 
     10 typedef struct { int64_t val[26]; } part_t;
     11 typedef struct { char v, comp, wnext[10]; int64_t b; } rule_t;
     12 typedef struct { char name[50]; int64_t n; rule_t r[100]; } workflow_t;
     13 
     14 int64_t nw, A;
     15 workflow_t w[N];
     16 part_t p[N];
     17 
     18 workflow_t readw(char *buf) {
     19 	workflow_t ret = {0};
     20 	for (int i = 0; *buf != '{'; buf++, i++)
     21 		ret.name[i] = *buf;
     22 	for (rule_t r; *buf != '}'; ret.r[ret.n++] = r) {
     23 		buf++;
     24 		memset(&r, 0, sizeof(r));
     25 		if (*(buf+1) == '<' || *(buf+1) == '>') {
     26 			r.v = *buf;
     27 			r.comp = *(buf+1);
     28 			r.b = atoll(buf+2);
     29 			while (*buf != ':') buf++;
     30 			buf++;
     31 		}
     32 		for (int i = 0; *buf != ',' && *buf != '}'; buf++, i++)
     33 			r.wnext[i] = *buf;
     34 	}
     35 	return ret;
     36 }
     37 
     38 workflow_t findw(char *name) {
     39 	for (int i = 0; i < nw; i++)
     40 		if (!strcmp(name, w[i].name))
     41 			return w[i];
     42 	printf("Error: workflow %s not found\n", name);
     43 	exit(1);
     44 }
     45 
     46 int64_t work(workflow_t ww, int64_t lox, int64_t hix, int64_t lom, int64_t him,
     47     int64_t loa, int64_t hia, int64_t los, int64_t his) {
     48 	if (lox > hix || lom > him || loa > hia || los > his)
     49 		return 0;
     50 
     51 	int64_t ret = 0;
     52 	for (int j = 0; j < ww.n; j++) {
     53 		int64_t lox1 = lox, hix1 = hix, lom1 = lom, him1 = him,
     54 			loa1 = loa, hia1 = hia, los1 = los, his1 = his;
     55 		rule_t r = ww.r[j];
     56 		switch (r.v) {
     57 		case 'x':
     58 			if (r.comp == '<') { hix1 = r.b-1; lox = r.b; }
     59 			else { lox1 = r.b+1, hix = r.b; }
     60 			break;
     61 		case 'm':
     62 			if (r.comp == '<') { him1 = r.b-1; lom = r.b; }
     63 			else { lom1 = r.b+1, him = r.b; }
     64 			break;
     65 		case 'a':
     66 			if (r.comp == '<') { hia1 = r.b-1; loa = r.b; }
     67 			else { loa1 = r.b+1, hia = r.b; }
     68 			break;
     69 		case 's':
     70 			if (r.comp == '<') { his1 = r.b-1; los = r.b; }
     71 			else { los1 = r.b+1, his = r.b; }
     72 			break;
     73 		default:
     74 			break;
     75 		}
     76 		ret += (r.wnext[0] == 'A' || r.wnext[0] == 'R') ?
     77 			MAX(0, hix1-lox1+1) * MAX(0, him1-lom1+1) *
     78 			    MAX(0, hia1-loa1+1) * MAX(0, his1-los1+1) *
     79 			    (r.wnext[0] == 'A')
     80 			:
     81 			work(findw(r.wnext), lox1, hix1,
     82 			    lom1, him1, loa1, hia1, los1, his1);
     83 	}
     84 
     85 	return ret;
     86 }
     87 
     88 int main() {
     89 	char *buf, line[N];
     90 
     91 	for (nw = 0; *(buf = fgets(line, N, stdin)) != '\n'; nw++)
     92 		w[nw] = readw(buf);
     93 
     94 	int64_t s = work(findw("in"), 1, 4000, 1, 4000, 1, 4000, 1, 4000);
     95 
     96 	printf("%" PRId64 "\n", s);
     97 	return 0;
     98 }