uppga.c (2540B)
1 #include "common.h" 2 3 // linear search for indices is really, really terrible, 4 // but I just want to get to part b now... 5 static inline size_t coi(size_t c, cond_t **co, size_t ncond) { 6 size_t i; 7 for (i = 0; i < ncond; i++) { 8 if (co[i][0].from == c) 9 return i; 10 } 11 return SIZE_MAX; 12 } 13 14 typedef struct { 15 uint64_t v[4]; 16 } part_t; 17 18 static inline int part_satisfies(part_t x, cond_t c) { 19 switch (c.cond) { 20 case '<': 21 return x.v[c.entry] < (uint64_t)c.bound; 22 case '>': 23 return x.v[c.entry] > (uint64_t)c.bound; 24 default: 25 assert(c.cond == '='); 26 return x.v[c.entry] == (uint64_t)c.bound; 27 } 28 } 29 30 static inline int check_part_recurse(part_t x, cond_t **co, size_t ncond, 31 size_t current, size_t accepted, 32 size_t rejected) { 33 if (current == accepted) 34 return 1; 35 if (current == rejected) 36 return 0; 37 38 size_t cnt = coi(current, co, ncond); 39 40 size_t j = 0; 41 while (co[cnt][j].bound != -1) { 42 if (part_satisfies(x, co[cnt][j])) { 43 return check_part_recurse(x, co, ncond, co[cnt][j].to, accepted, 44 rejected); 45 } 46 j++; 47 } 48 return check_part_recurse(x, co, ncond, co[cnt][j].to, accepted, rejected); 49 } 50 51 static inline int check_part(part_t x, cond_t **co, size_t nconds, 52 size_t accepted, size_t rejected, size_t in) { 53 return check_part_recurse(x, co, nconds, in, accepted, rejected); 54 } 55 56 int main(int argc, char **argv) { 57 char **lines; 58 size_t nlines = readlines(&lines, "input"); 59 size_t i, nconds; 60 61 cond_t *co[nlines]; 62 for (i = 0; i < nlines; i++) 63 co[i] = malloc(sizeof(*co[i]) * 512); 64 65 dict_t names; 66 dict_init(&names); 67 stack_u64 *v = parse(&names, &nconds, co, lines, nlines); 68 69 // print_dict(&names); 70 71 sd accepted_sd, rejected_sd, in_sd; 72 sd_init_str(&accepted_sd, "A"); 73 sd_init_str(&rejected_sd, "R"); 74 sd_init_str(&in_sd, "in"); 75 size_t accepted = *(size_t *)dict_lookup(&names, accepted_sd); 76 size_t rejected = *(size_t *)dict_lookup(&names, rejected_sd); 77 size_t in = *(size_t *)dict_lookup(&names, in_sd); 78 79 uint64_t add = 0; 80 for (i = 0; i < v[0].nmemb; i++) { 81 part_t tpart; 82 tpart.v[0] = v[0].data[i]; 83 tpart.v[1] = v[1].data[i]; 84 tpart.v[2] = v[2].data[i]; 85 tpart.v[3] = v[3].data[i]; 86 if (check_part(tpart, co, nconds, accepted, rejected, in)) { 87 add += tpart.v[0] + tpart.v[1] + tpart.v[2] + tpart.v[3]; 88 } 89 } 90 91 for (i = 0; i < nlines; i++) 92 free(co[i]); 93 94 printf("%llu\n", add); 95 }