From 36590fb5c769199cdfa9fa0256308dfb826f55b4 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 24 Dec 2023 14:58:21 +0200 Subject: [PATCH] AOC2023: Implement day21 part1 --- userspace/aoc2023/CMakeLists.txt | 1 + userspace/aoc2023/day21/CMakeLists.txt | 22 ++++ userspace/aoc2023/day21/main.cpp | 155 +++++++++++++++++++++++++ userspace/aoc2023/full/main.cpp | 2 +- 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 userspace/aoc2023/day21/CMakeLists.txt create mode 100644 userspace/aoc2023/day21/main.cpp diff --git a/userspace/aoc2023/CMakeLists.txt b/userspace/aoc2023/CMakeLists.txt index 8411a87811..e76083f841 100644 --- a/userspace/aoc2023/CMakeLists.txt +++ b/userspace/aoc2023/CMakeLists.txt @@ -23,6 +23,7 @@ set(AOC2023_PROJECTS day18 day19 day20 + day21 full ) diff --git a/userspace/aoc2023/day21/CMakeLists.txt b/userspace/aoc2023/day21/CMakeLists.txt new file mode 100644 index 0000000000..aaa6ec5ed3 --- /dev/null +++ b/userspace/aoc2023/day21/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.26) + +project(aoc2023_day21 CXX) + +set(SOURCES + main.cpp +) + +add_executable(aoc2023_day21 ${SOURCES}) +target_compile_options(aoc2023_day21 PUBLIC -O2 -g) +target_link_libraries(aoc2023_day21 PUBLIC libc ban) + +add_dependencies(aoc2023_day21 libc-install ban-install) + +add_custom_target(aoc2023_day21-install + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/aoc2023_day21 ${BANAN_AOC2023_BIN}/day21 + DEPENDS aoc2023_day21 + DEPENDS aoc2023_always +) + +add_dependencies(aoc2023 aoc2023_day21) +add_dependencies(aoc2023-install aoc2023_day21-install) diff --git a/userspace/aoc2023/day21/main.cpp b/userspace/aoc2023/day21/main.cpp new file mode 100644 index 0000000000..a037cf1aaf --- /dev/null +++ b/userspace/aoc2023/day21/main.cpp @@ -0,0 +1,155 @@ +#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; + +enum class Tile { Free, Rock }; + +struct Position +{ + i64 x; + i64 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; + } +}; + +namespace BAN +{ + template<> + struct hash + { + hash_t operator()(const Position& position) const + { + return hash()(((u64)position.x << 32) | (u64)position.y); + } + }; +} + +struct Garden +{ + Position start; + BAN::Vector> tiles; +}; + +Garden parse_garden(FILE* fp) +{ + Garden garden; + + i64 row = 0; + + 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(garden.tiles.emplace_back(line.size(), Tile::Free)); + for (size_t i = 0; i < line.size(); i++) + { + if (line[i] == '#') + garden.tiles.back()[i] = Tile::Rock; + if (line[i] == 'S') + garden.start = { .x = (i64)i, .y = row }; + } + + row++; + } + + return garden; +} + +i64 puzzle1(FILE* fp) +{ + auto garden = parse_garden(fp); + + BAN::HashSetUnstable visited, reachable, pending; + MUST(pending.insert(garden.start)); + + for (i32 i = 0; i <= 64; i++) + { + auto temp = BAN::move(pending); + pending = BAN::HashSetUnstable(); + + while (!temp.empty()) + { + auto position = *temp.begin(); + temp.remove(position); + + MUST(visited.insert(position)); + if (i % 2 == 0) + MUST(reachable.insert(position)); + + Position offsets[4] { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; + for (i32 j = 0; j < 4; j++) + { + auto next = position + offsets[j]; + if (next.y < 0 || next.y >= (i64)garden.tiles.size()) + continue; + if (next.x < 0 || next.x >= (i64)garden.tiles[0].size()) + continue; + if (garden.tiles[next.y][next.x] == Tile::Rock) + continue; + if (visited.contains(next)) + continue; + MUST(pending.insert(next)); + } + } + } + + return reachable.size(); +} + +i64 puzzle2(FILE* fp) +{ + (void)fp; + return -1; +} + +int main(int argc, char** argv) +{ + const char* file_path = "/usr/share/aoc2023/day21_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 c9371ecef7..a4a37288c0 100644 --- a/userspace/aoc2023/full/main.cpp +++ b/userspace/aoc2023/full/main.cpp @@ -4,7 +4,7 @@ int main() { - for (int i = 1; i <= 20; i++) + for (int i = 1; i <= 21; i++) { printf("day %d:\n", i);