Advent of Code 2022 - 2nd attempt in c++
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
|
#include <iostream>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
enum Opcode {
|
|
|
|
NOOP,
|
|
|
|
ADDX
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Instr {
|
|
|
|
Opcode op;
|
|
|
|
int arg;
|
|
|
|
};
|
|
|
|
|
|
|
|
unsigned instr_cycles[] = {
|
|
|
|
1, // NOOP
|
|
|
|
2 // ADDX
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef vector<Instr> 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<Instr> *prog;
|
|
|
|
vector<Instr>::const_iterator cur;
|
|
|
|
unsigned cur_cycles = 0;
|
|
|
|
bool run = true;
|
|
|
|
|
|
|
|
public:
|
|
|
|
unsigned cycle = 1;
|
|
|
|
int X = 1;
|
|
|
|
|
|
|
|
Cpu(const vector<Instr> *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);
|
|
|
|
}
|