From 7f8c298d7d4420802809068960aa04e8e491f123 Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Sun, 4 Dec 2022 14:02:22 -0600 Subject: feat: impl day 3 --- src/day_3.rs | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 +- src/main.rs | 3 +- 3 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 src/day_3.rs (limited to 'src') diff --git a/src/day_3.rs b/src/day_3.rs new file mode 100644 index 0000000..5335624 --- /dev/null +++ b/src/day_3.rs @@ -0,0 +1,123 @@ +use std::{ops::Deref, str::FromStr}; + +use anyhow::{anyhow, Context, Result}; + +pub fn day_3() -> Result<()> { + let input = include_str!("../input/day_3.txt"); + + println!("day 3"); + println!("part 1: {}", part_1(input)?); + println!("part 2: {}", part_2(input)?); + + Ok(()) +} + +trait Priority { + fn priority(self) -> Result; +} + +impl Priority for char { + fn priority(self) -> Result { + match self as u8 { + c @ 65..=90 => Ok(c - 65 + 27), + c @ 97..=122 => Ok(c - 97 + 1), + c => Err(anyhow!("failed to get priority of {}", c as char)), + } + } +} + +#[derive(Debug, Clone)] +struct Backpack(Vec); + +impl Backpack { + fn get_local_union(self) -> Result { + let (left, right) = self.split_at(self.len() / 2); + left.iter() + .cloned() + .find(|&item| right.contains(&item)) + .context(format!("Failed to find union in {:?}", &self)) + } + + fn get_group_union(group: &mut Vec) -> Result { + group + .split_first_mut() + .and_then(|(first, others)| { + first + .iter() + .cloned() + .find(|item| others.iter_mut().all(|b| b.contains(item))) + }) + .context(format!("Failed to find union in {:?}", group)) + } +} +impl Deref for Backpack { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::str::FromStr for Backpack { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + Ok(Backpack(s.as_bytes().iter().map(|c| *c as char).collect())) + } +} + +pub fn part_1(input: &str) -> Result { + input + .lines() + .map(Backpack::from_str) + .try_collect::>()? + .into_iter() + .map(|b| b.get_local_union()) + .try_collect::>()? + .into_iter() + .try_fold(0, |sum, c| c.priority().map(|p| sum + p as usize)) +} + +pub fn part_2(input: &str) -> Result { + let lines: Vec<&str> = input.lines().collect(); + lines.as_slice().chunks(3).try_fold(0, |acc, g| { + let mut group = g + .iter() + .cloned() + .map(Backpack::from_str) + .try_collect::>()?; + + Ok(Backpack::get_group_union(&mut group)?.priority()? as usize + acc) + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_1_example() -> Result<()> { + let test_input = r#"vJrwpWtwJgWrhcsFMMfFFhFp +jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL +PmmdzqPrVvPwwTWBwg +wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn +ttgJtRGJQctTZtZT +CrZsJsPPZsGzwwsLwLmpwMDw"#; + + assert_eq!(157, part_1(test_input)?); + Ok(()) + } + + #[test] + fn test_part_2_example() -> Result<()> { + let test_input = r#"vJrwpWtwJgWrhcsFMMfFFhFp +jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL +PmmdzqPrVvPwwTWBwg +wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn +ttgJtRGJQctTZtZT +CrZsJsPPZsGzwwsLwLmpwMDw"#; + + assert_eq!(70, part_2(test_input)?); + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 1d417d7..e0ca15f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,6 @@ +#![feature(iterator_try_collect)] + pub mod day_1; pub mod day_2; -pub mod day_3 {} +pub mod day_3; pub mod day_4; diff --git a/src/main.rs b/src/main.rs index fc0ca4b..b06c9d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,10 @@ -use advent_of_code_2022::{day_1, day_2, day_4}; +use advent_of_code_2022::{day_1, day_2, day_4, day_3}; use anyhow::Result; fn main() -> Result<()> { day_1::day_1()?; day_2::day_2()?; + day_3::day_3()?; day_4::day_4()?; Ok(()) -- cgit v1.2.3-70-g09d2