aocpp/2019/23.cpp

91 lines
2.1 KiB
C++
Raw Normal View History

2022-11-07 17:19:17 -08:00
#include <array>
2022-11-05 11:19:32 -07:00
#include <cstddef>
#include <deque>
#include <iostream>
#include <stdexcept>
#include <utility>
#include <variant>
#include <vector>
#include <aocpp/Startup.hpp>
2022-11-05 11:19:32 -07:00
#include <intcode/intcode.hpp>
using namespace intcode;
namespace {
2022-11-06 10:53:26 -08:00
struct Payload { ValueType x, y; };
struct Packet { ValueType destination; Payload payload; };
using Ethernet = std::deque<Packet>;
2022-11-07 17:19:17 -08:00
using Machines = std::array<Machine, 50>;
2022-11-05 11:19:32 -07:00
2022-11-07 17:19:17 -08:00
auto BuildNetwork(Machine m) -> Machines {
Machines machines;
2022-11-06 19:46:43 -08:00
auto& i = std::get<Input>(Step(m)).input;
2022-11-11 08:27:18 -08:00
for (i = 0; i < std::int64_t(machines.size()); i++) {
2022-11-07 17:19:17 -08:00
machines[i] = m;
2022-11-05 11:19:32 -07:00
}
return machines;
}
2022-11-06 10:53:26 -08:00
auto Interact(Ethernet & ethernet, Machine & m, std::optional<Payload> p) -> void {
for(;;) {
auto e = Step(m);
switch (e.index()) {
default: throw std::runtime_error{"unexpected halt"};
case 0: {
2022-11-06 19:46:43 -08:00
auto& i = std::get<0>(e).input;
2022-11-06 10:53:26 -08:00
if (p) {
i = p->x;
StepInput(m, p->y);
p = {};
break;
}
i = -1; // no packet
return;
}
case 1: {
2022-11-06 19:46:43 -08:00
auto d = std::get<1>(e).output;
2022-11-06 10:53:26 -08:00
auto x = StepOutput(m);
auto y = StepOutput(m);
ethernet.push_back({d, {x,y}});
}
2022-11-05 15:06:54 -07:00
}
2022-11-06 10:53:26 -08:00
}
2022-11-05 11:19:32 -07:00
}
} // namespace
2023-01-31 09:15:15 -08:00
auto Main(std::istream & in, std::ostream & out) -> void
2023-01-31 08:58:42 -08:00
{
auto machines = BuildNetwork(Machine{ParseStream(in)});
2022-11-05 11:19:32 -07:00
auto ethernet = Ethernet{};
std::optional<ValueType> part1;
std::optional<ValueType> part2;
2022-11-06 10:53:26 -08:00
std::optional<Payload> nat;
2022-11-05 11:19:32 -07:00
for(;;) {
2022-11-05 21:48:52 -07:00
if (!ethernet.empty()) {
2022-11-07 17:19:17 -08:00
auto const packet = ethernet.front();
2022-11-05 11:19:32 -07:00
ethernet.pop_front();
2022-11-06 10:53:26 -08:00
if (packet.destination == 255) {
nat = packet.payload;
if (!part1) { part1 = packet.payload.y; }
2022-11-05 11:19:32 -07:00
} else {
2022-11-06 10:53:26 -08:00
Interact(ethernet, machines.at(packet.destination), packet.payload);
2022-11-05 21:48:52 -07:00
}
} else if (nat) {
2022-11-06 10:53:26 -08:00
if (part2 == nat->y) { break; }
part2 = nat->y;
2022-11-05 21:48:52 -07:00
Interact(ethernet, machines[0], nat);
} else {
2022-11-06 10:53:26 -08:00
for (auto & m : machines) {
2022-11-05 21:48:52 -07:00
Interact(ethernet, m, {});
2022-11-05 11:19:32 -07:00
}
}
}
2023-01-31 09:15:15 -08:00
out << "Part 1: " << *part1 << std::endl;
out << "Part 2: " << *part2 << std::endl;
2022-11-05 11:19:32 -07:00
}