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