nicer fixed step interface

This commit is contained in:
Eric Mertens 2022-11-05 15:06:54 -07:00
parent b8f9152ff6
commit d96eafaa47
6 changed files with 59 additions and 60 deletions

View File

@ -13,9 +13,8 @@ namespace {
template <class R> auto Controller(Machine machine, R const &params) { template <class R> auto Controller(Machine machine, R const &params) {
std::vector<Machine> amps; std::vector<Machine> amps;
for (auto p : params) { for (auto p : params) {
auto m = machine; amps.push_back(machine);
std::get<Input>(Step(m)).pos = p; StepInput(amps.back(), p);
amps.push_back(std::move(m));
} }
return amps; return amps;
} }
@ -26,7 +25,7 @@ auto Feed(R &&amps, ValueType start) -> std::optional<ValueType> {
auto i = Step(m); auto i = Step(m);
if (auto p = std::get_if<Input>(&i)) { if (auto p = std::get_if<Input>(&i)) {
p->pos = start; p->pos = start;
start = std::get<Output>(Step(m)).val; start = StepOutput(m);
} else { } else {
return {}; return {};
} }

View File

@ -1,4 +1,5 @@
#include <iostream> #include <iostream>
#include <stdexcept>
#include <utility> #include <utility>
#include <tuple> #include <tuple>
#include <set> #include <set>
@ -13,17 +14,14 @@ auto Compute1(Machine machine)
-> std::size_t { -> std::size_t {
std::set<Coord> screen; std::set<Coord> screen;
for (;;) { Run(machine,
auto effect = Step(machine); []() -> ValueType { throw std::runtime_error{"unexpected input request"}; },
if (std::holds_alternative<Halt>(effect)) { [&](auto x) {
return screen.size(); auto y = StepOutput(machine);
} auto v = StepOutput(machine);
auto x = std::get<Output>(effect).val;
auto y = std::get<Output>(Step(machine)).val;
auto v = std::get<Output>(Step(machine)).val;
if (2 == v) { screen.insert({x,y}); } else { screen.erase({x,y}); } if (2 == v) { screen.insert({x,y}); } else { screen.erase({x,y}); }
} });
return screen.size();
} }
auto Compute2(Machine machine) { auto Compute2(Machine machine) {
@ -32,17 +30,14 @@ auto Compute2(Machine machine) {
ValueType ballX {0}; ValueType ballX {0};
machine.At(0) = 2; machine.At(0) = 2;
for(;;) {
auto effect = Step(machine); Run(machine,
if (std::holds_alternative<Halt>(effect)) { [&]() {
return score; return paddleX < ballX ? 1 : paddleX > ballX ? -1 : 0;
} else if (auto i = std::get_if<Input>(&effect)) { },
i->pos = paddleX < ballX ? 1 [&](auto x) {
: paddleX > ballX ? -1 : 0; auto y = StepOutput(machine);
} else { auto v = StepOutput(machine);
auto x = std::get<Output>(effect).val;
auto y = std::get<Output>(Step(machine)).val;
auto v = std::get<Output>(Step(machine)).val;
if (-1 == x && 0 == y) { if (-1 == x && 0 == y) {
score = v; score = v;
@ -56,8 +51,8 @@ auto Compute2(Machine machine) {
break; break;
} }
} }
} });
} return score;
} }
} // namespace } // namespace

View File

@ -16,8 +16,8 @@ using CoordOp = Coord(Coord);
CoordOp* const moves[4] {Up, Down, Left, Right}; CoordOp* const moves[4] {Up, Down, Left, Right};
auto Interact(Machine & m, ValueType cmd) -> ValueType { auto Interact(Machine & m, ValueType cmd) -> ValueType {
std::get<Input>(Step(m)).pos = cmd; StepInput(m, cmd);
return std::get<Output>(Step(m)).val; return StepOutput(m);
} }
auto CounterCommand(ValueType x) -> ValueType { auto CounterCommand(ValueType x) -> ValueType {

View File

@ -6,7 +6,6 @@
#include <utility> #include <utility>
#include <variant> #include <variant>
#include <vector> #include <vector>
#include <fstream>
#include <intcode/intcode.hpp> #include <intcode/intcode.hpp>
using namespace intcode; using namespace intcode;
@ -20,46 +19,40 @@ auto BuildNetwork(Machine m) -> std::vector<Machine> {
std::vector<Machine> machines; std::vector<Machine> machines;
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
machines.push_back(m); machines.push_back(m);
std::get<Input>(Step(machines.back())).pos = i; StepInput(machines.back(), i);
} }
return machines; return machines;
} }
auto Interact(Ethernet & ethernet, Machine & m, std::optional<Packet> p) -> void { auto Interact(Ethernet & ethernet, Machine & m, std::optional<Packet> p) -> void {
for(;;) { while(std::visit(overloaded{
auto effect = Step(m);
switch (effect.index()) {
default: [&](Input i) {
throw std::runtime_error{"unexpected halt"};
case 0: // Input
if (p) { if (p) {
std::get<Input>(effect).pos = p->first; i.pos = p->first;
std::get<Input>(Step(m)).pos = p->second; StepInput(m, p->second);
p = {}; p = {};
break; return true;
} }
std::get<Input>(effect).pos = -1; // no packet i.pos = -1; // no packet
return; return false;
},
case 1: // Output [&](Output o) {
auto d = std::get<Output>(effect).val; auto x = StepOutput(m);
auto x = std::get<Output>(Step(m)).val; auto y = StepOutput(m);
auto y = std::get<Output>(Step(m)).val; ethernet.push_back({o.val, {x,y}});
ethernet.push_back({d, {x,y}}); return true;
break; },
}
} [](Halt) -> bool { throw std::runtime_error{"unexpected halt"}; },
}, Step(m))) {}
} }
} // namespace } // namespace
auto main(int argc, char ** argv) -> int { auto main() -> int {
if (2 != argc) { return 1; } auto machines = BuildNetwork(Machine{ParseStream(std::cin)});
std::ifstream fin {argv[1]};
auto machines = BuildNetwork(Machine{ParseStream(fin)});
auto ethernet = Ethernet{}; auto ethernet = Ethernet{};
std::optional<ValueType> part1; std::optional<ValueType> part1;

View File

@ -17,6 +17,10 @@ ValueType val;
struct Halt {}; struct Halt {};
auto StepInput(Machine & m, ValueType input) -> void;
auto StepOutput(Machine & m) -> ValueType;
auto Step(Machine & m) -> std::variant<Input, Output, Halt>; auto Step(Machine & m) -> std::variant<Input, Output, Halt>;
struct BadInstruction : public std::runtime_error { struct BadInstruction : public std::runtime_error {

View File

@ -5,6 +5,14 @@ namespace intcode {
BadInstruction::BadInstruction(char const* what) BadInstruction::BadInstruction(char const* what)
: std::runtime_error{what} {} : std::runtime_error{what} {}
auto StepInput(Machine & m, ValueType input) -> void {
std::get<Input>(Step(m)).pos = input;
}
auto StepOutput(Machine & m) -> ValueType {
return std::get<Output>(Step(m)).val;
}
auto Step(Machine & m) -> std::variant<Input, Output, Halt> { auto Step(Machine & m) -> std::variant<Input, Output, Halt> {
for (;;) { for (;;) {
auto instruction = m.Next(); auto instruction = m.Next();