diff options
author | Marvin Borner | 2020-12-08 20:56:10 +0100 |
---|---|---|
committer | Marvin Borner | 2020-12-08 20:56:29 +0100 |
commit | a48df2144386d4779aaa73fcaaa46bcc66c79c4d (patch) | |
tree | cf5fbac2c35ee6939b750e8a9bc36d17c065b7bc /2020/04/solve.c | |
parent | c3071578cfe3f97cfda05372ff2da64474a9d0c1 (diff) |
Fixed naming for 10+ challenges
Diffstat (limited to '2020/04/solve.c')
-rw-r--r-- | 2020/04/solve.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/2020/04/solve.c b/2020/04/solve.c new file mode 100644 index 0000000..a613660 --- /dev/null +++ b/2020/04/solve.c @@ -0,0 +1,156 @@ +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void normalize(char *data) +{ + for (char *p = data; *p; p++) { + if (*p == '\n' && *(p + 1) == '\n') { + *p = ' '; + p++; + } else if (*p == '\n') { + *p = ' '; + } + } +} + +char *valid[] = { "byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid" }; +char *valid_colors[] = { "amb", "blu", "brn", "gry", "grn", "hzl", "oth" }; + +int part_one(char *data) +{ + int res = 0; + + int correct = 0; + for (char *p = data; *p; p++) { + if (*p == '\n') { + if (correct == 7) + res++; + correct = 0; + continue; + } + + char key[4] = { 0 }; + char value[16] = { 0 }; + sscanf(p, "%3[^:]:%s ", key, value); + + for (int i = 0; i < sizeof(valid) / sizeof(valid[0]); ++i) { + if (!strcmp(key, valid[i])) { + correct++; + break; + } + } + + p += 3 + strlen(value) + 1; + if (*(p + 1) == '\0') { + if (correct == 7) + res++; + } + } + + return res; +} + +#define EQ(a, b) (!strcmp((a), (b))) // String equality +#define BR(x) ((x) >= 1920 && (x) <= 2002) // Birth rule +#define IR(x) ((x) >= 2010 && (x) <= 2020) // Issue rule +#define ER(x) ((x) >= 2020 && (x) <= 2030) // Expiration rule +#define HR(x) ((x) >= 150 && (x) <= 193) // Height rule +#define CR(x) \ + (EQ(x, "amb") || EQ(x, "blu") || EQ(x, "brn") || EQ(x, "gry") || EQ(x, "grn") || \ + EQ(x, "hzl") || EQ(x, "oth")) // Eye color rule +// BTW: I hate gotos +int part_two(char *data) +{ + int res = 0; + + int correct = 0; + for (char *p = data; *p; p++) { + if (*p == '\n') { + if (correct == 7) + res++; + correct = 0; + continue; + } + char key[4] = { 0 }; + char value[16] = { 0 }; + sscanf(p, "%3[^:]:%s ", key, value); + + // General value verification/parsing + int y = 0; + if (EQ(key, "byr") || EQ(key, "iyr") || EQ(key, "eyr")) { + if (!sscanf(value, "%4d", &y)) + goto invalid; + } else if (EQ(key, "hgt")) { + char last = value[strlen(value) - 1]; + if (last == 'm') { + sscanf(value, "%dcm", &y); + } else if (last == 'n') { + sscanf(value, "%din", &y); + y = (int)roundf(((float)y * 2.54)); // lol + } else { + goto invalid; + } + } else if (EQ(key, "hcl") && (strlen(value) != 7 || !sscanf(value, "#%6x", &y))) { + goto invalid; + } else if (EQ(key, "ecl")) { + char c[4]; + if (!sscanf(value, "%3s", c) || !CR(c)) + goto invalid; + } else if (EQ(key, "pid")) { + if (!sscanf(value, "%9d", &y)) + goto invalid; + } + + // Number range verification + if (EQ(key, "byr") && !BR(y)) + goto invalid; + else if (EQ(key, "iyr") && !IR(y)) + goto invalid; + else if (EQ(key, "eyr") && !ER(y)) + goto invalid; + else if (EQ(key, "hgt") && !HR(y)) { + goto invalid; + } + + for (int i = 0; i < sizeof(valid) / sizeof(valid[0]); ++i) { + if (!strcmp(key, valid[i])) { + correct++; + break; + } + } + + goto next; + + invalid: + /* printf("Invalid: %s:%s (y=%d)\n", key, value, y); */ + correct = -42; // Awesome fix! + next: + p += 3 + strlen(value) + 1; + if (*(p + 1) == '\0') { + if (correct == 7) + res++; + } + } + + return res; +} + +#define SIZE 20000 +int main(int argc, char *argv[]) +{ + FILE *fp = fopen("input", "r"); + if (!fp) + exit(EXIT_FAILURE); + char buf[SIZE] = { 0 }; + fread(buf, SIZE, 1, fp); + normalize(buf); + + printf("%d\n", part_one(buf)); + printf("%d\n", part_two(buf)); + + fclose(fp); + return 0; +} |