1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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
}
}
}
|