advent-of-code-2024/day-12/main.c

83 lines
3.1 KiB
C

#include "aoc.h"
const int dx[] = {0, 1, 0, -1};
const int dy[] = {-1, 0, 1, 0};
static inline bool
inside(Grid *grid, int x, int y) {
return x >= 0 && y >= 0 && x < grid->width && y < grid->height;
}
static inline bool
unequal_or_outside(Grid *grid, int x, int y, char type) {
if (inside(grid, x, y)) {
return grid->grid[y * grid->width + x] != type;
}
else {
return true;
}
}
static void
flood_fill(Grid *grid, bool *visited, int x, int y, int *area, int *perimeter, int *sides) {
if (visited[y * grid->width + x]) {
return;
}
char type = grid->grid[y * grid->width + x];
(*area)++;
visited[y * grid->width + x] = true;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (unequal_or_outside(grid, nx, ny, type)) {
(*perimeter)++;
}
else {
flood_fill(grid, visited, nx, ny, area, perimeter, sides);
}
}
// convex corners
*sides += (unequal_or_outside(grid, x - 1, y, type) && unequal_or_outside(grid, x, y - 1, type)); // top left corner
*sides += (unequal_or_outside(grid, x + 1, y, type) && unequal_or_outside(grid, x, y - 1, type)); // top right corner
*sides += (unequal_or_outside(grid, x - 1, y, type) && unequal_or_outside(grid, x, y + 1, type)); // bottom left corner
*sides += (unequal_or_outside(grid, x + 1, y, type) && unequal_or_outside(grid, x, y + 1, type)); // bottom right corner
// concave corners
*sides += (!unequal_or_outside(grid, x - 1, y, type) && !unequal_or_outside(grid, x - 1, y - 1, type) && unequal_or_outside(grid, x, y - 1, type)); // top left corner
*sides += (!unequal_or_outside(grid, x + 1, y, type) && !unequal_or_outside(grid, x + 1, y - 1, type) && unequal_or_outside(grid, x, y - 1, type)); // top right corner
*sides += (!unequal_or_outside(grid, x - 1, y, type) && !unequal_or_outside(grid, x - 1, y + 1, type) && unequal_or_outside(grid, x, y + 1, type)); // bottom left corner
*sides += (!unequal_or_outside(grid, x + 1, y, type) && !unequal_or_outside(grid, x + 1, y + 1, type) && unequal_or_outside(grid, x, y + 1, type)); // bottom right corner
}
int main(int argc, char **argv) {
Arena *arena = make_arena(Megabytes(1));
str input = read_file(arena, argv[1]);
Grid grid = parse_grid(input, arena);
bool *visited = ARENA_ALLOC_ARRAY(arena, bool, grid.width * grid.height);
i64 part_1 = 0;
i64 part_2 = 0;
for (int y = 0; y < grid.height; y++) {
for (int x = 0; x < grid.width; x++) {
if (!visited[y * grid.width + x]) {
int area = 0;
int perimeter = 0;
int sides = 0;
flood_fill(&grid, visited, x, y, &area, &perimeter, &sides);
char type = grid.grid[y * grid.width + x];
/* printf("type = %c, area = %d, perimeter = %d, sides = %d\n", type, area, perimeter, sides); */
part_1 += area * perimeter;
part_2 += area * sides;
}
}
}
printf("%ld\n", part_1);
printf("%ld\n", part_2);
}