-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday6.rs
90 lines (78 loc) · 2.41 KB
/
day6.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
use aoc_runner_derive::aoc;
fn parse(input: &str) -> smallvec::SmallVec<[utils::RaceData; 4]> {
use itertools::Itertools;
let (times, distances) = input
.lines()
.map(|line| line.split(':').last().unwrap().split_ascii_whitespace())
.collect_tuple()
.unwrap();
times
.into_iter()
.zip(distances)
.map(|(time, distance)| utils::RaceData {
time: time.to_owned(),
distance: distance.to_owned(),
})
.collect()
}
#[aoc(day6, part1)]
pub fn part1(input: &str) -> u64 {
let input = parse(input);
input.iter().map(utils::RaceData::n_record_breaks).product()
}
#[aoc(day6, part2)]
#[must_use]
pub fn part2(input: &str) -> u64 {
let input = parse(input);
utils::RaceData::merge(&input).n_record_breaks1()
}
mod utils {
pub struct RaceData {
pub time: String,
pub distance: String,
}
impl RaceData {
/// Solver using brute force (faster than the quadratic formula for small inputs).
pub fn n_record_breaks(&self) -> u64 {
let (time, distance) = (self.time.parse().unwrap(), self.distance.parse().unwrap());
match (1..time).find(|j| j * (time - j) > distance) {
Some(first_record) => 1 + time - (2 * first_record),
_ => 1,
}
}
/// Solver based on quadratic formula (much faster than brute force for large inputs).
pub fn n_record_breaks1(&self) -> u64 {
let (time, distance) = (
self.time.parse::<u64>().unwrap(),
self.distance.parse::<u64>().unwrap(),
);
2 * num_integer::sqrt(time.pow(2) / 4 - distance - 1) + (time % 2) + 1
}
pub fn merge(sequence: &[Self]) -> Self {
let (time, distance) = sequence.iter().fold(
Default::default(),
|(time, distance): (String, String), data| {
(time + &data.time, distance + &data.distance)
},
);
Self { time, distance }
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
const SAMPLE: &str = indoc! {"
Time: 7 15 30
Distance: 9 40 200
"};
#[test]
pub fn part1_example() {
assert_eq!(part1(SAMPLE), 288);
}
#[test]
pub fn part2_example() {
assert_eq!(part2(SAMPLE), 71503);
}
}