From ce990c3026b6556d2649d11ab4ec46d541ec7c67 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 24 Dec 2023 13:39:26 +0200 Subject: [PATCH] AOC2023: Implement day20 part1 --- userspace/aoc2023/CMakeLists.txt | 1 + userspace/aoc2023/day20/CMakeLists.txt | 22 +++ userspace/aoc2023/day20/main.cpp | 189 +++++++++++++++++++++++++ userspace/aoc2023/full/main.cpp | 2 +- 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 userspace/aoc2023/day20/CMakeLists.txt create mode 100644 userspace/aoc2023/day20/main.cpp diff --git a/userspace/aoc2023/CMakeLists.txt b/userspace/aoc2023/CMakeLists.txt index 011b9e164c..8411a87811 100644 --- a/userspace/aoc2023/CMakeLists.txt +++ b/userspace/aoc2023/CMakeLists.txt @@ -22,6 +22,7 @@ set(AOC2023_PROJECTS day17 day18 day19 + day20 full ) diff --git a/userspace/aoc2023/day20/CMakeLists.txt b/userspace/aoc2023/day20/CMakeLists.txt new file mode 100644 index 0000000000..ee0430fc15 --- /dev/null +++ b/userspace/aoc2023/day20/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.26) + +project(aoc2023_day20 CXX) + +set(SOURCES + main.cpp +) + +add_executable(aoc2023_day20 ${SOURCES}) +target_compile_options(aoc2023_day20 PUBLIC -O2 -g) +target_link_libraries(aoc2023_day20 PUBLIC libc ban) + +add_dependencies(aoc2023_day20 libc-install ban-install) + +add_custom_target(aoc2023_day20-install + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/aoc2023_day20 ${BANAN_AOC2023_BIN}/day20 + DEPENDS aoc2023_day20 + DEPENDS aoc2023_always +) + +add_dependencies(aoc2023 aoc2023_day20) +add_dependencies(aoc2023-install aoc2023_day20-install) diff --git a/userspace/aoc2023/day20/main.cpp b/userspace/aoc2023/day20/main.cpp new file mode 100644 index 0000000000..a40f5b31d2 --- /dev/null +++ b/userspace/aoc2023/day20/main.cpp @@ -0,0 +1,189 @@ +#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 u8 = uint8_t; +using u16 = uint16_t; +using u32 = uint32_t; +using u64 = uint64_t; + +struct Signal +{ + BAN::String target; + BAN::String sender; + bool high; +}; + +struct Module +{ + BAN::String name; + BAN::Vector targets; + + virtual void handle_signal(const Signal& signal, BAN::Queue& signal_queue) = 0; +}; + +struct BroadcasterModule : public Module +{ + void handle_signal(const Signal& signal, BAN::Queue& signal_queue) override + { + for (const auto& target : targets) + MUST(signal_queue.push({ target, name, signal.high })); + } +}; + +struct FlipFlopModule : public Module +{ + bool is_on { false }; + + void handle_signal(const Signal& signal, BAN::Queue& signal_queue) override + { + if (signal.high) + return; + is_on = !is_on; + for (const auto& target : targets) + MUST(signal_queue.push({ target, name, is_on })); + } +}; + +struct ConjunctionModule : public Module +{ + BAN::HashMap inputs; + + void handle_signal(const Signal& signal, BAN::Queue& signal_queue) override + { + inputs[signal.sender] = signal.high; + bool send_value = false; + for (const auto& input : inputs) + if (!input.value) + send_value = true; + for (const auto& target : targets) + MUST(signal_queue.push({ target, name, send_value })); + } +}; + +BAN::HashMapUnstable> parse_modules(FILE* fp) +{ + BAN::HashMapUnstable> modules; + + char buffer[128]; + 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; + + BAN::UniqPtr module; + if (line.front() == '%') + { + module = MUST(BAN::UniqPtr::create()); + line = line.substring(1); + } + else if (line.front() == '&') + { + module = MUST(BAN::UniqPtr::create()); + line = line.substring(1); + } + else + { + module = MUST(BAN::UniqPtr::create()); + } + + auto name_targets = MUST(line.split('>')); + auto name = name_targets[0].substring(0, name_targets[0].size() - 2); + auto target_strs = MUST(name_targets[1].split(',')); + + for (auto target : target_strs) + MUST(module->targets.emplace_back(target.substring(1))); + + module->name = BAN::String(name); + MUST(modules.insert(module->name, BAN::move(module))); + } + + for (auto& [name, module] : modules) + { + for (auto& target : module->targets) + { + if (!modules.contains(target)) + continue; + if (auto* ptr = dynamic_cast(modules[target].ptr())) + MUST(ptr->inputs.insert(name, false)); + } + } + + return modules; +} + +i64 puzzle1(FILE* fp) +{ + auto modules = parse_modules(fp); + + BAN::Queue signal_queue; + + i64 sent_hi = 0; + i64 sent_lo = 0; + + for (size_t i = 0; i < 1000; i++) + { + MUST(signal_queue.push({ "broadcaster"sv, ""sv, false })); + while (!signal_queue.empty()) + { + auto signal = signal_queue.front(); + signal_queue.pop(); + + if (signal.high) + sent_hi++; + else + sent_lo++; + + if (!modules.contains(signal.target)) + continue; + + auto& module = modules[signal.target]; + module->handle_signal(signal, signal_queue); + } + } + + return sent_hi * sent_lo; +} + +i64 puzzle2(FILE* fp) +{ + (void)fp; + return -1; +} + +int main(int argc, char** argv) +{ + const char* file_path = "/usr/share/aoc2023/day20_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 1e383a0933..c9371ecef7 100644 --- a/userspace/aoc2023/full/main.cpp +++ b/userspace/aoc2023/full/main.cpp @@ -4,7 +4,7 @@ int main() { - for (int i = 1; i <= 19; i++) + for (int i = 1; i <= 20; i++) { printf("day %d:\n", i);