123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- #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;
- }
|