From 02973bde28a8a23d2657accda9b76bf9b6ebf61c Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sat, 3 Dec 2022 13:59:11 +0200 Subject: Day 3 --- 2022/src/bin/day_3.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 2022/src/bin/day_3.rs (limited to '2022/src/bin') diff --git a/2022/src/bin/day_3.rs b/2022/src/bin/day_3.rs new file mode 100644 index 0000000..ec2d5e2 --- /dev/null +++ b/2022/src/bin/day_3.rs @@ -0,0 +1,100 @@ +use nom::{ + character::complete::{line_ending, satisfy}, + combinator::map, + multi::{many1, separated_list1}, + IResult, +}; +use std::{collections::BTreeSet, fs, iter::Iterator}; + +fn main() -> Result<(), Box> { + let input = fs::read_to_string("inputs/day_3.txt")?; + let rucksacks = Rucksacks::parser(&input).unwrap().1; + dbg!(rucksacks.disorder_sum()); + dbg!(rucksacks.groups_sum()); + Ok(()) +} + +#[derive(Debug, PartialEq, Eq, Clone)] +struct Rucksacks(Vec); + +#[derive(Debug, PartialEq, Eq, Clone)] +struct Rucksack { + front: BTreeSet, + back: BTreeSet, +} + +#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)] +struct ItemType(char); + +impl Rucksacks { + fn parser(input: &str) -> IResult<&str, Rucksacks> { + map(separated_list1(line_ending, Rucksack::parser), Rucksacks)(input) + } + + fn disorder_sum(&self) -> u32 { + self.0.iter().map(|r| r.intersection_priority()).sum() + } + + fn groups_sum(&self) -> u32 { + self.0 + .chunks(3) + .map(|group| { + let mut overlap = group[0].union(); + for m in group.iter().skip(1) { + overlap = overlap.intersection(&m.union()).cloned().collect(); + } + overlap.iter().map(|c| c.priority()).sum::() + }) + .sum() + } +} + +impl Rucksack { + fn parser(input: &str) -> IResult<&str, Rucksack> { + map(many1(ItemType::parser), Rucksack::new)(input) + } + + fn new(contents: Vec) -> Rucksack { + let mid = contents.len() / 2; + let front_str = &contents[0..mid]; + let back_str = &contents[mid..]; + + let mut front = BTreeSet::new(); + for c in front_str { + front.insert(c.clone()); + } + + let mut back = BTreeSet::new(); + for c in back_str { + back.insert(c.clone()); + } + + Rucksack { front, back } + } + + fn intersection(&self) -> BTreeSet { + self.front.intersection(&self.back).cloned().collect() + } + + fn union(&self) -> BTreeSet { + self.front.union(&self.back).cloned().collect() + } + + fn intersection_priority(&self) -> u32 { + self.intersection().iter().map(|c| c.priority()).sum() + } +} + +impl ItemType { + fn parser(input: &str) -> IResult<&str, ItemType> { + map(satisfy(|c| c.is_alphabetic()), ItemType)(input) + } + + fn priority(&self) -> u32 { + if self.0.is_uppercase() { + (self.0 as u32 - 'A' as u32) + 27 + } else { + (self.0 as u32 - 'a' as u32) + 1 + } + } +} -- cgit v1.2.3