Files
adventofcode2023/day10/c/day10.c
2023-12-10 15:14:55 +01:00

270 lines
8.6 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_MAP_SIZE 256
typedef enum tile_type {
GROUND,
UP_DOWN,
LEFT_RIGHT,
UP_RIGHT,
UP_LEFT,
DOWN_LEFT,
DOWN_RIGHT,
START
} tile_type_t;
typedef struct tile {
tile_type_t type;
struct tile *links[2];
int part_of_loop;
} tile_t;
int main() {
char *p, *buf, c;
buf = (char *)malloc(MAX_MAP_SIZE);
memset(buf, 0, MAX_MAP_SIZE);
p = buf;
tile_t map[MAX_MAP_SIZE][MAX_MAP_SIZE];
memset(map, 0, MAX_MAP_SIZE*MAX_MAP_SIZE*sizeof(tile_t));
int x = 0, y = 0;
while ((c = getchar()) != EOF) {
*p++ = c;
if (c == '\n') {
x = 0;
p = buf;
while (*p != '\n') {
switch (*p) {
case '.':
map[x][y].type = GROUND;
break;
case '|':
map[x][y].type = UP_DOWN;
// UP
if (y != 0) {
map[x][y].links[0] = &map[x][y-1];
}
// DOWN
map[x][y].links[1] = &map[x][y+1];
break;
case '-':
map[x][y].type = LEFT_RIGHT;
// LEFT
if (x != 0) {
map[x][y].links[0] = &map[x-1][y];
}
// RIGHT
map[x][y].links[1] = &map[x+1][y];
break;
case 'L':
map[x][y].type = UP_RIGHT;
// UP
if (y != 0) {
map[x][y].links[0] = &map[x][y-1];
}
// RIGHT
map[x][y].links[1] = &map[x+1][y];
break;
case 'J':
map[x][y].type = UP_LEFT;
// UP
if (y != 0) {
map[x][y].links[0] = &map[x][y-1];
}
// LEFT
if (x != 0) {
map[x][y].links[1] = &map[x-1][y];
}
break;
case '7':
map[x][y].type = DOWN_LEFT;
// DOWN
map[x][y].links[0] = &map[x][y+1];
// LEFT
if (x != 0) {
map[x][y].links[1] = &map[x-1][y];
}
break;
case 'F':
map[x][y].type = DOWN_RIGHT;
// DOWN
map[x][y].links[0] = &map[x][y+1];
// RIGHT
map[x][y].links[1] = &map[x+1][y];
break;
case 'S':
map[x][y].type = START;
break;
}
p++;
x++;
}
y++;
memset(buf, 0, MAX_MAP_SIZE);
p = buf;
}
}
// Find start
tile_t *start, *curr, *prev;
int found = 0;
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
if (map[j][i].type == START) {
start = &map[j][i];
curr = start;
found = 1;
int link_num = 0;
// Connect up start tile
// UP
if (i != 0) {
for (int k = 0; k < 2; k++) {
if (map[j][i-1].links[k] == start) {
start->links[link_num] = &map[j][i-1];
link_num++;
break;
}
}
}
// DOWN
for (int k = 0; k < 2; k++) {
if (map[j][i+1].links[k] == start) {
start->links[link_num] = &map[j][i+1];
link_num++;
break;
}
}
// LEFT
if (j != 0) {
for (int k = 0; k < 2; k++) {
if (map[j-1][i].links[k] == start) {
start->links[link_num] = &map[j-1][i];
link_num++;
break;
}
}
}
// RIGHT
for (int k = 0; k < 2; k++) {
if (map[j+1][i].links[k] == start) {
start->links[link_num] = &map[j+1][i];
link_num++;
break;
}
}
// Assign the correct type to the start tile, needed for part2
if (start->links[0] == &map[j][i-1] && start->links[1] == &map[j][i+1]) {
start->type = UP_DOWN;
}
if (start->links[0] == &map[j][i-1] && start->links[1] == &map[j+1][i]) {
start->type = UP_RIGHT;
}
if (start->links[0] == &map[j][i-1] && start->links[1] == &map[j-1][i]) {
start->type = UP_LEFT;
}
if (start->links[0] == &map[j-1][i] && start->links[1] == &map[j+1][i]) {
start->type = LEFT_RIGHT;
}
if (start->links[0] == &map[j][i+1] && start->links[1] == &map[j-1][i]) {
start->type = DOWN_LEFT;
}
if (start->links[0] == &map[j][i+1] && start->links[1] == &map[j+1][i]) {
start->type = DOWN_RIGHT;
}
break;
}
}
if (found) {
break;
}
}
// Count to loop length
unsigned long loop_length = 0;
curr = start->links[0];
prev = start;
start->part_of_loop = 1;
while (curr != start) {
curr->part_of_loop = 1;
loop_length++;
for (int i = 0; i < 2; i++) {
if (prev != curr->links[i]) {
prev = curr;
curr = curr->links[i];
break;
}
}
}
unsigned long max_distance = loop_length % 2 ? loop_length / 2 + 1 : loop_length / 2;
printf("%lu\n", max_distance);
unsigned long inside_tile_count = 0;
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
if (map[j][i].part_of_loop) {
continue;
}
// Start going in a specific direction. (in this case right)
// If we are inside the pipes we will cross the pipe an odd number of times
int crosses = 0;
// If we entered a pipe through F or L we have to keep track whether we cross the pipe when leaving
int entry = 0;
for (int k = 1; k < x - j; k++) {
// We only care about pipes that are part of the loop
if (!map[j+k][i].part_of_loop) {
continue;
}
// If we are 'inside a pipe' we are no crossing it
tile_type_t tile_type = map[j+k][i].type;
if (tile_type == LEFT_RIGHT) {
continue;
}
// Entering the loop. We are not crossing it yet, it depends on the exit tile
if (tile_type == DOWN_RIGHT || tile_type == UP_RIGHT) {
if (tile_type == DOWN_RIGHT) {
entry = 1;
} else {
entry = 2;
}
continue;
}
// Vertical pipe, we are crossing the loop
if (tile_type == UP_DOWN) {
crosses += 1;
entry = 0;
continue;
}
// Exiting loop, check whether we crossed
if (tile_type == DOWN_LEFT || tile_type == UP_LEFT) {
if ((tile_type == DOWN_LEFT && entry == 2) || (tile_type == UP_LEFT && entry == 1)) {
crosses += 1;
}
entry = 0;
continue;
}
}
if (crosses % 2) {
inside_tile_count++;
}
}
}
printf("%lu\n", inside_tile_count);
free(buf);
}