diff options
Diffstat (limited to '2023/19/19a.c')
| -rw-r--r-- | 2023/19/19a.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/2023/19/19a.c b/2023/19/19a.c new file mode 100644 index 0000000..81ee535 --- /dev/null +++ b/2023/19/19a.c | |||
| @@ -0,0 +1,87 @@ | |||
| 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 | |||
| 9 | typedef struct { int64_t val[26]; } part_t; | ||
| 10 | typedef struct { char v, comp, wnext[10]; int64_t b; } rule_t; | ||
| 11 | typedef struct { char name[50]; int64_t n; rule_t r[100]; } workflow_t; | ||
| 12 | |||
| 13 | int64_t nw, np, A; | ||
| 14 | workflow_t w[N]; | ||
| 15 | part_t p[N]; | ||
| 16 | |||
| 17 | workflow_t readw(char *buf) { | ||
| 18 | workflow_t ret = {0}; | ||
| 19 | for (int i = 0; *buf != '{'; buf++, i++) | ||
| 20 | ret.name[i] = *buf; | ||
| 21 | for (rule_t r; *buf != '}'; ret.r[ret.n++] = r) { | ||
| 22 | buf++; | ||
| 23 | memset(&r, 0, sizeof(r)); | ||
| 24 | if (*(buf+1) == '<' || *(buf+1) == '>') { | ||
| 25 | r.v = *buf; | ||
| 26 | r.comp = *(buf+1); | ||
| 27 | r.b = atoll(buf+2); | ||
| 28 | while (*buf != ':') buf++; | ||
| 29 | buf++; | ||
| 30 | } | ||
| 31 | for (int i = 0; *buf != ',' && *buf != '}'; buf++, i++) | ||
| 32 | r.wnext[i] = *buf; | ||
| 33 | } | ||
| 34 | return ret; | ||
| 35 | } | ||
| 36 | |||
| 37 | part_t readp(char *buf) { | ||
| 38 | part_t p = {0}; | ||
| 39 | while (*buf != '}') { | ||
| 40 | buf++; | ||
| 41 | p.val[*buf-'a'] = atoll(buf+2); | ||
| 42 | while(*buf != ',' && *buf != '}') buf++; | ||
| 43 | } | ||
| 44 | return p; | ||
| 45 | } | ||
| 46 | |||
| 47 | int64_t value(part_t p) { | ||
| 48 | return p.val['x'-'a'] + p.val['m'-'a'] + p.val['a'-'a'] + p.val['s'-'a']; | ||
| 49 | } | ||
| 50 | |||
| 51 | bool satisfy(part_t p, rule_t r) { | ||
| 52 | if (r.v == 0) return true; | ||
| 53 | int64_t val = p.val[r.v-'a']; | ||
| 54 | return r.comp == '<' ? (val < r.b) : (val > r.b); | ||
| 55 | } | ||
| 56 | |||
| 57 | workflow_t findw(char *name) { | ||
| 58 | for (int i = 0; i < nw; i++) | ||
| 59 | if (!strcmp(name, w[i].name)) | ||
| 60 | return w[i]; | ||
| 61 | printf("Error: workflow %s not found\n", name); | ||
| 62 | exit(1); | ||
| 63 | } | ||
| 64 | |||
| 65 | int main() { | ||
| 66 | char *buf, line[N]; | ||
| 67 | |||
| 68 | for (nw = 0; *(buf = fgets(line, N, stdin)) != '\n'; nw++) | ||
| 69 | w[nw] = readw(buf); | ||
| 70 | |||
| 71 | for (np = 0; (buf = fgets(line, N, stdin)) != NULL; np++) | ||
| 72 | p[np] = readp(buf); | ||
| 73 | |||
| 74 | for (int i = 0; i < np; i++) { | ||
| 75 | workflow_t ww = findw("in"); | ||
| 76 | for (rule_t r; ; ww = findw(r.wnext)) { | ||
| 77 | for (int64_t j = 0; !satisfy(p[i], r = ww.r[j]); j++) ; | ||
| 78 | if (!strcmp("A", r.wnext) || !strcmp("R", r.wnext)) { | ||
| 79 | A += value(p[i]) * (r.wnext[0] == 'A'); | ||
| 80 | break; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | printf("%" PRId64 "\n", A); | ||
| 86 | return 0; | ||
| 87 | } | ||
