diff --git a/userspace/aoc2024/CMakeLists.txt b/userspace/aoc2024/CMakeLists.txt index 366985bb..2fcc438e 100644 --- a/userspace/aoc2024/CMakeLists.txt +++ b/userspace/aoc2024/CMakeLists.txt @@ -12,6 +12,7 @@ set(AOC2024_PROJECTS day11 day12 day13 + day14 full ) diff --git a/userspace/aoc2024/day14/CMakeLists.txt b/userspace/aoc2024/day14/CMakeLists.txt new file mode 100644 index 00000000..7190c796 --- /dev/null +++ b/userspace/aoc2024/day14/CMakeLists.txt @@ -0,0 +1,9 @@ +set(SOURCES + main.cpp +) + +add_executable(aoc2024_day14 ${SOURCES}) +banan_include_headers(aoc2024_day14 ban) +banan_link_library(aoc2024_day14 libc) + +install(TARGETS aoc2024_day14 OPTIONAL) diff --git a/userspace/aoc2024/day14/main.cpp b/userspace/aoc2024/day14/main.cpp new file mode 100644 index 00000000..db0cdffd --- /dev/null +++ b/userspace/aoc2024/day14/main.cpp @@ -0,0 +1,152 @@ +#include +#include + +#include +#include +#include +#include +#include +#include + +using i8 = int8_t; +using i16 = int16_t; +using i32 = int32_t; +using i64 = int64_t; +using isize = ssize_t; + +using u8 = uint8_t; +using u16 = uint16_t; +using u32 = uint32_t; +using u64 = uint64_t; +using usize = size_t; + +i64 part1(FILE* fp) +{ + i32 quadrants[4] {}; + + for (;;) + { + i32 px, py, vx, vy; + if (fscanf(fp, "p=%" SCNd32 ",%" SCNd32 " v=%" SCNd32 ",%" SCNd32 "\n", &px, &py, &vx, &vy) != 4) + break; + + const i32 tx = (((px + 100 * vx) % 101) + 101) % 101; + const i32 ty = (((py + 100 * vy) % 103) + 103) % 103; + + if (tx < 50 && ty < 51) + quadrants[0]++; + if (tx > 50 && ty < 51) + quadrants[1]++; + if (tx < 50 && ty > 51) + quadrants[2]++; + if (tx > 50 && ty > 51) + quadrants[3]++; + } + + return quadrants[0] * quadrants[1] * quadrants[2] * quadrants[3]; +} + +struct Robot +{ + i32 px, py; + i32 vx, vy; +}; + +usize largest_area(const BAN::Vector& robots) +{ + BAN::Array robot_map(false); + for (const auto& robot : robots) + robot_map[robot.py * 101 + robot.px] = true; + + BAN::Array checked(false); + + usize result = 0; + for (i32 y = 0; y < 103; y++) + { + for (i32 x = 0; x < 101; x++) + { + if (checked[y * 101 + x]) + continue; + if (!robot_map[y * 101 + x]) + continue; + + struct Position { i32 x, y; }; + BAN::Vector to_check; + MUST(to_check.reserve(101 * 103)); + + MUST(to_check.emplace_back(x, y)); + + usize area = 0; + while (!to_check.empty()) + { + const auto pos = to_check.back(); + to_check.pop_back(); + + if (checked[pos.y * 101 + pos.x]) + continue; + checked[pos.y * 101 + pos.x] = true; + + if (!robot_map[pos.y * 101 + pos.x]) + continue; + + area++; + + if (pos.x - 1 >= 0) MUST(to_check.emplace_back(pos.x - 1, pos.y )); + if (pos.x + 1 < 101) MUST(to_check.emplace_back(pos.x + 1, pos.y )); + if (pos.y - 1 >= 0) MUST(to_check.emplace_back(pos.x, pos.y - 1)); + if (pos.y + 1 < 103) MUST(to_check.emplace_back(pos.x, pos.y + 1)); + } + + result = BAN::Math::max(result, area); + } + } + + return result; +} + +i64 part2(FILE* fp) +{ + BAN::Vector robots; + + for (;;) + { + i32 px, py, vx, vy; + if (fscanf(fp, "p=%" SCNd32 ",%" SCNd32 " v=%" SCNd32 ",%" SCNd32 "\n", &px, &py, &vx, &vy) != 4) + break; + MUST(robots.emplace_back(px, py, vx, vy)); + } + + for (i64 frame = 0;; frame++) + { + if (largest_area(robots) >= robots.size() / 4) + return frame; + for (auto& robot : robots) + { + robot.px = (((robot.px + robot.vx) % 101) + 101) % 101; + robot.py = (((robot.py + robot.vy) % 103) + 103) % 103; + } + } +} + +int main(int argc, char** argv) +{ + const char* file_path = "/usr/share/aoc2024/day14_input.txt"; + + if (argc >= 2) + file_path = argv[1]; + + FILE* fp = fopen(file_path, "r"); + if (fp == nullptr) + { + perror("fopen"); + return 1; + } + + printf("part1: %" PRId64 "\n", part1(fp)); + + fseek(fp, 0, SEEK_SET); + + printf("part2: %" PRId64 "\n", part2(fp)); + + fclose(fp); +}