diff --git a/src/day14/solve.c b/src/day14/solve.c index 4899242..b7f2daa 100644 --- a/src/day14/solve.c +++ b/src/day14/solve.c @@ -9,11 +9,23 @@ #include "solve.h" #include "aoc/all.h" +#include +#include + #define MAX_DIM 100 #define ROLLING 'O' #define FIXED_POINT '#' #define EMPTY '.' +typedef struct { + XXH64_hash_t hash; + int cycle; +} Seen; + +#define P +#define T Seen +#include + static char platform[MAX_DIM][MAX_DIM]; static void tilt_north(int rows, int cols) { @@ -22,9 +34,25 @@ static void tilt_north(int rows, int cols) { char c = platform[y][x]; if (c != ROLLING) continue; int new_y = y; - while (new_y >= 1 && platform[new_y - 1][x] == EMPTY) { new_y--; } + while (new_y - 1 >= 0 && platform[new_y - 1][x] == EMPTY) { new_y--; } + if (new_y != y) { + // log_debug("row %d, col %d moves to row %d", y, x, new_y); + platform[new_y][x] = c; + platform[y][x] = EMPTY; + } + } + } +} + +static void tilt_south(int rows, int cols) { + for (int y = rows - 2; y >= 0; y--) { + for (int x = 0; x < cols; x++) { + char c = platform[y][x]; + if (c != ROLLING) continue; + int new_y = y; + while (new_y + 1 < rows && platform[new_y + 1][x] == EMPTY) { new_y++; } if (new_y != y) { - log_debug("row %d, col %d moves to row %d", y, x, new_y); + // log_debug("row %d, col %d moves to row %d", y, x, new_y); platform[new_y][x] = c; platform[y][x] = EMPTY; } @@ -32,6 +60,38 @@ static void tilt_north(int rows, int cols) { } } +static void tilt_east(int rows, int cols) { + for (int x = cols - 2; x >= 0; x--) { + for (int y = 0; y < rows; y++) { + char c = platform[y][x]; + if (c != ROLLING) continue; + int new_x = x; + while (new_x + 1 < cols && platform[y][new_x + 1] == EMPTY) { new_x++; } + if (new_x != x) { + // log_debug("row %d, col %d moves to col %d", y, x, new_x); + platform[y][new_x] = c; + platform[y][x] = EMPTY; + } + } + } +} + +static void tilt_west(int rows, int cols) { + for (int x = 1; x < cols; x++) { + for (int y = 0; y < rows; y++) { + char c = platform[y][x]; + if (c != ROLLING) continue; + int new_x = x; + while (new_x - 1 >= 0 && platform[y][new_x - 1] == EMPTY) { new_x--; } + if (new_x != x) { + // log_debug("row %d, col %d moves to col %d", y, x, new_x); + platform[y][new_x] = c; + platform[y][x] = EMPTY; + } + } + } +} + static i64 compute_total_load(int rows, int cols) { i64 result = 0; for (int y = 0; y < rows; y++) { @@ -50,6 +110,12 @@ static void print_platform(int rows, int cols) { } } +static inline XXH64_hash_t hash_platform(int rows, int cols) { return XXH3_64bits(&platform[0][0], rows * cols); } + +static size_t hash_helper(Seen *s) { return s->hash; } + +static int equal_helper(Seen *lhs, Seen *rhs) { return lhs->hash == rhs->hash; } + void solve(const char *buf, size_t buf_size, Solution *result) { size_t pos = 0; int rows, cols; @@ -68,10 +134,33 @@ void solve(const char *buf, size_t buf_size, Solution *result) { rows = y; } - tilt_north(rows, cols); - i64 part1, part2 = 0; - part1 = compute_total_load(rows, cols); + + int total_cycles = 1000000000; + // TODO: find repeating pattern + + _cleanup_(ust_Seen_free) ust_Seen seen = ust_Seen_init(hash_helper, equal_helper); + + for (int cycle = 1; cycle <= 1000000; cycle++) { + tilt_north(rows, cols); + if (cycle == 1) { part1 = compute_total_load(rows, cols); } + + tilt_west(rows, cols); + tilt_south(rows, cols); + tilt_east(rows, cols); + + if (cycle == 175) print_platform(rows, cols); + + Seen s = {.hash = hash_platform(rows, cols), .cycle = cycle}; + ust_Seen_node *node = ust_Seen_find(&seen, s); + if (node != NULL) { + printf("cycle %d collides with entry from cycle %d\n", cycle, node->key.cycle); + break; + } + ust_Seen_insert(&seen, s); + } + + print_platform(rows, cols); snprintf(result->part1, sizeof(result->part1), "%ld", part1); snprintf(result->part2, sizeof(result->part2), "%ld", part2); diff --git a/src/day14/solve_test.c b/src/day14/solve_test.c index ba0dc67..66cd8f8 100644 --- a/src/day14/solve_test.c +++ b/src/day14/solve_test.c @@ -25,7 +25,7 @@ O.#..O.#.#\n\ Solution solution; solve(buf, strlen(buf), &solution); ASSERT_STR("136", solution.part1); - // ASSERT_STR("0", solution.part2); + ASSERT_STR("64", solution.part2); } #ifdef HAVE_INPUTS