Cleanup for 2022 day 3: Turned into a lib and introduced parse errors
This commit is contained in:
parent
14918f6f5c
commit
cc5d08c90d
3 changed files with 86 additions and 68 deletions
86
2022/day03-rucksack_reorganization/src/lib.rs
Normal file
86
2022/day03-rucksack_reorganization/src/lib.rs
Normal 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)));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue