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