From 1936f63d47fbf6aadb2570809837a1418c3e86cf Mon Sep 17 00:00:00 2001 From: Eric Mertens Date: Thu, 3 Nov 2022 08:15:17 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + CMakeLists.txt | 21 ++++++++++ day02.cpp | 29 +++++++++++++ day05.cpp | 23 +++++++++++ day07.cpp | 78 ++++++++++++++++++++++++++++++++++ day09.cpp | 25 +++++++++++ lib/CMakeLists.txt | 2 + lib/include/intcode.hpp | 49 ++++++++++++++++++++++ lib/intcode.cpp | 92 +++++++++++++++++++++++++++++++++++++++++ 9 files changed, 320 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 day02.cpp create mode 100644 day05.cpp create mode 100644 day07.cpp create mode 100644 day09.cpp create mode 100644 lib/CMakeLists.txt create mode 100644 lib/include/intcode.hpp create mode 100644 lib/intcode.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3b04fe9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,21 @@ +cmake_minimum_required(VERSION 3.13) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 20) +project(aocpp19 + VERSION 1 + LANGUAGES C CXX +) + +add_subdirectory(lib) + +add_executable(day02 day02.cpp) +target_link_libraries(day02 intcode) + +add_executable(day05 day05.cpp) +target_link_libraries(day05 intcode) + +add_executable(day07 day07.cpp) +target_link_libraries(day07 intcode) + +add_executable(day09 day09.cpp) +target_link_libraries(day09 intcode) \ No newline at end of file diff --git a/day02.cpp b/day02.cpp new file mode 100644 index 0000000..7a11e75 --- /dev/null +++ b/day02.cpp @@ -0,0 +1,29 @@ +#include +#include + +#include + +namespace { + +auto compute(intcode machine, std::int64_t x, std::int64_t y) { + machine.at(1) = x; + machine.at(2) = y; + machine.step(); + return machine.at(0); +} + +} + +auto main() -> int { + auto machine = intcode{parse_stream(std::cin)}; + + std::cout << "Part 1: " << compute(machine, 12, 2) << std::endl; + + for (std::int64_t i = 0; i < 100; i++) { + for (std::int64_t j = 0; j < 100; j++) { + if (19690720 == compute(machine, i, j)) { + std::cout << "Part 2: " << 100*i+j << std::endl; + } + } + } +} \ No newline at end of file diff --git a/day05.cpp b/day05.cpp new file mode 100644 index 0000000..528aacd --- /dev/null +++ b/day05.cpp @@ -0,0 +1,23 @@ +#include +#include + +#include + +namespace { +auto compute(intcode machine, std::int64_t d) -> std::int64_t { + std::int64_t last_output = -1; + while (std::visit(overloaded { + [](Halt) { return false; }, + [d, &machine](Input arg) { arg.pos = d; return true; }, + [&last_output](Output arg) { last_output = arg.val; return true; } + }, machine.step())); + return last_output; +} +} + +auto main() -> int { + auto program = parse_stream(std::cin); + auto machine = intcode{std::move(program)}; + std::cout << "Part 1: " << compute(machine, 1) << std::endl; + std::cout << "Part 2: " << compute(std::move(machine), 5) << std::endl; +} \ No newline at end of file diff --git a/day07.cpp b/day07.cpp new file mode 100644 index 0000000..9d63194 --- /dev/null +++ b/day07.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include + +namespace { +auto compute(intcode machine, std::vector const& params) -> std::int64_t { + + std::vector amps; + + for (auto p : params) { + auto m = machine; + auto i = std::get(m.step()); + i.pos = p; + amps.emplace_back(std::move(m)); + } + + std::int64_t prev = 0; + + for (auto& m : amps) { + auto i = std::get(m.step()); + i.pos = prev; + auto o = std::get(m.step()); + prev = o.val; + } + + return prev; +} +auto compute2(intcode machine, std::vector const& params) -> std::int64_t { + + std::vector amps; + + for (auto p : params) { + auto m = machine; + auto i = std::get(m.step()); + i.pos = p; + amps.emplace_back(std::move(m)); + } + + std::int64_t last = 0; + std::int64_t prev = 0; + + for(;;) { + for (auto& m : amps) { + auto i = m.step(); + if (auto p = std::get_if(&i)) { + p->pos = prev; + prev = std::get(m.step()).val; + } else { + return last; + } + } + last = prev; + } +} +} + +auto main() -> int { + auto machine = intcode{parse_stream(std::cin)}; + { + std::vector params {0,1,2,3,4}; + std::int64_t best = 0; + do { + best = std::max(best, compute(machine, params)); + } while (std::next_permutation(params.begin(), params.end())); + std::cout << "Part 1: " << best << std::endl; + } + { + std::vector params {5,6,7,8,9}; + std::int64_t best = 0; + do { + best = std::max(best, compute2(machine, params)); + } while (std::next_permutation(params.begin(), params.end())); + std::cout << "Part 2: " << best << std::endl; + } +} \ No newline at end of file diff --git a/day09.cpp b/day09.cpp new file mode 100644 index 0000000..a8ab42b --- /dev/null +++ b/day09.cpp @@ -0,0 +1,25 @@ +#include +#include + +#include + +namespace { + +auto compute(intcode machine, std::int64_t d) -> std::int64_t { + std::int64_t output = -1; + while (std::visit(overloaded { + [](Halt) { return false; }, + [d, &machine](Input arg) { arg.pos = d; return true; }, + [&output](Output arg) { output = arg.val; return false; } + }, machine.step())); + return output; +} + +} + +auto main() -> int { + auto program = parse_stream(std::cin); + auto machine = intcode{std::move(program)}; + std::cout << "Part 1: " << compute(machine, 1) << std::endl; + std::cout << "Part 2: " << compute(std::move(machine), 2) << std::endl; +} \ No newline at end of file diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..047637c --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(intcode intcode.cpp) +target_include_directories(intcode PUBLIC include) \ No newline at end of file diff --git a/lib/include/intcode.hpp b/lib/include/intcode.hpp new file mode 100644 index 0000000..6c86cd2 --- /dev/null +++ b/lib/include/intcode.hpp @@ -0,0 +1,49 @@ +#ifndef INTCODE_HPP_ +#define INTCODE_HPP_ + +#include +#include +#include +#include +#include +#include + +template struct overloaded : Ts... { using Ts::operator()...; }; +template overloaded(Ts...) -> overloaded; + +struct BadInstruction : public std::exception { + std::int64_t instruction; + explicit BadInstruction(std::int64_t instruction) : instruction{instruction} {} + const char* what() const noexcept override { + return "bad instruction"; + } +}; + +struct Input { + std::int64_t& pos; +}; + +struct Output { + std::int64_t val; +}; + +struct Halt {}; + +class intcode { + std::vector rom_; + std::unordered_map ram_; + std::size_t pc_; + std::size_t base_; + + auto ref(std::int64_t instruction, std::int64_t p, std::size_t offset) -> std::int64_t&; + +public: + intcode(); + intcode(std::vector ram); + auto step() -> std::variant; + auto at(std::size_t) -> std::int64_t&; +}; + +auto parse_stream(std::istream& in) -> std::vector; + +#endif // INTCODE_HPP_ \ No newline at end of file diff --git a/lib/intcode.cpp b/lib/intcode.cpp new file mode 100644 index 0000000..420c147 --- /dev/null +++ b/lib/intcode.cpp @@ -0,0 +1,92 @@ +#include "intcode.hpp" +#include + +intcode::intcode() : rom_{}, ram_{}, pc_{0}, base_{0} {} + +intcode::intcode(std::vector ram) : rom_{ram}, ram_{}, pc_{0}, base_{0} {} + +auto intcode::ref(std::int64_t instruction, std::int64_t p, std::size_t offset) -> std::int64_t& { + auto& i = at(pc_ + offset); + switch (instruction / p % 10) { + case 0: return at(i); + case 1: return i; + case 2: return at(base_ + i); + default: throw BadInstruction{instruction}; + } +} + +auto intcode::at(std::size_t i) -> std::int64_t& { + return i < rom_.size() ? rom_[i] : ram_[i]; +} + +auto intcode::step() -> std::variant { + for (;;) { + auto instruction = at(pc_); + auto a = [this,instruction]() -> std::int64_t& { return ref(instruction, 100, 1); }; + auto b = [this,instruction]() -> std::int64_t& { return ref(instruction, 1000, 2); }; + auto c = [this,instruction]() -> std::int64_t& { return ref(instruction, 10000, 3); }; + + switch (instruction % 100) { + case 1: + c() = a() + b(); + pc_ += 4; + break; + + case 2: + c() = a() * b(); + pc_ += 4; + break; + + case 3: { + auto& pos = a(); + pc_ += 2; + return Input{pos}; + } + + case 4: { + auto val = a(); + pc_ += 2; + return Output{val}; + } + + case 5: + pc_ = a() ? b() : pc_ + 3; + break; + + case 6: + pc_ = a() ? pc_ + 3 : b(); + break; + + case 7: + c() = a() < b(); + pc_ += 4; + break; + + case 8: + c() = a() == b(); + pc_ += 4; + break; + + case 9: + base_ += a(); + pc_ += 2; + break; + + case 99: + return Halt{}; + + default: + throw BadInstruction{instruction}; + } + } +} + +auto parse_stream(std::istream& in) -> std::vector { + std::int64_t x; + std::string str; + std::vector result; + while(std::getline(in, str, ',')) { + result.push_back(std::stoi(str)); + } + return result; +} \ No newline at end of file