Files
adventofcode2024/day12/c/day12.c

204 lines
6.6 KiB
C
Raw Normal View History

2024-12-13 20:13:38 +01:00
#include <stdio.h>
#include <stdlib.h>
#define MAX_DIMENSION 1024
#define MAX_REGION 1024
void fill(char **map, int x, int y, int **region, int rows, int columns);
int main() {
char c;
char **map = calloc(MAX_DIMENSION, sizeof(map[0]));
int rows = 0, columns, i = 0;
map[rows] = calloc(MAX_DIMENSION, sizeof(map[0][0]));
while ((c = getchar()) != EOF) {
map[rows][i] = c;
i++;
if (c != '\n') {
continue;
}
columns = i - 1;
i = 0;
rows++;
map[rows] = calloc(MAX_DIMENSION, sizeof(map[0][0]));
}
int **visited = calloc(rows, sizeof(visited[0]));
for (i = 0; i < rows; i++) {
visited[i] = calloc(columns, sizeof(visited[0][0]));
}
int ***regions = calloc(MAX_REGION, sizeof(regions[0]));
int region_count = 0;
int cost = 0;
int cost2 = 0;
for (i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (visited[i][j]) {
continue;
}
// Create new region
regions[region_count] = calloc(rows, sizeof(regions[0][0]));
for (int k = 0; k < rows; k++) {
regions[region_count][k] = calloc(columns, sizeof(regions[0][0][0]));
}
// Fill new region
fill(map, i, j, regions[region_count], rows, columns);
int area = 0;
// Copy to visited
for (int k = 0; k < rows; k++) {
for (int l = 0; l < columns; l++) {
visited[k][l] |= regions[region_count][k][l];
area += regions[region_count][k][l];
}
}
// Calculate perimeter
int perimeter = 0;
for (int k = 0; k < rows; k++) {
for (int l = 0; l < columns; l++) {
if (!regions[region_count][k][l]) {
continue;
}
int row;
int column;
// Up
row = k - 1;
column = l;
if (row < 0 || !regions[region_count][row][column]) {
perimeter += 1;
}
// Down
row = k + 1;
column = l;
if (row >= rows || !regions[region_count][row][column]) {
perimeter += 1;
}
// Left
row = k;
column = l + 1;
if (column >= columns || !regions[region_count][row][column]) {
perimeter += 1;
}
// Right
row = k;
column = l - 1;
if (column < 0 || !regions[region_count][row][column]) {
perimeter += 1;
}
}
}
cost += area * perimeter;
// Calculate perimeter task two
perimeter = 0;
for (int k = 0; k < rows; k++) {
for (int l = 0; l < columns; l++) {
if (!regions[region_count][k][l]) {
continue;
}
if (k == 0) {
if (l == 0 || !regions[region_count][k][l-1]) {
perimeter++;
}
} else if (!regions[region_count][k-1][l]) {
if (l == 0 || !regions[region_count][k][l-1] || (regions[region_count][k][l-1] && regions[region_count][k][l-1] == regions[region_count][k-1][l-1])) {
perimeter++;
}
}
if (k == rows - 1) {
if (l == 0 || !regions[region_count][k][l-1]) {
perimeter++;
}
} else if (!regions[region_count][k+1][l]) {
if (l == 0 || !regions[region_count][k][l-1] || (regions[region_count][k][l-1] && regions[region_count][k][l-1] == regions[region_count][k+1][l-1])) {
perimeter++;
}
}
if (l == 0) {
if (k == 0 || !regions[region_count][k-1][l]) {
perimeter++;
}
} else if (!regions[region_count][k][l-1]) {
if (k == 0 || !regions[region_count][k-1][l] || (regions[region_count][k-1][l] && regions[region_count][k-1][l] == regions[region_count][k-1][l-1])) {
perimeter++;
}
}
if (l == columns - 1) {
if (k == 0 || !regions[region_count][k-1][l]) {
perimeter++;
}
} else if (!regions[region_count][k][l+1]) {
if (k == 0 || !regions[region_count][k-1][l] || (regions[region_count][k-1][l] && regions[region_count][k-1][l] == regions[region_count][k-1][l+1])) {
perimeter++;
}
}
}
}
cost2 += area * perimeter;
region_count++;
}
}
printf("%i\n", cost);
printf("%i\n", cost2);
for (i = 0; i < region_count; i++) {
for (int j = 0; j < rows; j++) {
free(regions[i][j]);
}
free(regions[i]);
}
free(regions);
for (i = 0; i < rows; i++) {
free(visited[i]);
}
free(visited);
for (i = 0; i < rows + 1; i++) {
free(map[i]);
}
free(map);
}
void fill(char **map, int x, int y, int **region, int rows, int columns) {
region[x][y] = 1;
int row;
int column;
// Up
row = x - 1;
column = y;
if (row >= 0 && map[row][column] == map[x][y] && !region[row][column]) {
fill(map, row, column, region, rows, columns);
}
// Down
row = x + 1;
column = y;
if (row < rows && map[row][column] == map[x][y] && !region[row][column]) {
fill(map, row, column, region, rows, columns);
}
// Left
row = x;
column = y + 1;
if (column < columns && map[row][column] == map[x][y] && !region[row][column]) {
fill(map, row, column, region, rows, columns);
}
// Right
row = x;
column = y - 1;
if (column >= 0 && map[row][column] == map[x][y] && !region[row][column]) {
fill(map, row, column, region, rows, columns);
}
}