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
use crate::input::Input;
pub fn solve(input: &mut Input) -> Result<u32, String> {
let mut intervals = Vec::new();
for line in input.text.lines() {
let (from, to) = line
.split_once('-')
.and_then(|(from, to)| Some((from.parse::<u32>().ok()?, to.parse::<u32>().ok()?)))
.ok_or("Invalid input")?;
if from > to {
return Err("Invalid interval with from > to".into());
}
intervals.push((from, to));
}
intervals.sort_unstable();
if input.is_part_one() {
Ok(intervals.iter().fold(0, |lowest_allowed, &(from, to)| {
if from > lowest_allowed {
lowest_allowed
} else {
std::cmp::max(lowest_allowed, to + 1)
}
}))
} else {
let mut in_gaps = intervals[0].0;
let mut highest_blocked = intervals[0].1;
for &(from, to) in intervals.iter() {
if highest_blocked != u32::MAX && from > highest_blocked + 1 {
in_gaps += from - highest_blocked - 1;
}
highest_blocked = std::cmp::max(highest_blocked, to);
}
Ok(u32::MAX - highest_blocked + in_gaps)
}
}
#[test]
pub fn tests() {
use crate::input::{test_part_one, test_part_two};
let real_input = include_str!("day20_input.txt");
test_part_one!(real_input => 17_348_574);
test_part_two!(real_input => 104);
}