diff --git a/src/day03.rs b/src/day03.rs new file mode 100644 index 0000000..0f2e913 --- /dev/null +++ b/src/day03.rs @@ -0,0 +1,101 @@ +use std::str::FromStr; + +use aoc_runner_derive::{aoc, aoc_generator}; + +#[derive(Debug, Default)] +pub struct Rucksack { + first_half: Vec, + second_half: Vec, +} + +#[derive(Debug, Copy, Clone)] +pub struct NoItemInBothHalves; + +#[derive(Debug, Copy, Clone)] +pub struct NoCommonItem; + +impl Rucksack { + fn find_item_in_both_halves(&self) -> Result { + for &item in &self.first_half { + if self.second_half.contains(&item) { + return Ok(item); + } + } + Err(NoItemInBothHalves) + } + + fn has_item(&self, item: u8) -> bool { + self.first_half.contains(&item) | self.second_half.contains(&item) + } + + fn find_common_item(&self, others: &[Rucksack]) -> Result { + for &item in self.first_half.iter().chain(&self.second_half) { + if others.iter().all(|rucksack| rucksack.has_item(item)) { + return Ok(item); + } + } + Err(NoCommonItem) + } +} + +#[derive(Debug, Copy, Clone)] +pub struct InvalidRucksack; + +impl FromStr for Rucksack { + type Err = InvalidRucksack; + + fn from_str(s: &str) -> Result { + let mut priorities = s + .chars() + .map(|ch| { + if !ch.is_ascii_alphabetic() { + Err(InvalidRucksack) + } else if ch.is_ascii_uppercase() { + Ok(ch as u8 - b'A' + 27) + } else { + Ok(ch as u8 - b'a' + 1) + } + }) + .collect::, _>>()?; + let second_half = priorities.split_off(priorities.len() / 2); + Ok(Rucksack { + first_half: priorities, + second_half, + }) + } +} + +#[aoc_generator(day3, part1)] +pub fn input_generator_part1(input: &str) -> Vec { + input.lines().map(|l| l.parse().unwrap()).collect() +} + +#[aoc_generator(day3, part2)] +pub fn input_generator_part2(input: &str) -> Vec> { + input + .lines() + .collect::>() + .chunks(3) + .map(|list| { + list.iter() + .map(|el| el.parse().unwrap()) + .collect::>() + }) + .collect::>() +} + +#[aoc(day3, part1)] +pub fn solve_part1(input: &[Rucksack]) -> u64 { + input + .iter() + .map(|rucksack| rucksack.find_item_in_both_halves().unwrap() as u64) + .sum() +} + +#[aoc(day3, part2)] +pub fn solve_part2(input: &[Vec]) -> u64 { + input + .iter() + .map(|rucksacks| rucksacks[0].find_common_item(&rucksacks[1..]).unwrap() as u64) + .sum() +} diff --git a/src/lib.rs b/src/lib.rs index 4256064..5616faa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,5 +2,6 @@ use aoc_runner_derive::aoc_lib; pub mod day01; pub mod day02; +pub mod day03; aoc_lib! { year = 2022 }