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