summaryrefslogtreecommitdiff
path: root/2022/src/bin/day_3.rs
diff options
context:
space:
mode:
Diffstat (limited to '2022/src/bin/day_3.rs')
-rw-r--r--2022/src/bin/day_3.rs100
1 files changed, 100 insertions, 0 deletions
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<dyn std::error::Error>> {
+ 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<Rucksack>);
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+struct Rucksack {
+ front: BTreeSet<ItemType>,
+ back: BTreeSet<ItemType>,
+}
+
+#[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::<u32>()
+ })
+ .sum()
+ }
+}
+
+impl Rucksack {
+ fn parser(input: &str) -> IResult<&str, Rucksack> {
+ map(many1(ItemType::parser), Rucksack::new)(input)
+ }
+
+ fn new(contents: Vec<ItemType>) -> 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<ItemType> {
+ self.front.intersection(&self.back).cloned().collect()
+ }
+
+ fn union(&self) -> BTreeSet<ItemType> {
+ 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
+ }
+ }
+}