-
Notifications
You must be signed in to change notification settings - Fork 0
/
day10.rs
93 lines (75 loc) · 2.38 KB
/
day10.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
92
93
use std::collections::HashMap;
use crate::Day;
pub struct Day10(Vec<usize>);
impl Day for Day10 {
fn parse(text: &str) -> Box<Self>
where
Self: Sized,
{
let mut numbers: Vec<usize> = text.lines().flat_map(|line| line.parse()).collect();
numbers.sort();
Box::new(Day10(numbers))
}
fn solve1(&self) -> usize {
let (ones, threes) = outlets_with_jolt_ones_threes(&self.0);
ones * threes
}
fn solve2(&self) -> usize {
num_arrangements(&self.0)
}
}
/// A 'jolt' is the difference between two outlets,
/// 0->1 and 10->11 have a jolt of 1, 1->4 has a 'jolt' of 3
fn outlets_with_jolt_ones_threes(adapters: &[usize]) -> (usize, usize) {
let (ones, threes) = adapters
.iter()
.fold((0, (0, 0)), |(num, mut acc), next| {
if next - num == 1 {
acc.0 += 1;
} else if next - num == 3 {
acc.1 += 1;
} else {
unreachable!("There are no 1-jolt or 3-jolt!?");
}
(*next, acc)
})
.1;
(ones, threes + 1)
}
fn num_arrangements(adapters: &[usize]) -> usize {
let last = adapters.last().unwrap() + 3;
let get_route = |routes: &HashMap<_, _>, i: &usize, offset: usize| -> usize {
*i.checked_sub(offset)
.map(|n| routes.get(&n).unwrap_or(&0))
.unwrap_or(&0)
};
let mut combis = HashMap::new();
combis.insert(0, 1); // At start (always 0) theres only 1 possible combination
adapters.iter().chain(&[last]).for_each(|i| {
let r1 = get_route(&combis, i, 1);
let r2 = get_route(&combis, i, 2);
let r3 = get_route(&combis, i, 3);
combis.insert(*i, r1 + r2 + r3);
});
*combis.get(&last).unwrap()
}
#[cfg(test)]
mod tests {
use crate::{day10::Day10, Day};
const EXAMPLE_1: &str = include_str!("../../data/10_example1.in");
const EXAMPLE_2: &str = include_str!("../../data/10_example2.in");
#[test]
fn test_part1() {
let day1 = Day10::parse(EXAMPLE_1);
assert_eq!(7 * 5, day1.solve1());
let day2 = Day10::parse(EXAMPLE_2);
assert_eq!(22 * 10, day2.solve1());
}
#[test]
fn test_part2() {
let day1 = Day10::parse(EXAMPLE_1);
assert_eq!(8, day1.solve2());
let day2 = Day10::parse(EXAMPLE_2);
assert_eq!(19208, day2.solve2());
}
}