270 lines
8.6 KiB
C
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);
|
||
|
|
}
|