-
Notifications
You must be signed in to change notification settings - Fork 3
/
day_15.rs
91 lines (74 loc) · 2.03 KB
/
day_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
89
90
91
use common::{Answer, Solution};
use itertools::Itertools;
pub struct Day15;
impl Solution for Day15 {
fn name(&self) -> &'static str {
"Lens Library"
}
fn part_a(&self, input: &str) -> Answer {
input
.trim()
.split(',')
.map(|x| hash(x) as u32)
.sum::<u32>()
.into()
}
fn part_b(&self, input: &str) -> Answer {
let input = parse(input);
let mut boxes = vec![Vec::new(); 256];
for (label, focal_len) in input {
let key = hash(label) as usize;
if let Some(focal_len) = focal_len {
if let Some((_, e)) = boxes[key]
.iter_mut()
.find(|x: &&mut (&str, u32)| x.0 == label)
{
*e = focal_len;
} else {
boxes[key].push((label, focal_len));
}
} else {
boxes[key].retain(|x| x.0 != label);
}
}
let mut acc = 0;
for (i, e) in boxes.iter().enumerate() {
for (j, f) in e.iter().enumerate() {
acc += (i + 1) * (j + 1) * f.1 as usize;
}
}
acc.into()
}
}
fn parse(input: &str) -> Vec<(&str, Option<u32>)> {
let mut out = Vec::new();
for i in input.trim().split(',') {
let (label, focal_len) = i.split(['=', '-'].as_ref()).collect_tuple().unwrap();
out.push((label, focal_len.parse::<u32>().ok()));
}
out
}
fn hash(input: &str) -> u8 {
let mut out = 0u8;
for c in input.chars() {
out = out.wrapping_add(c as u8).wrapping_mul(17);
}
out
}
#[cfg(test)]
mod test {
use common::Solution;
use indoc::indoc;
use super::Day15;
const CASE: &str = indoc! {"
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
"};
#[test]
fn part_a() {
assert_eq!(Day15.part_a(CASE), 1320.into());
}
#[test]
fn part_b() {
assert_eq!(Day15.part_b(CASE), 145.into());
}
}