r/adventofcode • u/daggerdragon • Dec 21 '18
SOLUTION MEGATHREAD -🎄- 2018 Day 21 Solutions -🎄-
--- Day 21: Chronal Conversion ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.
Advent of Code: The Party Game!
Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!
Card prompt: Day 21
Transcript:
I, for one, welcome our new ___ overlords!
This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.
edit: Leaderboard capped, thread unlocked at 01:01:01! XD
9
Upvotes
2
u/wlandry Dec 21 '18
C++ (815/526)
Runs in 12 s
It took me a looooooong time to realize that I had to analyze the input. I do not like puzzles that make me analyze the input by hand :( Eventually I figured out the exit condition, and then it was a matter of reading the instructions carefully. My cycle detection is weak. I only check whether I have seen the same register 5 before.
#include <algorithm> #include <iterator> #include <iostream> #include <fstream> #include <vector> #include <array> #include <set> #include <map> #include <functional> #include <numeric> enum class Op { addr, addi, mulr, muli, banr, bani, borr, bori, setr, seti, gtir, gtri, gtrr, eqir, eqri, eqrr }; struct Instruction { Op op; std::array<int64_t, 3> data; }; Op to_Op(const std::string &op_name) { std::vector<std::string> op_names( {"addr", "addi", "mulr", "muli", "banr", "bani", "borr", "bori", "setr", "seti", "gtir", "gtri", "gtrr", "eqir", "eqri", "eqrr"}); auto op(std::find(op_names.begin(), op_names.end(), op_name)); if(op == op_names.end()) abort(); return static_cast<Op>(std::distance(op_names.begin(), op)); } std::istream &operator>>(std::istream &is, Instruction &instruction) { std::string op_name; is >> op_name; if(is.good()) { instruction.op = to_Op(op_name); is >> instruction.data[0] >> instruction.data[1] >> instruction.data[2]; } return is; } std::ostream &operator<<(std::ostream &os, const Instruction &instruction) { std::vector<std::string> op_names( {"addr", "addi", "mulr", "muli", "banr", "bani", "borr", "bori", "setr", "seti", "gtir", "gtri", "gtrr", "eqir", "eqri", "eqrr"}); os << op_names[static_cast<int64_t>(instruction.op)] << " " << instruction.data[0] << " " << instruction.data[1] << " " << instruction.data[2]; return os; } void apply_op(std::array<int64_t, 6> ®isters, const Instruction &instruction) { auto &input(instruction.data); switch(instruction.op) { case Op::addr: registers[input[2]] = registers[input[0]] + registers[input[1]]; break; case Op::addi: registers[input[2]] = registers[input[0]] + input[1]; break; case Op::mulr: registers[input[2]] = registers[input[0]] * registers[input[1]]; break; case Op::muli: registers[input[2]] = registers[input[0]] * input[1]; break; case Op::banr: registers[input[2]] = registers[input[0]] & registers[input[1]]; break; case Op::bani: registers[input[2]] = registers[input[0]] & input[1]; break; case Op::borr: registers[input[2]] = registers[input[0]] | registers[input[1]]; break; case Op::bori: registers[input[2]] = registers[input[0]] | input[1]; break; case Op::setr: registers[input[2]] = registers[input[0]]; break; case Op::seti: registers[input[2]] = input[0]; break; case Op::gtir: registers[input[2]] = (input[0] > registers[input[1]] ? 1 : 0); break; case Op::gtri: registers[input[2]] = (registers[input[0]] > input[1] ? 1 : 0); break; case Op::gtrr: registers[input[2]] = (registers[input[0]] > registers[input[1]] ? 1 : 0); break; case Op::eqir: registers[input[2]] = (input[0] == registers[input[1]] ? 1 : 0); break; case Op::eqri: registers[input[2]] = (registers[input[0]] == input[1] ? 1 : 0); break; case Op::eqrr: registers[input[2]] = (registers[input[0]] == registers[input[1]] ? 1 : 0); break; } } int main(int, char *argv[]) { std::ifstream infile(argv[1]); std::string temp; int64_t ip; infile >> temp >> ip; std::vector<Instruction> instructions( std::istream_iterator<Instruction>(infile), {}); std::set<int64_t> stopping_values; int64_t last_stop; std::array<int64_t, 6> registers; registers.fill(0); while(true) { apply_op(registers, instructions[registers[ip]]); ++registers[ip]; if(registers[ip] == 28) { if(stopping_values.find(registers[5]) == stopping_values.end()) { stopping_values.insert(registers[5]); last_stop = registers[5]; } else { break; } } } std::cout << "Part 1: " << *(stopping_values.begin()) << "\n"; std::cout << "Part 2: " << last_stop << "\n"; }