diff options
| author | Mistivia <i@mistivia.com> | 2024-01-27 14:02:35 +0800 |
|---|---|---|
| committer | Mistivia <i@mistivia.com> | 2024-01-27 14:02:35 +0800 |
| commit | 6580dcd9127f69aaa794472ec92bc46015dc4019 (patch) | |
| tree | dc2c7e102c75180f7bd98c2f3a14f8b55f83c0f2 /advent-of-code/2023/03/part2.c | |
init
Diffstat (limited to 'advent-of-code/2023/03/part2.c')
| -rw-r--r-- | advent-of-code/2023/03/part2.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/advent-of-code/2023/03/part2.c b/advent-of-code/2023/03/part2.c new file mode 100644 index 0000000..a5ab825 --- /dev/null +++ b/advent-of-code/2023/03/part2.c @@ -0,0 +1,149 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> + +#include "vec.h" +#include "str.h" +#include "map.h" + +void* read_input() { + FILE* fp = fopen("./input", "r"); + void *vec = new_vec(); + while(1) { + char *line = fgetline(fp); + if (line == NULL) break; + char *stripped = str_strip(line); + if (strlen(stripped) == 0) break; + vec_push_back(vec, stripped); + } + return vec; +} + +typedef struct { + int line; + int column; + int value; + int length; +} num_t; + +char *compose_key(int x, int y) { + void* ss = new_ss(); + ss_add(ss, "%d,%d", x, y); + return ss_cstr(ss); +} + +void *parse_nums(void *schema) { + void *nums = new_vec(); + int j = 0; + const int IN_NUM = 0, IDLE = 1; + int state = IDLE; + for (int i = 0; i < vec_size(schema); i++) { + char *line = vec_get(schema, i); + int line_len = strlen(line); + int value = 0; + int length = 0; + state = IDLE; + j = 0; + while (1) { + char c = '.'; + if (j < line_len) c = line[j]; + if (state == IDLE) { + if (isdigit(c)) { + state = IN_NUM; + continue; + } else { + j++; + if (j >= line_len) break; + continue; + } + } else if (state == IN_NUM) { + if (isdigit(c)) { + value = value * 10 + (c - '0'); + length++; + j++; + continue; + } else { + num_t *n = malloc(sizeof(num_t)); + *n = (num_t){ + .line = i, + .column = j - length, + .value = value, + .length = length + }; + vec_push_back(nums, n); + value = 0; + length = 0; + state = IDLE; + if (j >= line_len) break; + continue; + } + } + } + } + return nums; +} + +char char_at(void *schema, int line, int column) { + char *buf = vec_get(schema, line); + return buf[column]; +} + +void mark_asterisks(void *asterisks, num_t *num, int x, int y) { + const char *key = compose_key(x, y); + void *num_list = dict_get(asterisks, key); + if (num_list == NULL) { + num_list = new_vec(); + dict_set(asterisks, key, num_list); + } + vec_push_back(num_list, num); +} + +void find_asterisks(void *schema, void *asterisks, num_t *num) { + int line_len = vec_size(schema); + int col_len = strlen(vec_get(schema, 0)); + for (int i = num->column - 1; i < num->column + num->length + 1; i++) { + if (num->line - 1 < 0) continue; + if (i < 0 || i >= col_len) continue; + char c = char_at(schema, num->line - 1, i); + if (c == '*') mark_asterisks(asterisks, num, num->line - 1, i); + } + for (int i = num->column - 1; i < num->column + num->length + 1; i++) { + if (num->line + 1 >= line_len) continue; + if (i < 0 || i >= col_len) continue; + char c = char_at(schema, num->line + 1, i); + if (c == '*') mark_asterisks(asterisks, num, num->line + 1, i); + } + if (num->column - 1 >= 0) { + char c = char_at(schema, num->line, num->column - 1); + if (c == '*') mark_asterisks(asterisks, num, num->line, num->column - 1); + } + if (num->column + num->length < col_len) { + char c = char_at(schema, num->line, num->column + num->length); + if (c == '*') mark_asterisks(asterisks, num, num->line, num->column + num->length); + } +} + +int main() { + void *schema = read_input(); + void *nums = parse_nums(schema); + int sum = 0; + void *asterisks = new_dict(); + for (int i = 0; i < vec_size(nums); i++) { + num_t *num = vec_get(nums, i); + find_asterisks(schema, asterisks, num); + } + for (void *iter = dict_begin(asterisks); + iter != NULL; + iter = dict_next(asterisks, iter)) { + void *list = dict_iter_value(iter); + if (vec_size(list) == 2) { + num_t* n1 = vec_get(list, 0); + num_t* n2 = vec_get(list, 1); + sum += n1->value * n2->value; + } + } + printf("%d\n", sum); + return 0; +} |
