Cleanup for 2022 day 3: Turned into a lib and introduced parse errors

This commit is contained in:
Burnus 2023-05-12 20:53:04 +02:00
parent 14918f6f5c
commit cc5d08c90d
3 changed files with 86 additions and 68 deletions

View file

@ -0,0 +1,86 @@
use std::collections::HashSet;
use core::fmt::Display;
#[derive(Debug, PartialEq, Eq)]
pub enum ParseError {
InvalidToken(char),
}
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidToken(t) => write!(f, "Invalid Item encountered: {t}"),
}
}
}
pub fn run(input: &str) -> Result<(u32, u32), ParseError> {
let first = input.lines().map(duplicate_prio).sum::<Result<u32, ParseError>>()?;
let second = get_badge_prios(input)?;
Ok((first, second))
}
fn item_priority(item: char) -> Result<u32, ParseError> {
match item {
lc if lc.is_ascii_lowercase() => Ok(lc as u32 - 96),
uc if uc.is_ascii_uppercase() => Ok(uc as u32 - 38),
e => Err(ParseError::InvalidToken(e)),
}
}
fn duplicate_prio(line: &str) -> Result<u32, ParseError> {
if line.len() % 2 != 0 {
panic!("Odd number of items!");
}
let comp1 = &line[..line.len()/2].chars().collect::<HashSet<char>>();
let comp2 = &line[line.len()/2..].chars().collect::<HashSet<char>>();
comp1.iter()
.filter(|c| comp2.contains(*c))
.map(|c| item_priority(*c))
.sum()
}
fn badge_prio(e1: &str, e2: &str, e3: &str) -> Result<u32, ParseError> {
e1.chars()
.filter(|c| e2.contains(*c) && e3.contains(*c))
.map(item_priority)
.max_by(|a, b| match (a, b) {
(Ok(a), Ok(b)) => a.cmp(b),
(Ok(_), _err) => std::cmp::Ordering::Less,
(_err, _) => std::cmp::Ordering::Greater,
})
.unwrap()
}
fn get_badge_prios(list: &str) -> Result<u32, ParseError> {
let mut badge_prios = 0;
let mut iter = list.lines();
while let (Some(e1), Some(e2), Some(e3)) = (iter.next(), iter.next(), iter.next()) {
let this_badge = badge_prio(e1, e2, e3);
badge_prios += this_badge?;
}
Ok(badge_prios)
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::read_to_string;
fn read_file(name: &str) -> String {
read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string()
}
#[test]
fn test_sample() {
let sample_input = read_file("tests/sample_input");
assert_eq!(run(&sample_input), Ok((157, 70)));
}
#[test]
fn test_challenge() {
let challenge_input = read_file("tests/challenge_input");
assert_eq!(run(&challenge_input), Ok((7746, 2604)));
}
}

View file

@ -1,68 +0,0 @@
use std::collections::HashSet;
use std::fs;
fn read_file(path: &str) -> String {
fs::read_to_string(path)
.expect("File not Found")
}
fn item_priority(item: char) -> u32 {
match item {
lc if ('a'..='z').contains(&lc) => lc as u32 - 96,
uc if ('A'..='Z').contains(&uc) => uc as u32 - 38,
_ => panic!("Unexpected Token"),
}
}
fn duplicate_prio(line: &str) -> u32 {
if line.len() % 2 != 0 {
panic!("Odd number of items!");
}
let comp1 = &line[..line.len()/2].chars().collect::<HashSet<char>>();
let comp2 = &line[line.len()/2..].chars().collect::<HashSet<char>>();
comp1.iter()
.filter(|c| comp2.contains(*c))
.map(|c| item_priority(*c))
.sum()
}
fn badge_prio(e1: &str, e2: &str, e3: &str) -> u32 {
e1.chars()
.filter(|c| e2.contains(*c) && e3.contains(*c))
.map(item_priority)
.max()
.unwrap()
}
fn get_badge_prios(list: &str) -> u32 {
let mut badge_prios = 0;
let mut iter = list.lines();
while let (Some(e1), Some(e2), Some(e3)) = (iter.next(), iter.next(), iter.next()) {
badge_prios += badge_prio(e1, e2, e3);
}
badge_prios
}
fn main() {
let contents = read_file("input");
let duplicate_prios: u32 = contents.lines().map(duplicate_prio).sum();
let badge_prios = get_badge_prios(&contents);
println!("Priorities of Duplicates: {duplicate_prios}");
println!("Badge Priorities: {badge_prios}");
}
#[test]
fn sample_input() {
let contents = read_file("tests/sample_input");
assert_eq!(contents.lines().map(duplicate_prio).sum::<u32>(), 157);
assert_eq!(get_badge_prios(&contents), 70);
}
#[test]
fn challenge_input() {
let contents = read_file("tests/input");
assert_eq!(contents.lines().map(duplicate_prio).sum::<u32>(), 7746);
assert_eq!(get_badge_prios(&contents), 2604);
}