104 lines
2.3 KiB
Rust
104 lines
2.3 KiB
Rust
use aoc_runner_derive::{aoc, aoc_generator};
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
enum Instruction {
|
|
AddX(i32),
|
|
NoOp,
|
|
}
|
|
|
|
#[aoc_generator(day10)]
|
|
fn generator(input: &str) -> Vec<Instruction> {
|
|
input
|
|
.lines()
|
|
.map(|l| {
|
|
if l == "noop" {
|
|
Instruction::NoOp
|
|
} else if let Some(l) = l.strip_prefix("addx ") {
|
|
Instruction::AddX(l.parse().unwrap())
|
|
} else {
|
|
panic!()
|
|
}
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
struct CpuState {
|
|
cycle: i32,
|
|
x: i32,
|
|
}
|
|
|
|
fn run_simulation(input: &[Instruction], mut during_cycle_handler: impl FnMut(CpuState)) {
|
|
let mut cycle = 1;
|
|
let mut x = 1;
|
|
let mut iter = input.iter().copied();
|
|
let mut current_instruction = iter.next().unwrap();
|
|
let mut current_instruction_cycle = 0;
|
|
|
|
// god i hate fenceposts
|
|
loop {
|
|
// START OF CYCLE
|
|
|
|
let need_new_instruction = match (current_instruction, current_instruction_cycle) {
|
|
(_, 0) => false,
|
|
(Instruction::NoOp, 1) => true,
|
|
(Instruction::AddX(_), 1) => false,
|
|
(Instruction::AddX(v), 2) => {
|
|
x += v;
|
|
true
|
|
}
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
if need_new_instruction {
|
|
let Some(tmp) = iter.next() else {
|
|
break
|
|
};
|
|
current_instruction = tmp;
|
|
current_instruction_cycle = 0;
|
|
}
|
|
|
|
// DURING CYCLE
|
|
|
|
during_cycle_handler(CpuState { cycle, x });
|
|
|
|
// END OF CYCLE
|
|
|
|
current_instruction_cycle += 1;
|
|
cycle += 1;
|
|
}
|
|
}
|
|
|
|
#[aoc(day10, part1)]
|
|
fn part1(input: &[Instruction]) -> i32 {
|
|
let mut res = 0;
|
|
|
|
run_simulation(input, |CpuState { cycle, x }| {
|
|
if (cycle + 20) % 40 == 0 {
|
|
res += cycle * x;
|
|
}
|
|
});
|
|
|
|
res
|
|
}
|
|
|
|
#[aoc(day10, part2)]
|
|
fn part2(input: &[Instruction]) -> String {
|
|
let mut res = "\n".to_owned(); // newline so that `cargo aoc` formats this nicely
|
|
|
|
run_simulation(input, |CpuState { cycle, x }| {
|
|
let crt_x_pos = (cycle - 1) % 40;
|
|
|
|
if (crt_x_pos - x).abs() <= 1 {
|
|
res.push('#');
|
|
} else {
|
|
res.push(' '); // the puzzle says `.` but ` ` is more readable
|
|
}
|
|
|
|
if cycle % 40 == 0 {
|
|
res.push('\n');
|
|
}
|
|
});
|
|
|
|
res
|
|
}
|