aoc22/src/day10.rs
2022-12-15 16:26:34 +01:00

105 lines
2.3 KiB
Rust

#[derive(Debug)]
pub enum Instruction {
Noop,
Addx(isize),
}
pub fn parse_instructions(input: &String) -> Vec<Instruction> {
let mut result = Vec::new();
for line in input.lines() {
if line == "noop" {
result.push(Instruction::Noop);
} else {
let (inst, v) = line.split_once(' ').unwrap();
assert_eq!(inst, "addx");
let v = v.parse().unwrap();
result.push(Instruction::Addx(v));
}
}
result
}
#[derive(Debug)]
pub struct CPU {
pub x: isize,
pub cycle: isize,
instructions: Vec<Instruction>,
pc: usize,
inst_cycle: usize,
}
impl CPU {
pub fn new(instructions: Vec<Instruction>) -> CPU {
CPU {
x: 1,
cycle: 0,
instructions,
pc: 0,
inst_cycle: 0,
}
}
pub fn do_cycle(&mut self) -> Option<()> {
if let Some(inst) = self.instructions.get(self.pc) {
match inst {
Instruction::Noop => {
self.pc += 1;
}
Instruction::Addx(v) => {
self.inst_cycle += 1;
if self.inst_cycle == 2 {
self.pc += 1;
self.inst_cycle = 0;
self.x += v;
}
}
}
self.cycle += 1;
Some(())
} else {
None
}
}
pub fn signal_strength(&self) -> isize {
return self.x * (self.cycle + 1);
}
}
pub struct CRT {
pub pixels: [[char; 40]; 6],
}
impl CRT {
pub fn new() -> CRT {
CRT {
pixels: [['.'; 40]; 6],
}
}
pub fn render(&mut self, cpu: &CPU) {
let c = cpu.cycle;
assert!(c >= 0 && c < 240);
let x = c % 40;
let y = c / 40;
let sprite_pos = cpu.x - 1;
let px = &mut self.pixels[y as usize][x as usize];
if x >= sprite_pos && x < sprite_pos + 3 {
*px = '#';
} else {
*px = '.';
}
}
pub fn draw(&self) {
for y in 0..6 {
for x in 0..40 {
print!("{}", self.pixels[y][x]);
}
print!("\n");
}
}
}