209 lines
6.1 KiB
C
209 lines
6.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define LINE_MAX_LENGTH 256
|
|
|
|
typedef enum tile_type {
|
|
EMPTY,
|
|
MIRROR_LEFT_TO_UP,
|
|
MIRROR_LEFT_TO_DOWN,
|
|
SPLITTER_VERTICAL,
|
|
SPLITTER_HORIZONTAL,
|
|
} tile_type_t;
|
|
|
|
typedef enum light_direction {
|
|
LEFT_TO_RIGHT,
|
|
RIGHT_TO_LEFT,
|
|
UP_TO_DOWN,
|
|
DOWN_TO_UP,
|
|
} light_direction_t;
|
|
|
|
typedef struct tile {
|
|
tile_type_t type;
|
|
light_direction_t lights[4];
|
|
int lights_num;
|
|
} tile_t;
|
|
|
|
void traverse_light(tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y, int entry_x, int entry_y, int dir[2]);
|
|
int has_light(tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y, light_direction_t direction, int max_x, int max_y);
|
|
light_direction_t dir_to_direction(int dir[2]);
|
|
int count_energized(tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y);
|
|
|
|
int main() {
|
|
char *p, *buf, c;
|
|
|
|
buf = (char *)malloc(LINE_MAX_LENGTH);
|
|
memset(buf, 0, LINE_MAX_LENGTH);
|
|
p = buf;
|
|
|
|
tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH];
|
|
memset(map, 0, LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(tile_t));
|
|
int x = 0, y = 0;
|
|
|
|
while ((c = getchar()) != EOF) {
|
|
*p++ = c;
|
|
if (c == '\n') {
|
|
p = buf;
|
|
x = 0;
|
|
|
|
while (*p != '\n') {
|
|
switch (*p) {
|
|
case '.':
|
|
map[x][y].type = EMPTY;
|
|
break;
|
|
case '/':
|
|
map[x][y].type = MIRROR_LEFT_TO_UP;
|
|
break;
|
|
case '\\':
|
|
map[x][y].type = MIRROR_LEFT_TO_DOWN;
|
|
break;
|
|
case '|':
|
|
map[x][y].type = SPLITTER_VERTICAL;
|
|
break;
|
|
case '-':
|
|
map[x][y].type = SPLITTER_HORIZONTAL;
|
|
break;
|
|
}
|
|
x++;
|
|
p++;
|
|
}
|
|
y++;
|
|
memset(buf, 0, LINE_MAX_LENGTH);
|
|
p = buf;
|
|
}
|
|
}
|
|
|
|
tile_t map_cpy[LINE_MAX_LENGTH][LINE_MAX_LENGTH];
|
|
memcpy(map_cpy, map, LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(tile_t));
|
|
|
|
int dir[2] = {1, 0};
|
|
traverse_light(map_cpy, x, y, -1, 0, dir);
|
|
int part1 = count_energized(map_cpy, x, y);
|
|
|
|
int max_energized = 0, energized;
|
|
// LEFT COLUMN
|
|
for (int i = 0; i < y; i++) {
|
|
dir[0] = 1;
|
|
dir[1] = 0;
|
|
memcpy(map_cpy, map, LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(tile_t));
|
|
traverse_light(map_cpy, x, y, -1, i, dir);
|
|
energized = count_energized(map_cpy, x, y);
|
|
|
|
if (energized > max_energized) {
|
|
max_energized = energized;
|
|
}
|
|
}
|
|
// RIGHT COLUMN
|
|
for (int i = 0; i < y; i++) {
|
|
dir[0] = -1;
|
|
dir[1] = 0;
|
|
memcpy(map_cpy, map, LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(tile_t));
|
|
traverse_light(map_cpy, x, y, x, i, dir);
|
|
energized = count_energized(map_cpy, x, y);
|
|
|
|
if (energized > max_energized) {
|
|
max_energized = energized;
|
|
}
|
|
}
|
|
// TOP ROW
|
|
for (int i = 0; i < x; i++) {
|
|
dir[0] = 0;
|
|
dir[1] = 1;
|
|
memcpy(map_cpy, map, LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(tile_t));
|
|
traverse_light(map_cpy, x, y, i, -1, dir);
|
|
energized = count_energized(map_cpy, x, y);
|
|
|
|
if (energized > max_energized) {
|
|
max_energized = energized;
|
|
}
|
|
}
|
|
// BOTTOM ROW
|
|
for (int i = 0; i < x; i++) {
|
|
dir[0] = 0;
|
|
dir[1] = -1;
|
|
memcpy(map_cpy, map, LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(tile_t));
|
|
traverse_light(map_cpy, x, y, i, y, dir);
|
|
energized = count_energized(map_cpy, x, y);
|
|
|
|
if (energized > max_energized) {
|
|
max_energized = energized;
|
|
}
|
|
}
|
|
|
|
printf("%i\n", part1);
|
|
printf("%i\n", max_energized);
|
|
free(buf);
|
|
}
|
|
|
|
void traverse_light(tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y, int entry_x, int entry_y, int dir[2]) {
|
|
light_direction_t curr_direction = dir_to_direction(dir);
|
|
|
|
int curr_x = entry_x, curr_y = entry_y;
|
|
|
|
while (!has_light(map, curr_x + dir[0], curr_y + dir[1], curr_direction, x - 1, y - 1)) {
|
|
curr_x += dir[0];
|
|
curr_y += dir[1];
|
|
map[curr_x][curr_y].lights[map[curr_x][curr_y].lights_num] = curr_direction;
|
|
map[curr_x][curr_y].lights_num++;
|
|
|
|
if (map[curr_x][curr_y].type == MIRROR_LEFT_TO_UP) {
|
|
int tmp = dir[0];
|
|
dir[0] = -dir[1];
|
|
dir[1] = -tmp;
|
|
} else if (map[curr_x][curr_y].type == MIRROR_LEFT_TO_DOWN) {
|
|
int tmp = dir[0];
|
|
dir[0] = dir[1];
|
|
dir[1] = tmp;
|
|
} else if (map[curr_x][curr_y].type == SPLITTER_HORIZONTAL && dir[1] != 0) {
|
|
dir[0] = 1;
|
|
dir[1] = 0;
|
|
int recurse_dir[2] = {-1, 0};
|
|
traverse_light(map, x, y, curr_x, curr_y, recurse_dir);
|
|
} else if (map[curr_x][curr_y].type == SPLITTER_VERTICAL && dir[0] != 0) {
|
|
dir[0] = 0;
|
|
dir[1] = 1;
|
|
int recurse_dir[2] = {0, -1};
|
|
traverse_light(map, x, y, curr_x, curr_y, recurse_dir);
|
|
}
|
|
curr_direction = dir_to_direction(dir);
|
|
}
|
|
}
|
|
|
|
int has_light(tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y, light_direction_t direction, int max_x, int max_y) {
|
|
if (x < 0 || y < 0 || x > max_x || y > max_y) {
|
|
return 1;
|
|
}
|
|
for (int i = 0; i < map[x][y].lights_num; i++) {
|
|
if (map[x][y].lights[i] == direction) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
light_direction_t dir_to_direction(int dir[2]) {
|
|
if (dir[0] == 1) {
|
|
return LEFT_TO_RIGHT;
|
|
} else if (dir[0] == -1) {
|
|
return RIGHT_TO_LEFT;
|
|
} else if (dir[1] == 1) {
|
|
return UP_TO_DOWN;
|
|
}
|
|
return DOWN_TO_UP;
|
|
}
|
|
|
|
int count_energized(tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y) {
|
|
int sum = 0;
|
|
for (int i = 0; i < y; i++) {
|
|
for (int j = 0; j < x; j++) {
|
|
if (map[j][i].lights_num > 0) {
|
|
sum++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return sum;
|
|
}
|