#include #include #include #include #include "../../lib/aoc.h" struct Map; typedef struct Region { struct Map *map; char plant; int positions[1000]; int positions_count; } Region; typedef struct Map { char *data; int width; int height; int input_length; Region regions[1000]; int regions_count; } Map; int region_perimeter(Region *r) { int perimeter = 0; for (int i = 0; i < r->positions_count; i++) { int position = r->positions[i]; if (position - r->map->width < 0 || r->map->data[position - r->map->width] != r->plant - 'A' + 'a') { perimeter++; } if (position - 1 < 0 || r->map->data[position - 1] != r->plant - 'A' + 'a') { perimeter++; } if (position + 1 > r->map->input_length || r->map->data[position + 1] != r->plant - 'A' + 'a') { perimeter++; } if (position + r->map->width > r->map->input_length || r->map->data[position + r->map->width] != r->plant - 'A' + 'a') { perimeter++; } } return perimeter; } int region_price(Region *r) { int rp = region_perimeter(r); int price = rp * r->positions_count; return price; } int main() { char *input = aoc_read_input(); int input_length = strlen(input); Map m; fflush(stdout); m.data = input; m.width = strchr(input, '\n') - input + 1; m.height = input_length / m.width; m.regions_count = 0; m.input_length = input_length; // initialize regions for (int i = 0; i < input_length; i++) { if (m.data[i] == '\n' || m.data[i] < 'A' || m.data[i] > 'Z') continue; Region *r = &(m.regions[m.regions_count++]); r->plant = m.data[i]; r->positions_count = 0; r->map = &m; int next_positions[1000]; next_positions[0] = i; int next_positions_count = 1; int nn_positions[1000]; int nn_positions_count = 0; while (next_positions_count > 0) { for (int j = 0; j < next_positions_count; j++) { int next_position = next_positions[j]; r->positions[r->positions_count++] = next_position; m.data[next_position] = m.data[next_position] - 'A' + 'a'; } for (int j = 0; j < next_positions_count; j++) { int next_position = next_positions[j]; if (next_position - m.width > 0 && m.data[next_position - m.width] == r->plant) { nn_positions[nn_positions_count++] = next_position - m.width; } if (next_position - 1 > 0 && m.data[next_position - 1] == r->plant) { nn_positions[nn_positions_count++] = next_position - 1; } if (next_position + 1 < input_length && m.data[next_position + 1] == r->plant) { nn_positions[nn_positions_count++] = next_position + 1; } if (next_position + m.width < input_length && m.data[next_position + m.width] == r->plant) { nn_positions[nn_positions_count++] = next_position + m.width; } } qsort(nn_positions, nn_positions_count, sizeof(int), aoc_sort_int); if (nn_positions_count == 0) break; next_positions_count = 1; next_positions[0] = nn_positions[0]; for (int j = 1; j < nn_positions_count; j++) { if (nn_positions[j] != next_positions[next_positions_count - 1]) { next_positions[next_positions_count++] = nn_positions[j]; } } nn_positions_count = 0; } } int cost = 0; for (int i = 0; i < m.regions_count; i++) { cost += region_price(&m.regions[i]); // printf("%c: %d\n", m.regions[i].plant, m.regions[i].positions_count); } printf("Part 1: %d\n", cost); // printf("Part 2: %lld\n", big_stone_count_sum); aoc_free(); return 0; }