diff --git a/userspace/aoc2023/CMakeLists.txt b/userspace/aoc2023/CMakeLists.txt index e76083f841..7e8f9b5c53 100644 --- a/userspace/aoc2023/CMakeLists.txt +++ b/userspace/aoc2023/CMakeLists.txt @@ -24,6 +24,7 @@ set(AOC2023_PROJECTS day19 day20 day21 + day23 full ) diff --git a/userspace/aoc2023/day23/CMakeLists.txt b/userspace/aoc2023/day23/CMakeLists.txt new file mode 100644 index 0000000000..d27f82bf2a --- /dev/null +++ b/userspace/aoc2023/day23/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.26) + +project(aoc2023_day23 CXX) + +set(SOURCES + main.cpp +) + +add_executable(aoc2023_day23 ${SOURCES}) +target_compile_options(aoc2023_day23 PUBLIC -O2 -g) +target_link_libraries(aoc2023_day23 PUBLIC libc ban) + +add_dependencies(aoc2023_day23 libc-install ban-install) + +add_custom_target(aoc2023_day23-install + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/aoc2023_day23 ${BANAN_AOC2023_BIN}/day23 + DEPENDS aoc2023_day23 + DEPENDS aoc2023_always +) + +add_dependencies(aoc2023 aoc2023_day23) +add_dependencies(aoc2023-install aoc2023_day23-install) diff --git a/userspace/aoc2023/day23/main.cpp b/userspace/aoc2023/day23/main.cpp new file mode 100644 index 0000000000..60521ae2f6 --- /dev/null +++ b/userspace/aoc2023/day23/main.cpp @@ -0,0 +1,156 @@ +#include +#include +#include +#include + +#include +#include +#include + +using i8 = int8_t; +using i16 = int16_t; +using i32 = int32_t; +using i64 = int64_t; + +using u8 = uint8_t; +using u16 = uint16_t; +using u32 = uint32_t; +using u64 = uint64_t; + +BAN::Vector> parse_grid(FILE* fp) +{ + BAN::Vector> grid; + + char buffer[256]; + while (fgets(buffer, sizeof(buffer), fp)) + { + BAN::StringView line(buffer); + ASSERT(line.back() == '\n'); + line = line.substring(0, line.size() - 1); + if (line.empty()) + break; + + MUST(grid.emplace_back(line.size(), '\0')); + for (size_t i = 0; i < line.size(); i++) + grid.back()[i] = line[i]; + } + + return grid; +} + +struct Position +{ + i64 x, y; + + Position operator+(const Position& other) const + { + return { .x = x + other.x, .y = y + other.y }; + } + + bool operator==(const Position& other) const + { + return x == other.x && y == other.y; + } +}; + +i64 recurse_grid(BAN::Vector& path, const BAN::Vector>& grid) +{ + const auto entry = path.back(); + BAN::ScopeGuard _([&] { while (path.back() != entry) path.pop_back(); }); + + while (path.back().y < (i64)grid.size() - 1) + { + BAN::Array valid_next; + size_t valid_next_count = 0; + + constexpr Position offsets[4] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; + for (size_t i = 0; i < 4; i++) + { + auto next = path.back() + offsets[i]; + if (next.y < 0 || next.y >= (i64)grid.size()) + continue; + if (next.x < 0 || next.x >= (i64)grid.front().size()) + continue; + switch (grid[next.y][next.x]) + { + case '^': next.y--; break; + case 'v': next.y++; break; + case '<': next.x--; break; + case '>': next.x++; break; + case '#': continue; + } + if (path.contains(next)) + continue; + valid_next[valid_next_count++] = next; + } + + if (valid_next_count == 0) + return 0; + + if (valid_next_count == 1) + { + MUST(path.push_back(valid_next.front())); + continue; + } + + i64 result = 0; + for (size_t i = 0; i < valid_next_count; i++) + { + MUST(path.push_back(valid_next[i])); + result = BAN::Math::max(result, recurse_grid(path, grid)); + path.pop_back(); + } + return result; + } + + i64 result = 0; + for (size_t i = 1; i < path.size(); i++) + result += BAN::Math::abs(path[i - 1].x - path[i].x) + BAN::Math::abs(path[i - 1].y - path[i].y); + return result; +} + +i64 puzzle1(FILE* fp) +{ + auto grid = parse_grid(fp); + + BAN::Vector path; + for (i64 x = 0; x < (i64)grid.front().size(); x++) + { + if (grid.front()[x] == '.') + { + MUST(path.push_back({ .x = x, .y = 0 })); + break; + } + } + + return recurse_grid(path, grid); +} + +i64 puzzle2(FILE* fp) +{ + (void)fp; + return -1; +} + +int main(int argc, char** argv) +{ + const char* file_path = "/usr/share/aoc2023/day23_input.txt"; + + if (argc >= 2) + file_path = argv[1]; + + FILE* fp = fopen(file_path, "r"); + if (fp == nullptr) + { + perror("fopen"); + return 1; + } + + printf("puzzle1: %" PRId64 "\n", puzzle1(fp)); + + fseek(fp, 0, SEEK_SET); + + printf("puzzle2: %" PRId64 "\n", puzzle2(fp)); + + fclose(fp); +} diff --git a/userspace/aoc2023/full/main.cpp b/userspace/aoc2023/full/main.cpp index a4a37288c0..b98090c925 100644 --- a/userspace/aoc2023/full/main.cpp +++ b/userspace/aoc2023/full/main.cpp @@ -4,8 +4,10 @@ int main() { - for (int i = 1; i <= 21; i++) + for (int i = 1; i <= 23; i++) { + if (i == 22) + continue; printf("day %d:\n", i); char command[128];