-
Notifications
You must be signed in to change notification settings - Fork 0
/
15.rs
88 lines (76 loc) · 2.15 KB
/
15.rs
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
use std::collections::VecDeque;
static INPUT_TXT: &str = include_str!("../../input/15.txt");
fn main() {
println!("Part 1: {}", part_1(INPUT_TXT));
println!("Part 2: {}", part_2(INPUT_TXT));
}
fn hash(s: &str) -> u32 {
s.chars().fold(0, |acc, c| {
((acc + u32::try_from(c).expect("failed to get ascii value")) * 17) % 256
})
}
fn part_1(input: &str) -> u32 {
input.trim().split(',').map(hash).sum()
}
enum Op {
Minus,
Equals(usize),
}
fn hashmap<'a>(
mut boxes: Vec<VecDeque<(&'a str, usize)>>,
lens: &'a str,
) -> Vec<VecDeque<(&'a str, usize)>> {
let (label, focal_length) = if lens.contains('=') {
let (a, b) = lens.split_once('=').unwrap();
(a, Op::Equals(b.parse::<usize>().unwrap()))
} else {
(lens.trim_end_matches('-'), Op::Minus)
};
let box_index = usize::try_from(hash(label)).expect("failed to get box index");
if let Some(pos) = boxes[box_index].iter().position(|&(l, _)| l == label) {
match focal_length {
Op::Equals(f) => {
boxes[box_index][pos] = (label, f);
}
Op::Minus => {
boxes[box_index].remove(pos);
}
}
} else if let Op::Equals(f) = focal_length {
boxes[box_index].push_back((label, f));
}
boxes
}
fn focusing_power(boxes: &VecDeque<(&str, usize)>) -> usize {
boxes
.iter()
.enumerate()
.map(|(index, &(_, focus_length))| (index + 1) * focus_length)
.sum()
}
fn part_2(input: &str) -> usize {
input
.trim()
.split(',')
.fold(vec![VecDeque::default(); 256], hashmap)
.iter()
.enumerate()
.filter(|(_, b)| !b.is_empty())
.map(|(index, b)| (index + 1) * focusing_power(b))
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
static INPUT: &str = "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7";
#[test]
fn test_part_1() {
assert_eq!(part_1(INPUT), 1320);
assert_eq!(part_1(INPUT_TXT), 511_498);
}
#[test]
fn test_part_2() {
assert_eq!(part_2(INPUT), 145);
assert_eq!(part_2(INPUT_TXT), 284_674);
}
}