diff --git a/src/day10/mod.rs b/src/day10/mod.rs index 32237a1..ce513ed 100644 --- a/src/day10/mod.rs +++ b/src/day10/mod.rs @@ -1,111 +1,6 @@ +use crate::puter::Puter; use crate::read; -#[derive(Debug, PartialEq, Eq, Clone, Hash)] -enum Command { - AddX(i32), - Noop, -} -impl Command { - fn from_str(s: &str) -> Self { - match s { - "noop" => Command::Noop, - s => { - let (c, i) = s.split_once(' ').unwrap(); - match (c, i.parse::()) { - ("addx", Ok(i)) => Self::AddX(i), - _ => unreachable!(), - } - } - } - } - - fn num_cycles(&self) -> usize { - match self { - Self::Noop => 1, - Self::AddX(_) => 2, - } - } -} - -struct Puter { - register_x: (i32, i32), - cycle: usize, - pixel_row: [bool; Puter::LINE_WIDTH], - rows: Vec, - cycles_processing_left: usize, - - signal_strengths: Vec, -} - -impl Puter { - const LINE_WIDTH: usize = 40; - const SPRITE_WIDTH: usize = 3; - const SPRITE_WIDTH_HALF: usize = Puter::SPRITE_WIDTH / 2; - - pub fn new() -> Self { - Self { - register_x: (1, 1), - cycle: 1, - pixel_row: [false; Puter::LINE_WIDTH], - rows: Vec::with_capacity(6), - cycles_processing_left: 0, - signal_strengths: Vec::with_capacity(6), - } - } - - fn execute(&mut self, cmd: Command) { - match cmd { - Command::Noop => {} - Command::AddX(v) => { - self.register_x.1 += v; - } - }; - self.cycles_processing_left = cmd.num_cycles(); - } - - pub fn run(&mut self, program: &str) { - let mut lines = program.lines(); - loop { - if self.cycles_processing_left == 0 { - match lines.next() { - Some(s) => self.execute(Command::from_str(s)), - _ => return, - }; - } - - self.cycles_processing_left -= 1; - - let pixel = (self.cycle - 1) % Puter::LINE_WIDTH; - let is_lit = pixel.abs_diff(self.register_x.0 as usize) <= Puter::SPRITE_WIDTH_HALF; - self.pixel_row[pixel] = is_lit; - if pixel == Puter::LINE_WIDTH - 1 { - self.rows.push( - self.pixel_row - .map(|l| if l { '#' } else { ' ' }) - .iter() - .collect(), - ); - } else if pixel == (Puter::LINE_WIDTH / 2) - 1 { - self.signal_strengths - .push(self.cycle as i32 * self.register_x.0); - } - - if self.cycles_processing_left == 0 { - self.register_x.0 = self.register_x.1; - } - self.cycle += 1; - } - } - - pub fn signal_strengths(&self) -> Vec { - self.signal_strengths.clone() - } - - pub fn output(&self) -> Vec { - self.rows.clone() - } -} - pub fn run() { let input = read("10"); let mut device = Puter::new(); diff --git a/src/main.rs b/src/main.rs index 8cb35f3..d4e2e8f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ mod day07; mod day08; mod day09; mod day10; +mod puter; fn main() { let today = Local::now().day(); diff --git a/src/puter/mod.rs b/src/puter/mod.rs new file mode 100644 index 0000000..b58ee0e --- /dev/null +++ b/src/puter/mod.rs @@ -0,0 +1,105 @@ +#[derive(Debug, PartialEq, Eq, Clone, Hash)] +pub(crate) enum Command { + AddX(i32), + Noop, +} +impl Command { + fn from_str(s: &str) -> Self { + match s { + "noop" => Command::Noop, + s => { + let (c, i) = s.split_once(' ').unwrap(); + match (c, i.parse::()) { + ("addx", Ok(i)) => Self::AddX(i), + _ => unreachable!(), + } + } + } + } + + fn num_cycles(&self) -> usize { + match self { + Self::Noop => 1, + Self::AddX(_) => 2, + } + } +} + +pub(crate) struct Puter { + register_x: (i32, i32), + cycle: usize, + pixel_row: [bool; Puter::LINE_WIDTH], + rows: Vec, + cycles_processing_left: usize, + + signal_strengths: Vec, +} + +impl Puter { + const LINE_WIDTH: usize = 40; + const SPRITE_WIDTH: usize = 3; + const SPRITE_WIDTH_HALF: usize = Puter::SPRITE_WIDTH / 2; + + pub fn new() -> Self { + Self { + register_x: (1, 1), + cycle: 1, + pixel_row: [false; Puter::LINE_WIDTH], + rows: Vec::with_capacity(6), + cycles_processing_left: 0, + signal_strengths: Vec::with_capacity(6), + } + } + + fn execute(&mut self, cmd: Command) { + match cmd { + Command::Noop => {} + Command::AddX(v) => { + self.register_x.1 += v; + } + }; + self.cycles_processing_left = cmd.num_cycles(); + } + + pub fn run(&mut self, program: &str) { + let mut lines = program.lines(); + loop { + if self.cycles_processing_left == 0 { + match lines.next() { + Some(s) => self.execute(Command::from_str(s)), + _ => return, + }; + } + + self.cycles_processing_left -= 1; + + let pixel = (self.cycle - 1) % Puter::LINE_WIDTH; + let is_lit = pixel.abs_diff(self.register_x.0 as usize) <= Puter::SPRITE_WIDTH_HALF; + self.pixel_row[pixel] = is_lit; + if pixel == Puter::LINE_WIDTH - 1 { + self.rows.push( + self.pixel_row + .map(|l| if l { '#' } else { ' ' }) + .iter() + .collect(), + ); + } else if pixel == (Puter::LINE_WIDTH / 2) - 1 { + self.signal_strengths + .push(self.cycle as i32 * self.register_x.0); + } + + if self.cycles_processing_left == 0 { + self.register_x.0 = self.register_x.1; + } + self.cycle += 1; + } + } + + pub fn signal_strengths(&self) -> Vec { + self.signal_strengths.clone() + } + + pub fn output(&self) -> Vec { + self.rows.clone() + } +}