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