From 54fd03233ae1f4831e7fdd8c89b01218cccdbb08 Mon Sep 17 00:00:00 2001 From: Ruediger Ludwig Date: Sun, 5 Feb 2023 16:12:44 +0100 Subject: [PATCH] day10 finished --- data/day10/example01.txt | 146 +++++++++++++++++++++++++++++++++ data/day10/expected01.txt | 6 ++ data/day10/input.txt | 143 +++++++++++++++++++++++++++++++++ src/days/day10/mod.rs | 165 ++++++++++++++++++++++++++++++++++++++ src/days/mod.rs | 4 +- src/main.rs | 2 +- 6 files changed, 464 insertions(+), 2 deletions(-) create mode 100644 data/day10/example01.txt create mode 100644 data/day10/expected01.txt create mode 100644 data/day10/input.txt create mode 100644 src/days/day10/mod.rs diff --git a/data/day10/example01.txt b/data/day10/example01.txt new file mode 100644 index 0000000..94cd0a8 --- /dev/null +++ b/data/day10/example01.txt @@ -0,0 +1,146 @@ +addx 15 +addx -11 +addx 6 +addx -3 +addx 5 +addx -1 +addx -8 +addx 13 +addx 4 +noop +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx 5 +addx -1 +addx -35 +addx 1 +addx 24 +addx -19 +addx 1 +addx 16 +addx -11 +noop +noop +addx 21 +addx -15 +noop +noop +addx -3 +addx 9 +addx 1 +addx -3 +addx 8 +addx 1 +addx 5 +noop +noop +noop +noop +noop +addx -36 +noop +addx 1 +addx 7 +noop +noop +noop +addx 2 +addx 6 +noop +noop +noop +noop +noop +addx 1 +noop +noop +addx 7 +addx 1 +noop +addx -13 +addx 13 +addx 7 +noop +addx 1 +addx -33 +noop +noop +noop +addx 2 +noop +noop +noop +addx 8 +noop +addx -1 +addx 2 +addx 1 +noop +addx 17 +addx -9 +addx 1 +addx 1 +addx -3 +addx 11 +noop +noop +addx 1 +noop +addx 1 +noop +noop +addx -13 +addx -19 +addx 1 +addx 3 +addx 26 +addx -30 +addx 12 +addx -1 +addx 3 +addx 1 +noop +noop +noop +addx -9 +addx 18 +addx 1 +addx 2 +noop +noop +addx 9 +noop +noop +noop +addx -1 +addx 2 +addx -37 +addx 1 +addx 3 +noop +addx 15 +addx -21 +addx 22 +addx -6 +addx 1 +noop +addx 2 +addx 1 +noop +addx -10 +noop +noop +addx 20 +addx 1 +addx 2 +addx 2 +addx -6 +addx -11 +noop +noop +noop \ No newline at end of file diff --git a/data/day10/expected01.txt b/data/day10/expected01.txt new file mode 100644 index 0000000..ecee815 --- /dev/null +++ b/data/day10/expected01.txt @@ -0,0 +1,6 @@ +## ## ## ## ## ## ## ## ## ## +### ### ### ### ### ### ### +#### #### #### #### #### +##### ##### ##### ##### +###### ###### ###### #### +####### ####### ####### \ No newline at end of file diff --git a/data/day10/input.txt b/data/day10/input.txt new file mode 100644 index 0000000..871fb66 --- /dev/null +++ b/data/day10/input.txt @@ -0,0 +1,143 @@ +noop +addx 26 +addx -21 +addx 2 +addx 3 +noop +noop +addx 23 +addx -17 +addx -1 +noop +noop +addx 7 +noop +addx 3 +addx 1 +noop +noop +addx 2 +noop +addx 7 +noop +addx -12 +addx 13 +addx -38 +addx 5 +addx 34 +addx -2 +addx -29 +addx 2 +addx 5 +addx 2 +addx 3 +addx -2 +addx -1 +addx 8 +addx 2 +addx 6 +addx -26 +addx 23 +addx -26 +addx 33 +addx 2 +addx -37 +addx -1 +addx 1 +noop +noop +noop +addx 5 +addx 5 +addx 3 +addx -2 +addx 2 +addx 5 +addx 5 +noop +noop +addx -2 +addx 4 +noop +noop +noop +addx 3 +noop +noop +addx 7 +addx -1 +addx -35 +addx -1 +addx 5 +addx 3 +noop +addx 4 +noop +noop +noop +noop +noop +addx 5 +addx 1 +noop +noop +noop +addx -7 +addx 12 +addx 2 +addx 7 +noop +addx -2 +noop +noop +addx 7 +addx 2 +addx -39 +noop +noop +addx 5 +addx 2 +addx -4 +addx 25 +addx -18 +addx 7 +noop +addx -2 +addx 5 +addx 2 +addx 6 +addx -5 +addx 2 +addx -22 +addx 29 +addx -21 +addx -7 +addx 31 +addx 2 +noop +addx -36 +addx 1 +addx 5 +noop +addx 1 +addx 4 +addx 5 +noop +noop +noop +addx 3 +noop +addx -13 +addx 15 +noop +addx 5 +noop +addx 1 +noop +addx 3 +addx 2 +addx 4 +addx 3 +noop +addx -3 +noop \ No newline at end of file diff --git a/src/days/day10/mod.rs b/src/days/day10/mod.rs new file mode 100644 index 0000000..13bfdcf --- /dev/null +++ b/src/days/day10/mod.rs @@ -0,0 +1,165 @@ +use super::template::{DayTrait, ResultType}; +use std::{num::ParseIntError, slice::Iter}; +use thiserror::Error; + +const DAY_NUMBER: usize = 10; + +pub struct Day; + +impl DayTrait for Day { + fn get_day_number(&self) -> usize { + DAY_NUMBER + } + + fn part1(&self, lines: &[String]) -> anyhow::Result { + let instructions = lines + .iter() + .map(|line| Instruction::parse(line)) + .collect::, _>>()?; + let result = CpuCycles::signal_strength(&instructions, &[20, 60, 100, 140, 180, 220]); + Ok(ResultType::Integer(result as i64)) + } + + fn part2(&self, lines: &[String]) -> anyhow::Result { + let instructions = lines + .iter() + .map(|line| Instruction::parse(line)) + .collect::, _>>()?; + let result = CpuCycles::draw(&instructions); + Ok(ResultType::Lines(result)) + } +} + +#[derive(Debug, Error)] +enum CpuError { + #[error("unknown instruction: {0}")] + UnknownInstruction(String), + + #[error("could not parse Number")] + InvalidInteger(#[from] ParseIntError), +} + +enum Instruction { + Add(i32), + Noop, +} + +impl Instruction { + pub fn parse(line: &str) -> Result { + if line == "noop" { + Ok(Instruction::Noop) + } else if line.starts_with("addx") { + let value = line[5..].parse()?; + Ok(Instruction::Add(value)) + } else { + Err(CpuError::UnknownInstruction(line.to_owned())) + } + } +} + +struct CpuCycles<'a> { + register: i32, + instructions: Iter<'a, Instruction>, + current: Option, +} + +impl<'a> CpuCycles<'a> { + pub fn create(instructions: &'a [Instruction]) -> Self { + Self { + instructions: instructions.iter(), + register: 1, + current: None, + } + } + + pub fn signal_strength(instructions: &'a [Instruction], to_collect: &[usize]) -> i32 { + CpuCycles::create(instructions) + .enumerate() + .filter_map(|(cycle, register)| { + if to_collect.contains(&(cycle + 1)) { + Some(register * (cycle + 1) as i32) + } else { + None + } + }) + .sum() + } + + pub fn draw(instructions: &'a [Instruction]) -> Vec { + let mut result = Vec::new(); + let mut line = "".to_owned(); + for (cycle, sprite) in CpuCycles::create(instructions).enumerate() { + let cycle = (cycle % 40) as i32; + if (sprite - cycle).abs() <= 1 { + line.push('#'); + } else { + line.push(' '); + } + if cycle == 39 { + result.push(line.to_owned()); + line = "".to_owned(); + } + } + result + } +} + +impl<'a> Iterator for CpuCycles<'a> { + type Item = i32; + + fn next(&mut self) -> Option { + if let Some(value) = self.current { + let start_register = self.register; + self.register += value; + self.current = None; + Some(start_register) + } else if let Some(instruction) = self.instructions.next() { + match instruction { + Instruction::Add(value) => self.current = Some(*value), + Instruction::Noop => {} + } + Some(self.register) + } else { + None + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::common::file::read_lines; + use anyhow::Result; + + #[test] + fn test_simple() -> Result<()> { + let instructions = vec![Instruction::Noop, Instruction::Add(3), Instruction::Add(-5)]; + let expected = vec![1, 1, 1, 4, 4]; + let result = CpuCycles::create(&instructions).collect::>(); + assert_eq!(result, expected); + + Ok(()) + } + + #[test] + fn test_part1() -> Result<()> { + let day = Day {}; + let lines = read_lines(day.get_day_number(), "example01.txt")?; + let expected = ResultType::Integer(13140); + let result = day.part1(&lines)?; + assert_eq!(result, expected); + + Ok(()) + } + + #[test] + fn test_part2() -> Result<()> { + let day = Day {}; + let lines = read_lines(day.get_day_number(), "example01.txt")?; + let expected = ResultType::Lines(read_lines(day.get_day_number(), "expected01.txt")?); + let result = day.part2(&lines)?; + assert_eq!(result, expected); + + Ok(()) + } +} diff --git a/src/days/mod.rs b/src/days/mod.rs index 4f4726e..a9252e7 100644 --- a/src/days/mod.rs +++ b/src/days/mod.rs @@ -7,6 +7,7 @@ mod day06; mod day07; mod day08; mod day09; +mod day10; mod template; pub use template::DayTrait; @@ -16,7 +17,7 @@ pub mod day_provider { use super::*; use thiserror::Error; - const MAX_DAY: usize = 9; + const MAX_DAY: usize = 10; pub fn get_day(day_num: usize) -> Result, ProviderError> { match day_num { @@ -29,6 +30,7 @@ pub mod day_provider { 7 => Ok(Box::new(day07::Day)), 8 => Ok(Box::new(day08::Day)), 9 => Ok(Box::new(day09::Day)), + 10 => Ok(Box::new(day10::Day)), _ => Err(ProviderError::InvalidNumber(day_num)), } } diff --git a/src/main.rs b/src/main.rs index ff4cd7f..7e90532 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,7 @@ fn output(day: usize, part: usize, result: ResultType, time: Duration) { time.as_secs_f32() ); for line in &value[1..] { - println!(" part : {line}"); + println!(" {line}"); } } ResultType::Nothing => {}