#include #include #include #include #include #include #include #include using namespace intcode; namespace { template auto Controller(Machine machine, R const ¶ms) { auto& i = std::get(Step(machine)).input; std::vector amps; amps.reserve(params.size()); for (auto p : params) { i = p; amps.push_back(machine); } return amps; } template auto Feed(R &&s, ValueType start) -> std::optional { for (auto &m : amps) { auto e = Step(m); if (auto i = std::get_if(&e)) { i->input = start; start = StepOutput(m); } else { return {}; } } return {start}; } auto compute1(Machine machine, std::vector const ¶ms) -> ValueType { return *Feed(Controller(std::move(machine), params), 0); } auto compute2(Machine machine, std::vector const ¶ms) -> ValueType { auto amps = Controller(std::move(machine), params); ValueType last = 0; while (auto next = Feed(amps, last)) { last = *next; } return last; } template const &> F> auto optimize(Machine machine, std::vector params, F f) { ValueType best = 0; do { best = std::max(best, f(machine, params)); } while (std::next_permutation(params.begin(), params.end())); return best; } } // namespace auto main(int argc, char** argv) -> int { auto machine = Machine{ParseStream(aocpp::Startup(argc, argv))}; 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; }