diff --git a/c/2024/12/garden_groups.c b/c/2024/12/garden_groups.c new file mode 100644 index 0000000..7a08287 --- /dev/null +++ b/c/2024/12/garden_groups.c @@ -0,0 +1,135 @@ +#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; +}