diff --git a/2022/day3/rust/src/main.rs b/2022/day3/rust/src/main.rs index 2f9b82c..4e432ce 100644 --- a/2022/day3/rust/src/main.rs +++ b/2022/day3/rust/src/main.rs @@ -1,6 +1,6 @@ use std::{ - collections::HashSet, io::{stdin, Read}, + ops::{BitAnd, BitOr}, }; fn item_priority(item: char) -> u32 { @@ -11,9 +11,48 @@ fn item_priority(item: char) -> u32 { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct ItemSet(u64); + +impl ItemSet { + pub fn priority_of_single_item(self) -> Option { + if self.0.is_power_of_two() { + Some(self.0.trailing_zeros()) + } else { + None + } + } +} + +impl FromIterator for ItemSet { + fn from_iter>(iter: T) -> Self { + Self( + iter.into_iter() + .map(item_priority) + .fold(0, |acc, i| acc | (1 << i)), + ) + } +} + +impl BitOr for ItemSet { + type Output = Self; + + fn bitor(self, rhs: Self) -> Self::Output { + Self(BitOr::bitor(self.0, rhs.0)) + } +} + +impl BitAnd for ItemSet { + type Output = Self; + + fn bitand(self, rhs: Self) -> Self::Output { + Self(BitAnd::bitand(self.0, rhs.0)) + } +} + struct Rucksack { - left: HashSet, - right: HashSet, + left: ItemSet, + right: ItemSet, } fn main() { @@ -26,8 +65,8 @@ fn main() { let (left, right) = line.split_at(line.len() / 2); assert_eq!(left.len(), right.len()); - let left: HashSet<_> = left.chars().collect(); - let right: HashSet<_> = right.chars().collect(); + let left = left.chars().collect(); + let right = right.chars().collect(); Rucksack { left, right } }) @@ -35,21 +74,20 @@ fn main() { let sum1: u32 = sacks .iter() - .map(|sack| item_priority(*sack.left.intersection(&sack.right).next().unwrap())) + .map(|sack| (sack.left & sack.right).priority_of_single_item().unwrap()) .sum(); let sum2: u32 = sacks .chunks(3) .into_iter() .map(|sacks| { - let common = sacks + sacks .iter() - .map(|sack| &sack.left | &sack.right) - .reduce(|a, b| &a & &b) - .unwrap(); - assert_eq!(common.len(), 1); - - item_priority(common.into_iter().next().unwrap()) + .map(|sack| sack.left | sack.right) + .reduce(BitAnd::bitand) + .unwrap() + .priority_of_single_item() + .unwrap() }) .sum();