Day10 C
This commit is contained in:
BIN
day10/c/day10
Executable file
BIN
day10/c/day10
Executable file
Binary file not shown.
269
day10/c/day10.c
Normal file
269
day10/c/day10.c
Normal file
@@ -0,0 +1,269 @@
|
||||
#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);
|
||||
}
|
||||
Reference in New Issue
Block a user