Day14 C
This commit is contained in:
204
day14/c/day14.c
Normal file
204
day14/c/day14.c
Normal file
@@ -0,0 +1,204 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user