diff options
Diffstat (limited to 'src/day_01.rs')
-rw-r--r-- | src/day_01.rs | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/day_01.rs b/src/day_01.rs new file mode 100644 index 0000000..9c0310e --- /dev/null +++ b/src/day_01.rs @@ -0,0 +1,103 @@ +use anyhow::Context; + +use crate::{Problem, Solution}; + +pub struct Day01; + +impl Problem for Day01 { + const DAY: u8 = 1; + + const INPUT: &'static str = include_str!("../input/day_01.txt"); +} + +impl Solution for Day01 { + type Answer1 = usize; + + type Answer2 = usize; + + fn part_1(input: &str) -> anyhow::Result<Self::Answer1> { + input.trim().split('\n').try_fold(0, |acc, line| { + let first = line + .chars() + .find_map(|c| c.to_digit(10).map(|n| n as usize)) + .context("Failed to find first number")?; + + let last = line + .chars() + .rev() + .find_map(|c| c.to_digit(10).map(|n| n as usize)) + .unwrap_or(first); + + Ok(acc + first * 10 + last) + }) + } + + fn part_2(input: &str) -> anyhow::Result<Self::Answer2> { + let words = [ + "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", + ]; + + input.trim().split('\n').try_fold(0, |acc, line| { + let mut buf = String::new(); + let first = line + .chars() + .find_map(|c| { + buf.push(c); + words + .iter() + .enumerate() + .find_map(|(n, w)| buf.contains(w).then_some(n)) + .or_else(|| c.to_digit(10).map(|n| n as usize)) + }) + .context("Failed to find first number")?; + + buf.clear(); + let last = line + .chars() + .rev() + .find_map(|c| { + buf.insert(0, c); + words + .iter() + .enumerate() + .find_map(|(n, w)| buf.contains(w).then_some(n)) + .or_else(|| c.to_digit(10).map(|n| n as usize)) + }) + .unwrap_or(first); + + Ok(acc + first * 10 + last) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_1() -> anyhow::Result<()> { + let input = indoc::indoc! {" + 1abc2 + pqr3stu8vwx + a1b2c3d4e5f + treb7uchet + "}; + + Ok(assert_eq!(142, Day01::part_1(input)?)) + } + + #[test] + fn test_part_2() -> anyhow::Result<()> { + let input = indoc::indoc! {" + two1nine + eightwothree + abcone2threexyz + xtwone3four + 4nineeightseven2 + zoneight234 + 7pqrstsixteen + "}; + + Ok(assert_eq!(281, Day01::part_2(input)?)) + } +} |