#include #include using namespace std; enum Opcode { NOOP, ADDX }; struct Instr { Opcode op; int arg; }; unsigned instr_cycles[] = { 1, // NOOP 2 // ADDX }; typedef vector Input; Input parse() { Input data; for (string line; getline(cin, line);) { Instr instr; string op = line.substr(0, 5); if (op == "noop") { instr.op = NOOP; } else if (op == "addx ") { instr.op = ADDX; instr.arg = stoi(line.substr(5)); } data.push_back(instr); } return data; } class Cpu { const vector *prog; vector::const_iterator cur; unsigned cur_cycles = 0; bool run = true; public: unsigned cycle = 1; int X = 1; Cpu(const vector *prog) { this->prog = prog; this->cur = prog->begin(); } void tick(); bool running() { return run; } }; void Cpu::tick() { if (!run) return; // Fetch next instruction if (!cur_cycles) { cur_cycles = instr_cycles[cur->op]; } // Execute instruction when done if (!--cur_cycles) { switch (cur->op) { case NOOP: break; case ADDX: this->X += cur->arg; break; } cur++; if (cur >= prog->end()) run = false; } cycle++; } unsigned p1(const Input &input) { unsigned sum = 0; Cpu cpu(&input); while (cpu.running()) { if ((cpu.cycle + 20) % 40 == 0) sum += cpu.cycle * cpu.X; cpu.tick(); } return sum; } #define WIDTH 40 void p2(const Input &input) { Cpu cpu(&input); while (cpu.running()) { // Calculate current CRT line int X = cpu.cycle % WIDTH; if (X == 0) X += WIDTH; // Draw pixel if (cpu.X <= X && X <= cpu.X + 2) cout << '#'; else cout << '.'; if (X == WIDTH) cout << endl; cpu.tick(); } } int main() { auto input = parse(); cout << p1(input) << endl; p2(input); }