diff --git a/day07.cpp b/day07.cpp index 06d1c0e..e34911e 100644 --- a/day07.cpp +++ b/day07.cpp @@ -13,9 +13,8 @@ namespace { template auto Controller(Machine machine, R const ¶ms) { std::vector amps; for (auto p : params) { - auto m = machine; - std::get(Step(m)).pos = p; - amps.push_back(std::move(m)); + amps.push_back(machine); + StepInput(amps.back(), p); } return amps; } @@ -26,7 +25,7 @@ auto Feed(R &&s, ValueType start) -> std::optional { auto i = Step(m); if (auto p = std::get_if(&i)) { p->pos = start; - start = std::get(Step(m)).val; + start = StepOutput(m); } else { return {}; } diff --git a/day13.cpp b/day13.cpp index cb9b659..cf931a1 100644 --- a/day13.cpp +++ b/day13.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -13,17 +14,14 @@ auto Compute1(Machine machine) -> std::size_t { std::set screen; - for (;;) { - auto effect = Step(machine); - if (std::holds_alternative(effect)) { - return screen.size(); - } - auto x = std::get(effect).val; - auto y = std::get(Step(machine)).val; - auto v = std::get(Step(machine)).val; - - if (2 == v) { screen.insert({x,y}); } else { screen.erase({x,y}); } - } + Run(machine, + []() -> ValueType { throw std::runtime_error{"unexpected input request"}; }, + [&](auto x) { + auto y = StepOutput(machine); + auto v = StepOutput(machine); + if (2 == v) { screen.insert({x,y}); } else { screen.erase({x,y}); } + }); + return screen.size(); } auto Compute2(Machine machine) { @@ -32,17 +30,14 @@ auto Compute2(Machine machine) { ValueType ballX {0}; machine.At(0) = 2; - for(;;) { - auto effect = Step(machine); - if (std::holds_alternative(effect)) { - return score; - } else if (auto i = std::get_if(&effect)) { - i->pos = paddleX < ballX ? 1 - : paddleX > ballX ? -1 : 0; - } else { - auto x = std::get(effect).val; - auto y = std::get(Step(machine)).val; - auto v = std::get(Step(machine)).val; + + Run(machine, + [&]() { + return paddleX < ballX ? 1 : paddleX > ballX ? -1 : 0; + }, + [&](auto x) { + auto y = StepOutput(machine); + auto v = StepOutput(machine); if (-1 == x && 0 == y) { score = v; @@ -56,8 +51,8 @@ auto Compute2(Machine machine) { break; } } - } - } + }); + return score; } } // namespace diff --git a/day15.cpp b/day15.cpp index 386a452..148138a 100644 --- a/day15.cpp +++ b/day15.cpp @@ -16,8 +16,8 @@ using CoordOp = Coord(Coord); CoordOp* const moves[4] {Up, Down, Left, Right}; auto Interact(Machine & m, ValueType cmd) -> ValueType { - std::get(Step(m)).pos = cmd; - return std::get(Step(m)).val; + StepInput(m, cmd); + return StepOutput(m); } auto CounterCommand(ValueType x) -> ValueType { diff --git a/day23.cpp b/day23.cpp index 412ca6c..73e180d 100644 --- a/day23.cpp +++ b/day23.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include using namespace intcode; @@ -20,46 +19,40 @@ auto BuildNetwork(Machine m) -> std::vector { std::vector machines; for (int i = 0; i < 50; i++) { machines.push_back(m); - std::get(Step(machines.back())).pos = i; + StepInput(machines.back(), i); } return machines; } auto Interact(Ethernet & ethernet, Machine & m, std::optional p) -> void { - for(;;) { - auto effect = Step(m); - switch (effect.index()) { + while(std::visit(overloaded{ - default: - throw std::runtime_error{"unexpected halt"}; - - case 0: // Input - if (p) { - std::get(effect).pos = p->first; - std::get(Step(m)).pos = p->second; - p = {}; - break; - } - std::get(effect).pos = -1; // no packet - return; - - case 1: // Output - auto d = std::get(effect).val; - auto x = std::get(Step(m)).val; - auto y = std::get(Step(m)).val; - ethernet.push_back({d, {x,y}}); - break; + [&](Input i) { + if (p) { + i.pos = p->first; + StepInput(m, p->second); + p = {}; + return true; } - } + i.pos = -1; // no packet + return false; + }, + + [&](Output o) { + auto x = StepOutput(m); + auto y = StepOutput(m); + ethernet.push_back({o.val, {x,y}}); + return true; + }, + + [](Halt) -> bool { throw std::runtime_error{"unexpected halt"}; }, + }, Step(m))) {} } } // namespace -auto main(int argc, char ** argv) -> int { - if (2 != argc) { return 1; } - std::ifstream fin {argv[1]}; - - auto machines = BuildNetwork(Machine{ParseStream(fin)}); +auto main() -> int { + auto machines = BuildNetwork(Machine{ParseStream(std::cin)}); auto ethernet = Ethernet{}; std::optional part1; diff --git a/lib/include/intcode/Interpreter.hpp b/lib/include/intcode/Interpreter.hpp index e3ca67a..13bc499 100644 --- a/lib/include/intcode/Interpreter.hpp +++ b/lib/include/intcode/Interpreter.hpp @@ -17,6 +17,10 @@ ValueType val; struct Halt {}; +auto StepInput(Machine & m, ValueType input) -> void; + +auto StepOutput(Machine & m) -> ValueType; + auto Step(Machine & m) -> std::variant; struct BadInstruction : public std::runtime_error { diff --git a/lib/src/Interpreter.cpp b/lib/src/Interpreter.cpp index eafc7a8..41abde5 100644 --- a/lib/src/Interpreter.cpp +++ b/lib/src/Interpreter.cpp @@ -5,6 +5,14 @@ namespace intcode { BadInstruction::BadInstruction(char const* what) : std::runtime_error{what} {} +auto StepInput(Machine & m, ValueType input) -> void { + std::get(Step(m)).pos = input; +} + +auto StepOutput(Machine & m) -> ValueType { + return std::get(Step(m)).val; +} + auto Step(Machine & m) -> std::variant { for (;;) { auto instruction = m.Next();