diff options
Diffstat (limited to 'aoc_2022/src/day_10.rs')
-rw-r--r-- | aoc_2022/src/day_10.rs | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/aoc_2022/src/day_10.rs b/aoc_2022/src/day_10.rs new file mode 100644 index 0000000..9c5179d --- /dev/null +++ b/aoc_2022/src/day_10.rs @@ -0,0 +1,132 @@ +use std::{fmt::Display, str::FromStr}; + +use aoc::{Problem, Solution}; + +enum Instruction { + Addx(isize), + Noop, +} + +impl From<Instruction> for usize { + fn from(value: Instruction) -> Self { + match value { + Instruction::Addx(_) => 2, + Instruction::Noop => 1, + } + } +} + +impl Display for Instruction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Instruction::Addx(x) => write!(f, "addx {}", x), + Instruction::Noop => write!(f, "noop"), + } + } +} + +impl FromStr for Instruction { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "noop" => Ok(Self::Noop), + s if s.contains("addx") => s + .split_once(' ') + .ok_or_else(|| anyhow::anyhow!("Incorrect format for addx")) + .and_then(|(_, n)| n.parse().map_err(Into::into)) + .map(Self::Addx), + s => Err(anyhow::anyhow!("Unknown instruction: {s}")), + } + } +} + +fn generate_states(input: &str) -> Vec<isize> { + let mut register = 1; + input + .lines() + .flat_map(Instruction::from_str) + .flat_map(move |i| { + let mut states = vec![register]; + if let Instruction::Addx(x) = i { + states.push(register); + register += x; + } + states + }) + .collect() +} + +pub struct Day10; + +impl Problem for Day10 { + const DAY: u8 = 10; + + const INPUT: &'static str = include_str!("../input/day_10.txt"); +} + +impl Solution for Day10 { + type Answer1 = isize; + + type Answer2 = String; + + fn part_1(input: &str) -> Result<Self::Answer1, anyhow::Error> { + let signal_strength = generate_states(input) + .iter() + .enumerate() + .skip(19) + .step_by(40) + .map(|(cycle, register)| (cycle as isize + 1) * register) + .sum(); + + Ok(signal_strength) + } + + fn part_2(input: &str) -> Result<Self::Answer2, anyhow::Error> { + let output = generate_states(input) + .chunks(40) + .map(|chunk| { + chunk.iter().enumerate().map(|(draw, sprite)| { + if (sprite - 1..=sprite + 1).contains(&(draw as isize)) { + '#' + } else { + '.' + } + }) + }) + .fold(String::new(), |mut acc, line| { + acc.extend(line); + acc.push('\n'); + acc + }); + + Ok(output) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use pretty_assertions::assert_eq; + + const TEST_INPUT: &str = include_str!("../input/day_10_example.txt"); + + #[test] + fn test_part_1_example() -> Result<(), anyhow::Error> { + Ok(assert_eq!(13140, Day10::part_1(TEST_INPUT)?)) + } + + #[test] + fn test_part_2_example() -> Result<(), anyhow::Error> { + let test_output = indoc::indoc! {r#" + ##..##..##..##..##..##..##..##..##..##.. + ###...###...###...###...###...###...###. + ####....####....####....####....####.... + #####.....#####.....#####.....#####..... + ######......######......######......#### + #######.......#######.......#######..... + "#}; + + Ok(assert_eq!(test_output, Day10::part_2(TEST_INPUT)?)) + } +} |