advent/2022/src/day3.rs
2022-12-04 20:38:46 -08:00

103 lines
2.4 KiB
Rust

use std::str::FromStr;
const DATA: &'static str = include_str!("../data/day3.txt");
// const DATA: &'static str = "
// vJrwpWtwJgWrhcsFMMfFFhFp
// jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
// PmmdzqPrVvPwwTWBwg
// wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
// ttgJtRGJQctTZtZT
// CrZsJsPPZsGzwwsLwLmpwMDw
// ";
#[derive(Debug)]
enum DataError {
Imbalanced,
UnknownValue,
NoDuplicate,
NoTriplicate,
ShortGroup,
}
struct Rucksack {
left: Vec<u8>,
right: Vec<u8>,
}
impl Rucksack {
fn find_duplicate(&self) -> Option<u8> {
// pretty sure this is faster than hash set, given the sizes involved
self.left.iter()
.find(|c| self.right.contains(c))
.map(|c| *c)
}
fn iter_all(&self) -> impl Iterator<Item = &u8> {
self.left.iter().chain(self.right.iter())
}
fn contains(&self, v: u8) -> bool {
self.left.contains(&v) || self.right.contains(&v)
}
}
impl FromStr for Rucksack {
type Err = DataError;
fn from_str(line: &str) -> Result<Rucksack, DataError> {
let line = line.trim();
if line.len() % 2 != 0 {
return Err(DataError::Imbalanced);
}
let (a, b) = line.as_bytes().split_at(line.len() / 2);
Ok(Rucksack {
left: a.into(),
right: b.into(),
})
}
}
fn priority(c: u8) -> Result<u64, DataError> {
match c {
// lowercase
97..=122 => Ok(c as u64 - 96),
// uppercase
65..=90 => Ok(c as u64 - 38),
_ => Err(DataError::UnknownValue),
}
}
fn main() -> Result<(), DataError> {
let mut dup_total = 0;
let rucks = DATA.trim()
.split("\n")
.map(|line| Rucksack::from_str(line))
.collect::<Result<Vec<Rucksack>, DataError>>()?;
for ruck in rucks.iter() {
let dup = ruck.find_duplicate()
.ok_or(DataError::NoDuplicate)?;
dup_total += priority(dup)?;
}
println!("Part 1: {dup_total}");
let mut groups_total = 0;
for (idx, ruck) in rucks.iter().enumerate().step_by(3) {
if idx > rucks.len() - 3 {
return Err(DataError::ShortGroup);
}
let badge = *ruck.iter_all()
.find(|&v| rucks[idx + 1].contains(*v) && rucks[idx + 2].contains(*v))
.ok_or(DataError::NoTriplicate)?;
groups_total += priority(badge)?;
}
println!("Part 2: {groups_total}");
Ok(())
}