diff --git a/src/year2022/day03.rs b/src/year2022/day03.rs index 701ff4b..2b17a7b 100644 --- a/src/year2022/day03.rs +++ b/src/year2022/day03.rs @@ -1,31 +1,39 @@ -use std::collections::BTreeSet; - -fn char_to_score(c: char) -> u32 { - match c { - 'a'..='z' => c as u32 - 96, - 'A'..='Z' => c as u32 - 38, - _ => unreachable!(), +/// Number of trailing zeros tells us which bit is set and there should only be one set +/// Do some math to convert to the needed priority +fn bits_to_priority(b: u64) -> u32 { + let trailing = b.trailing_zeros(); + match trailing { + 0..=25 => trailing + 27, + 32..=57 => trailing - 31, + _ => unreachable!(""), } } +/// For each byte in the string offset it towards 0 +/// to make it fit in u64 and set a bit at the position of its value +fn to_bits(s: &str) -> u64 { + s.bytes().fold(0, |a, v| a | 1 << (v - 65)) +} + pub fn part1(input: &str) -> impl std::fmt::Display { input .lines() .map(|l| l.split_at(l.len() / 2)) - .map(|(l, r)| { - let a: BTreeSet = l.chars().collect(); - let b: BTreeSet = r.chars().collect(); - a.intersection(&b) - .next() - .expect("We know there is at least one") - .clone() - }) - .map(char_to_score) + .map(|(l, r)| bits_to_priority(to_bits(l) & to_bits(r))) .sum::() } pub fn part2(input: &str) -> impl std::fmt::Display { - "" + let mut lines = input.lines(); + let mut sum = 0; + + while let Some(l1) = lines.next() { + let l2 = lines.next().expect("second is guaranteed to be there"); + let l3 = lines.next().expect("third is guaranteed to be there"); + + sum += bits_to_priority(to_bits(l1) & to_bits(l2) & to_bits(l3)); + } + sum } #[test]