From ae1e96f10b399266825e275ca4a8100ceede9cad Mon Sep 17 00:00:00 2001 From: Thomas Schmucker Date: Thu, 23 Oct 2025 19:28:20 +0200 Subject: days 19-25, aoc 2016 --- 2016/src/day23.cpp | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 2016/src/day23.cpp (limited to '2016/src/day23.cpp') diff --git a/2016/src/day23.cpp b/2016/src/day23.cpp new file mode 100644 index 0000000..81bffe4 --- /dev/null +++ b/2016/src/day23.cpp @@ -0,0 +1,287 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace { + +enum class OpCode : uint8_t { + CPY, + INC, + DEC, + JNZ, + TGL +}; + +using memory_type = map; + +struct Argument { + explicit Argument(string value) + : value{ std::move(value) } + { + } + + [[nodiscard]] + int eval(const memory_type& memory) const + { + const auto chr = value.at(0); + + if ( chr >= 'a' && chr <= 'z' ) { + return memory.at(chr); + } + else { + return stoi(value); + } + } + + [[nodiscard]] + char reg() const + { + if ( !is_reg() ) { + throw runtime_error("invalid register access! "s + value); + } + + return value.at(0); + } + + [[nodiscard]] + bool is_reg() const + { + const auto chr = value.at(0); + + return chr >= 'a' && chr <= 'z'; + } + + string value; +}; + +struct Instruction { + Instruction(OpCode opCode, const Argument& x) + : opCode{ opCode } + , x{ x } + { + } + + Instruction(OpCode opCode, const Argument& x, const Argument& y) + : opCode{ opCode } + , x{ x } + , y{ y } + { + } + + OpCode opCode; + optional x; + optional y; +}; + +vector +split_words(const string& line, char sep = ' ') +{ + vector words; + stringstream strm{ line }; + + for ( string word; getline(strm, word, sep); ) { + words.emplace_back(word); + } + + return words; +} + +vector +read_file(const filesystem::path& filename) +{ + ifstream input{ filename }; + + vector instructions; + + for ( string line; getline(input, line); ) { + const auto words = split_words(line); + + if ( words.at(0) == "cpy" ) { + instructions.emplace_back(OpCode::CPY, Argument(words.at(1)), Argument(words.at(2))); + } + else if ( words.at(0) == "inc" ) { + instructions.emplace_back(OpCode::INC, Argument(words.at(1))); + } + else if ( words.at(0) == "dec" ) { + instructions.emplace_back(OpCode::DEC, Argument(words.at(1))); + } + else if ( words.at(0) == "jnz" ) { + instructions.emplace_back(OpCode::JNZ, Argument(words.at(1)), Argument(words.at(2))); + } + else if ( words.at(0) == "tgl" ) { + instructions.emplace_back(OpCode::TGL, Argument(words.at(1))); + } + else { + cerr << "unknown opcode..." << '\n'; + } + } + + return instructions; +} + +#define JIT + +void +execute(memory_type& memory, vector instructions) +{ + for ( size_t ip = 0; ip < instructions.size(); ) { +#if defined(JIT) + if ( ip + 2 < instructions.size() ) { + const auto& i0 = instructions[ip]; + const auto& i1 = instructions[ip + 1]; + const auto& i2 = instructions[ip + 2]; + + if ( i0.opCode == OpCode::INC && + i1.opCode == OpCode::DEC && + i2.opCode == OpCode::JNZ && + i2.x && i2.x->value == i1.x->value && + i2.y && i2.y->value == "-2" ) { + char X = i0.x->reg(); + char Y = i1.x->reg(); + memory[X] += memory[Y]; + memory[Y] = 0; + ip += 3; + continue; + } + } +#endif + +#if defined(JIT) + if ( ip + 5 < instructions.size() ) { + const auto& i0 = instructions[ip]; + const auto& i1 = instructions[ip + 1]; + const auto& i2 = instructions[ip + 2]; + const auto& i3 = instructions[ip + 3]; + const auto& i4 = instructions[ip + 4]; + const auto& i5 = instructions[ip + 5]; + + if ( i0.opCode == OpCode::CPY && + i1.opCode == OpCode::INC && + i2.opCode == OpCode::DEC && + i3.opCode == OpCode::JNZ && + i4.opCode == OpCode::DEC && + i5.opCode == OpCode::JNZ && + i3.x && i3.y && i3.x->value == i2.x->value && i3.y->value == "-2" && + i5.x && i5.y && i5.x->value == i4.x->value && i5.y->value == "-5" && + i0.y->is_reg() && i1.x->is_reg() && i2.x->is_reg() && i4.x->is_reg() ) { + char X = i0.x->is_reg() ? i0.x->reg() : 0; + int valX = i0.x->is_reg() ? memory[X] : stoi(i0.x->value); + + char Y = i0.y->reg(); + char Z = i1.x->reg(); + char W = i4.x->reg(); + + memory[Z] += valX * memory[W]; + memory[Y] = 0; + memory[W] = 0; + ip += 6; + continue; + } + } +#endif + + const auto& instruction = instructions.at(ip); + + // cout << "#" << ip << " - " << memory['a'] << ", " << memory['b'] << ", " << memory['c'] << ", " << memory['d'] << ": " << (int) instruction.opCode << '\n'; + + switch ( instruction.opCode ) { + using enum OpCode; + case CPY: + memory[instruction.y->reg()] = instruction.x->eval(memory); + ++ip; + break; + case INC: + memory[instruction.x->reg()]++; + ++ip; + break; + case DEC: + memory[instruction.x->reg()]--; + ++ip; + break; + case JNZ: + if ( instruction.x->eval(memory) != 0 ) { + ip += static_cast(instruction.y->eval(memory)); + } + else { + ++ip; + } + break; + case TGL: + if ( auto foo = ip + static_cast(instruction.x->eval(memory)); foo < instructions.size() ) { + switch ( instructions[foo].opCode ) { + case CPY: + instructions[foo].opCode = JNZ; + break; + case INC: + instructions[foo].opCode = DEC; + break; + case DEC: + instructions[foo].opCode = INC; + break; + case JNZ: + instructions[foo].opCode = CPY; + break; + case TGL: + instructions[foo].opCode = INC; + break; + } + } + + ++ip; + break; + } + } +} + +void +part1(const vector& instructions) +{ + map memory; + + memory['a'] = 7; + memory['b'] = 0; + memory['c'] = 0; + memory['d'] = 0; + + execute(memory, instructions); + + cout << "Part1: " << memory['a'] << '\n'; +} + +void +part2(const vector& instructions) +{ + map memory; + + memory['a'] = 12; + memory['b'] = 0; + memory['c'] = 0; + memory['d'] = 0; + + execute(memory, instructions); + + cout << "Part2: " << memory['a'] << '\n'; +} + +} // namespace + +int +main() +{ + const auto instructions = read_file("data/day23.txt"); + try { + part1(instructions); + part2(instructions); + } + catch ( exception& e ) { + cerr << e.what() << '\n'; + } +} -- cgit v1.3