summaryrefslogtreecommitdiffstats
path: root/aoc_2022/src/day_10.rs
diff options
context:
space:
mode:
Diffstat (limited to 'aoc_2022/src/day_10.rs')
-rw-r--r--aoc_2022/src/day_10.rs132
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)?))
+ }
+}