diff options
author | Toby Vincent <tobyv@tobyvin.dev> | 2023-12-01 18:17:33 -0600 |
---|---|---|
committer | Toby Vincent <tobyv@tobyvin.dev> | 2023-12-01 18:17:33 -0600 |
commit | 8525793927ad76a5ffa4a5f522b9a80c1a637644 (patch) | |
tree | 3b502ed3f841ac3e7498f8c4c802b86effeb97a2 /src |
feat: impl day 1
Diffstat (limited to 'src')
-rw-r--r-- | src/day_01.rs | 103 | ||||
-rw-r--r-- | src/lib.rs | 27 | ||||
-rw-r--r-- | src/main.rs | 7 |
3 files changed, 137 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)?)) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a895a9d --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,27 @@ +pub mod day_01; + +pub trait Solution: Problem { + type Answer1: std::fmt::Display + Default; + + type Answer2: std::fmt::Display + Default; + + fn part_1(input: &str) -> anyhow::Result<Self::Answer1>; + + fn part_2(input: &str) -> anyhow::Result<Self::Answer2>; + + fn solve() -> anyhow::Result<()> { + println!("Day {}.1", Self::DAY); + println!("{}\n", Self::part_1(Self::INPUT)?); + + println!("Day {}.2", Self::DAY); + println!("{}\n", Self::part_2(Self::INPUT)?); + + Ok(()) + } +} + +pub trait Problem { + const DAY: u8; + + const INPUT: &'static str; +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..689a756 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,7 @@ +use aoc_2023::{day_01::Day01, Solution}; + +fn main() -> anyhow::Result<()> { + Day01::solve()?; + + Ok(()) +} |