176 lines
4 KiB
C
176 lines
4 KiB
C
#include<stdlib.h>
|
|
#include<stdio.h>
|
|
#include<string.h>
|
|
#include<stdbool.h>
|
|
|
|
struct list {
|
|
char type;
|
|
struct square *tiles;
|
|
unsigned int area;
|
|
unsigned int perimeter;
|
|
struct list *next;
|
|
};
|
|
struct square {
|
|
int x;
|
|
int y;
|
|
struct square *next;
|
|
};
|
|
|
|
bool tile_in_list(int x, int y, struct list *plot)
|
|
{
|
|
if (!plot)
|
|
return 0;
|
|
struct square *current = plot->tiles;
|
|
while (current) {
|
|
if (current->x == x && current->y == y) {
|
|
return 1;
|
|
}
|
|
current = current->next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool plot_exists (int x, int y, struct list *plots)
|
|
{
|
|
struct list *current = plots;
|
|
while (current) {
|
|
if (tile_in_list(x, y, current))
|
|
return 1;
|
|
current = current->next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void add_tile(int x, int y, struct list *plot)
|
|
{
|
|
if (plot->tiles == NULL) {
|
|
plot->tiles = malloc(sizeof(struct square));
|
|
plot->tiles->x = x;
|
|
plot->tiles->y = y;
|
|
plot->tiles->next = NULL;
|
|
return;
|
|
}
|
|
|
|
struct square *tiles = plot->tiles;
|
|
while (tiles->next)
|
|
tiles = tiles->next;
|
|
|
|
tiles->next = malloc(sizeof(struct square));
|
|
tiles->next->x = x;
|
|
tiles->next->y = y;
|
|
tiles->next->next = NULL;
|
|
}
|
|
|
|
struct list *check_plot(int x, int y, int width, int height, char **map, struct list *plot, bool daddy)
|
|
{
|
|
int dir[4][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
|
|
int perimeter = 0;
|
|
// daddy simply states if this function was called from the outside,
|
|
// since the main loop will never send grids in the same plot
|
|
// should actually be solved by handling the list outside this func
|
|
|
|
struct list *prevPlot = plot;
|
|
while (plot && plot->type != map[x][y]) {
|
|
prevPlot = plot;
|
|
plot = plot->next;
|
|
}
|
|
// create list of every tile in this plot
|
|
// init list
|
|
if (plot == NULL || daddy) {
|
|
plot = malloc(sizeof(struct list));
|
|
plot->type = map[x][y];
|
|
plot->area = 0;
|
|
plot->perimeter = 0;
|
|
plot->tiles = NULL;
|
|
plot->next = NULL;
|
|
if (prevPlot)
|
|
prevPlot->next = plot;
|
|
}
|
|
// check if current tile is in this list
|
|
// if yes, return
|
|
if (tile_in_list(x, y, plot))
|
|
return NULL;
|
|
// else, add, then check all surrounding tiles with this function
|
|
add_tile(x, y, plot);
|
|
plot->area++;
|
|
|
|
// look in every direction for same type, recurse it
|
|
for (int i = 0; i < 4; i++) {
|
|
if (x + dir[i][0] >= 0 &&
|
|
x + dir[i][0] < width &&
|
|
y + dir[i][1] >= 0 &&
|
|
y + dir[i][1] < height) {
|
|
if (map[x + dir[i][0]][y + dir[i][1]] == map[x][y]) {
|
|
check_plot(x + dir[i][0], y + dir[i][1],
|
|
width, height, map, plot, false);
|
|
} else {
|
|
plot->perimeter++;
|
|
}
|
|
} else
|
|
plot->perimeter++;
|
|
}
|
|
return plot;
|
|
}
|
|
|
|
int main ()
|
|
{
|
|
// figure out data dimensions
|
|
FILE *input = fopen("./input", "r");
|
|
int width = 0;
|
|
int height = 1;
|
|
while (fgetc(input) != '\n') width++;
|
|
for (char c = fgetc(input); c != EOF; c = fgetc(input)) {
|
|
if (c == '\n')
|
|
height++;
|
|
}
|
|
rewind(input);
|
|
printf("Dimensions: %d x %d\n", width, height);
|
|
|
|
// make 2d array
|
|
char **map = malloc(width * sizeof(char*));
|
|
map[0] = malloc(width * height);
|
|
for (int i = 1; i < width; i++) {
|
|
map[i] = map[0] + i * height;
|
|
}
|
|
|
|
// put the data in the array
|
|
for (int i = 0; i < height; i++) {
|
|
for (int j = 0; j < width; j++) {
|
|
map[j][i] = fgetc(input);
|
|
}
|
|
fgetc(input);
|
|
}
|
|
fclose(input);
|
|
|
|
int scoreSum = 0;
|
|
// find plots not in list, check their score
|
|
struct list *plots = NULL;
|
|
struct list *current = NULL;
|
|
char prevType = 0;
|
|
for (int i = 0; i < height; i++) {
|
|
for (int j = 0; j < width; j++) {
|
|
// nasty if. prev type, skip. first, init head.
|
|
// else, if tile is already in plot-list, skip
|
|
// else, add a new plot to the list from current tile
|
|
if (map[j][i] == prevType)
|
|
continue;
|
|
if (i == 0 && j == 0) {
|
|
plots = check_plot(j,i, width, height, map, plots, true);
|
|
current = plots;
|
|
}
|
|
else if (plot_exists(j, i, plots))
|
|
continue;
|
|
else
|
|
current = check_plot(j,i, width, height, map, current, true);
|
|
}
|
|
}
|
|
current = plots;
|
|
int sum = 0;
|
|
while (current) {
|
|
printf("plot %c is area %d and perimeter %d\n", current->type, current->area, current->perimeter);
|
|
sum += current->area * current->perimeter;
|
|
current = current->next;
|
|
}
|
|
|
|
printf("total score: %d\n", sum);
|
|
}
|