Files
adventofcode2023/day14/c/day14.c
2023-12-18 20:26:51 +01:00

205 lines
5.2 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_MAX_LENGTH 256
#define MAX_ROUNDED_ROCKS 8*1024
#define MAX_HISTORY_SIZE 2048
#define abs(a) ((a) > 0 ? (a) : -(a))
#define CYCLES 1000000000
typedef enum tile {
EMPTY,
ROUNDED_ROCK,
CUBE_ROCK,
} tile_t;
typedef struct position {
int x;
int y;
} position_t;
void tilt(tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y, int dir[2]);
int main() {
char *p, *buf, c;
buf = (char *)malloc(LINE_MAX_LENGTH);
memset(buf, 0, LINE_MAX_LENGTH);
p = buf;
position_t rocks[MAX_ROUNDED_ROCKS];
int rocks_num = 0, x = 0, y = 0;
tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH];
while ((c = getchar()) != EOF) {
*p++ = c;
if (c == '\n') {
x = 0;
p = buf;
while (*p != '\n') {
switch (*p) {
case '.':
map[x][y] = EMPTY;
break;
case '#':
map[x][y] = CUBE_ROCK;
break;
case 'O':
map[x][y] = ROUNDED_ROCK;
rocks[rocks_num].x = x;
rocks[rocks_num].y = y;
rocks_num++;
break;
}
p++;
x++;
}
y++;
memset(buf, 0, LINE_MAX_LENGTH);
p = buf;
}
}
int dir[2] = {0, -1};
tilt(map, x, y, dir);
int part1 = 0;
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
if (map[j][i] == ROUNDED_ROCK) {
part1 += y - i;
}
}
}
printf("%i\n", part1);
tile_t ***history = (tile_t***)malloc(MAX_HISTORY_SIZE * sizeof(tile_t**));
for (int i = 0; i < MAX_HISTORY_SIZE; i++) {
history[i] = malloc(LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(tile_t));
}
int history_num = 0;
int offset = 0, period = 0;
for (int i = 0; i < CYCLES; i++) {
int found = 0;
for (int j = 0; j < history_num; j++) {
if (!memcmp(map, history[j], LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(tile_t))) {
offset = j;
period = history_num - j;
found = 1;
break;
}
}
if (!found) {
memcpy(history[history_num], map, LINE_MAX_LENGTH * LINE_MAX_LENGTH * sizeof(tile_t));
history_num++;
}
if (found) {
break;
}
if (i != 0) {
dir[0] = 0;
dir[1] = -1;
tilt(map, x, y, dir);
}
dir[0] = -1;
dir[1] = 0;
tilt(map, x, y, dir);
dir[0] = 0;
dir[1] = 1;
tilt(map, x, y, dir);
dir[0] = 1;
dir[1] = 0;
tilt(map, x, y, dir);
}
for (int i = 0; i < (CYCLES - history_num) % period; i++) {
dir[0] = 0;
dir[1] = -1;
tilt(map, x, y, dir);
dir[0] = -1;
dir[1] = 0;
tilt(map, x, y, dir);
dir[0] = 0;
dir[1] = 1;
tilt(map, x, y, dir);
dir[0] = 1;
dir[1] = 0;
tilt(map, x, y, dir);
}
int part2 = 0;
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
if (map[j][i] == ROUNDED_ROCK) {
part2 += y - i;
}
}
}
printf("%i\n", part2);
for (int i = 0; i < MAX_HISTORY_SIZE; i++) {
free(history[i]);
}
free(history);
free(buf);
}
void tilt(tile_t map[LINE_MAX_LENGTH][LINE_MAX_LENGTH], int x, int y, int dir[2]) {
position_t start;
int *iterate, iter_length;
if (dir[0] == 1) {
start.x = x - 1;
start.y = 0;
iterate = &start.y;
iter_length = y;
} else if (dir[0] == -1) {
start.x = 0;
start.y = 0;
iterate = &start.y;
iter_length = y;
} else if (dir[1] == 1) {
start.x = 0;
start.y = y - 1;
iterate = &start.x;
iter_length = x;
} else if (dir[1] == -1) {
start.x = 0;
start.y = 0;
iterate = &start.x;
iter_length = x;
}
position_t to_put;
for (int i = 0; i < iter_length; i++) {
*iterate = i;
memcpy(&to_put, &start, sizeof(position_t));
int *iterate_secondary = iter_length == x ? &to_put.y : &to_put.x, iter_length_secondary = iter_length == x ? y : x;
for (int j = 0; j < iter_length_secondary; j++) {
int cx = start.x - dir[0] * j;
int cy = start.y - dir[1] * j;
tile_t current_tile = map[cx][cy];
switch (current_tile) {
case EMPTY:
break;
case ROUNDED_ROCK:
map[cx][cy] = EMPTY;
map[to_put.x][to_put.y] = ROUNDED_ROCK;
to_put.x -= dir[0];
to_put.y -= dir[1];
break;
case CUBE_ROCK:
to_put.x = cx - dir[0];
to_put.y = cy - dir[1];
break;
}
}
}
}