From 40f58503dce2049598cce3bacc62bd8e7b87853c Mon Sep 17 00:00:00 2001 From: Eric Mertens Date: Thu, 3 Nov 2022 12:53:10 -0700 Subject: [PATCH] checkpoint --- compile_commands.json | 1 + day02.cpp | 32 ++++---- day05.cpp | 36 +++++---- day07.cpp | 114 +++++++++++++--------------- day09.cpp | 34 +++++---- lib/include/intcode.hpp | 69 +++++++++-------- lib/intcode.cpp | 163 ++++++++++++++++++++++------------------ 7 files changed, 238 insertions(+), 211 deletions(-) create mode 120000 compile_commands.json diff --git a/compile_commands.json b/compile_commands.json new file mode 120000 index 0000000..25eb4b2 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1 @@ +build/compile_commands.json \ No newline at end of file diff --git a/day02.cpp b/day02.cpp index 7a11e75..52f11b2 100644 --- a/day02.cpp +++ b/day02.cpp @@ -3,27 +3,29 @@ #include +using namespace intcode; + 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 compute(Machine machine, value_type x, value_type y) { + machine.at(1) = x; + machine.at(2) = y; + machine.step(); + return machine.at(0); } -} +} // namespace auto main() -> int { - auto machine = intcode{parse_stream(std::cin)}; + auto machine = Machine{parse_stream(std::cin)}; - std::cout << "Part 1: " << compute(machine, 12, 2) << std::endl; + 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; - } - } + 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 index 528aacd..8e7ebe9 100644 --- a/day05.cpp +++ b/day05.cpp @@ -2,22 +2,30 @@ #include #include +using namespace intcode; 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 compute(Machine machine, value_type d) -> value_type { + value_type 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; } +} // namespace + 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 + auto machine = Machine{parse_stream(std::cin)}; + std::cout << "Part 1: " << compute(machine, 1) << std::endl; + std::cout << "Part 2: " << compute(std::move(machine), 5) << std::endl; +} diff --git a/day07.cpp b/day07.cpp index 9d63194..caab2f6 100644 --- a/day07.cpp +++ b/day07.cpp @@ -1,78 +1,66 @@ +#include +#include #include +#include #include #include -#include #include +using namespace intcode; 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; +template auto set_params(Machine machine, R const ¶ms) { + std::vector amps; + for (auto p : params) { + auto m = machine; + std::get(m.step()).pos = p; + amps.push_back(std::move(m)); + } + return amps; } -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; +template +auto feed(R &&s, value_type start) -> std::optional { + for (auto &m : amps) { + auto i = m.step(); + if (auto p = std::get_if(&i)) { + p->pos = start; + start = std::get(m.step()).val; + } else { + return {}; } + } + return {start}; } + +auto compute1(Machine machine, std::vector const ¶ms) + -> value_type { + return *feed(set_params(std::move(machine), params), 0); } +auto compute2(Machine machine, std::vector const ¶ms) + -> value_type { + auto amps = set_params(std::move(machine), params); + value_type last = 0; + while (auto next = feed(amps, last)) { + last = *next; + } + return last; +} + +template const &> F> +auto optimize(Machine machine, std::vector params, F f) { + value_type best = 0; + do { + best = std::max(best, f(machine, params)); + } while (std::next_permutation(params.begin(), params.end())); + return best; +} + +} // namespace 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 + auto machine = Machine{parse_stream(std::cin)}; + std::cout << "Part 1: " << optimize(machine, {0, 1, 2, 3, 4}, compute1) << std::endl; + std::cout << "Part 2: " << optimize(std::move(machine), {5, 6, 7, 8, 9}, compute2) << std::endl; +} diff --git a/day09.cpp b/day09.cpp index a8ab42b..a66cd2e 100644 --- a/day09.cpp +++ b/day09.cpp @@ -2,24 +2,30 @@ #include #include +using namespace intcode; 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 compute(Machine machine, value_type d) -> value_type { + value_type output = -1; + while (std::visit(overloaded{ + [](Halt) { return false; }, + [d](Input arg) { + arg.pos = d; + return true; + }, + [&output](Output arg) { + output = arg.val; + return false; + }}, + machine.step())); + return output; } -} +} // namespace 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 + auto machine = Machine{parse_stream(std::cin)}; + std::cout << "Part 1: " << compute(machine, 1) << std::endl; + std::cout << "Part 2: " << compute(std::move(machine), 2) << std::endl; +} diff --git a/lib/include/intcode.hpp b/lib/include/intcode.hpp index 6c86cd2..f0c01b8 100644 --- a/lib/include/intcode.hpp +++ b/lib/include/intcode.hpp @@ -1,49 +1,56 @@ #ifndef INTCODE_HPP_ #define INTCODE_HPP_ -#include #include -#include #include -#include +#include #include +#include +#include -template struct overloaded : Ts... { using Ts::operator()...; }; -template overloaded(Ts...) -> overloaded; +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"; - } -}; +namespace intcode { -struct Input { - std::int64_t& pos; -}; + using value_type = std::int64_t; -struct Output { - std::int64_t val; -}; + struct Input { + value_type &pos; + }; -struct Halt {}; + struct Output { + value_type val; + }; -class intcode { - std::vector rom_; - std::unordered_map ram_; - std::size_t pc_; - std::size_t base_; + struct Halt {}; - auto ref(std::int64_t instruction, std::int64_t p, std::size_t offset) -> std::int64_t&; +class Machine { + std::vector rom_; + std::unordered_map ram_; + std::size_t pc_; + std::size_t base_; + + auto ref(value_type instruction, value_type p, std::size_t offset) + -> value_type &; public: - intcode(); - intcode(std::vector ram); - auto step() -> std::variant; - auto at(std::size_t) -> std::int64_t&; + Machine(); + explicit Machine(std::vector ram); + auto step() -> std::variant; + auto at(std::size_t) -> value_type &; + }; -auto parse_stream(std::istream& in) -> std::vector; +struct BadInstruction : public std::exception { + std::size_t pc; + value_type instruction; + explicit BadInstruction(std::size_t pc, value_type instruction); + const char *what() const noexcept override; +}; -#endif // INTCODE_HPP_ \ No newline at end of file +auto parse_stream(std::istream &in) -> std::vector; + +} + +#endif // INTCODE_HPP_ diff --git a/lib/intcode.cpp b/lib/intcode.cpp index 420c147..4bb5b2e 100644 --- a/lib/intcode.cpp +++ b/lib/intcode.cpp @@ -1,92 +1,107 @@ #include "intcode.hpp" #include -intcode::intcode() : rom_{}, ram_{}, pc_{0}, base_{0} {} +namespace intcode { -intcode::intcode(std::vector ram) : rom_{ram}, ram_{}, pc_{0}, base_{0} {} +BadInstruction::BadInstruction(std::size_t pc, value_type instruction) + : pc{pc}, instruction{instruction} {} -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}; - } +char const *BadInstruction::what() const noexcept { return "bad instruction"; } + +Machine::Machine() : rom_{}, ram_{}, pc_{0}, base_{0} {} + +Machine::Machine(std::vector ram) + : rom_{ram}, ram_{}, pc_{0}, base_{0} {} + +auto Machine::ref(value_type instruction, value_type p, std::size_t offset) + -> value_type & { + 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{pc_, instruction}; + } } -auto intcode::at(std::size_t i) -> std::int64_t& { - return i < rom_.size() ? rom_[i] : ram_[i]; +auto Machine::at(std::size_t i) -> value_type & { + 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); }; +auto Machine::step() -> std::variant { + for (;;) { + auto instruction = at(pc_); + auto a = [=]() -> auto & { return ref(instruction, 100, 1); }; + auto b = [=]() -> auto & { return ref(instruction, 1000, 2); }; + auto c = [=]() -> auto & { return ref(instruction, 10000, 3); }; - switch (instruction % 100) { - case 1: - c() = a() + b(); - pc_ += 4; - break; + 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 2: + c() = a() * b(); + pc_ += 4; + break; - case 4: { - auto val = a(); - pc_ += 2; - return Output{val}; - } + case 3: { + auto &pos = a(); + pc_ += 2; + return Input{pos}; + } - case 5: - pc_ = a() ? b() : pc_ + 3; - break; + case 4: { + auto val = a(); + pc_ += 2; + return Output{val}; + } - 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 5: + pc_ = a() ? b() : pc_ + 3; + break; - case 99: - return Halt{}; + case 6: + pc_ = a() ? pc_ + 3 : b(); + break; - default: - throw BadInstruction{instruction}; - } - } + 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{pc_, 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 +auto parse_stream(std::istream &in) -> std::vector { + value_type x; + std::string str; + std::vector result; + while (std::getline(in, str, ',')) { + result.push_back(std::stoi(str)); + } + return result; +} + +}