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