-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday15.rs
71 lines (64 loc) · 1.87 KB
/
day15.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
use std::collections::HashMap;
fn hash(data: &str) -> u8 {
data.bytes()
.fold(0, |acc, b| 17u8.wrapping_mul(acc.wrapping_add(b)))
}
pub fn part1(data: &str) -> u32 {
data.lines()
.flat_map(|line| line.split(','))
.map(|step| u32::from(hash(step)))
.sum()
}
pub fn part2(data: &str) -> Option<usize> {
let mut lenses = HashMap::<&str, (usize, usize)>::new();
for (i, step) in data.lines().flat_map(|line| line.split(',')).enumerate() {
if let Some(key) = step.strip_suffix('-') {
lenses.remove(key);
} else {
let (key, value) = step.split_once('=')?;
let value = value.parse::<usize>().ok()?;
lenses
.entry(key)
.and_modify(|(entry, _)| {
*entry = value;
})
.or_insert((value, i));
}
}
let mut boxes: [Vec<(usize, usize)>; 256] = std::array::from_fn(|_| vec![]);
for (key, value) in lenses.into_iter() {
boxes[usize::from(hash(key))].push(value);
}
Some(
boxes
.into_iter()
.enumerate()
.map(|(i, mut boxes)| {
boxes.sort_by_key(|(_, c)| *c);
(i + 1)
* boxes
.into_iter()
.enumerate()
.map(|(j, (value, _))| (j + 1) * value)
.sum::<usize>()
})
.sum::<usize>(),
)
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
use pretty_assertions::assert_eq;
static EXAMPLE: &str = indoc! {"
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
"};
#[test]
fn part1_examples() {
assert_eq!(1320, part1(EXAMPLE));
}
#[test]
fn part2_examples() {
assert_eq!(Some(145), part2(EXAMPLE));
}
}