-
Notifications
You must be signed in to change notification settings - Fork 3
/
day_06.rs
132 lines (113 loc) · 3.13 KB
/
day_06.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Day 6: Wait For It
//
// Today was simple, a nice break from yesterday. I can see multiple ways of improving
// the solution, but I'm happy with it for now.
#[derive(Debug)]
pub struct Input {
races: Vec<(u64, u64)>,
}
fn parse_numbers(s: &str) -> Vec<u64> {
s.split(':')
.nth(1)
.unwrap()
.split_whitespace()
.map(|s| s.trim().parse::<u64>().unwrap())
.collect::<Vec<_>>()
}
fn parse_merged_numbers(s: &str) -> u64 {
s.chars()
.filter(char::is_ascii_digit)
.collect::<String>()
.parse::<u64>()
.unwrap()
}
#[aoc_generator(day6, part1)]
pub fn input_generator(input: &str) -> Input {
let (times, distances) = input.split_once('\n').unwrap();
let times = parse_numbers(times);
let distances = parse_numbers(distances);
let races = times
.iter()
.zip(distances.iter())
.map(|(t, d)| (*t, *d))
.collect::<Vec<_>>();
Input { races }
}
#[aoc_generator(day6, part2)]
pub fn input_generator_part2(input: &str) -> Input {
let lines = input.lines().collect::<Vec<_>>();
let time = parse_merged_numbers(lines[0]);
let distance = parse_merged_numbers(lines[1]);
let races = vec![(time, distance)];
Input { races }
}
fn race(races: &[(u64, u64)]) -> u64 {
races
.iter()
.map(|(time, record)| {
(1..*time).fold(0, |acc, t| {
let speed = time - t;
let remaining_time = time - speed;
let distance_covered = speed * remaining_time;
if distance_covered > *record {
acc + 1
} else {
acc
}
})
})
.product::<u64>()
}
/* Part One
*
* We get a table of race times and the record distance. We need to find how many
* ways there are to beat the record. The race starts by holding a button to build
* up speed for a certain amount of time, and then releasing it. The distance
* covered is the speed times the remaining time.
*
*/
// Your puzzle answer was
/*
/// ```
/// use advent_of_code_2023::day_06::*;
/// let data = include_str!("../input/2023/day6.txt");
/// assert_eq!(solve_part_01(&input_generator(data)), 861300);
/// ```
*/
#[aoc(day6, part1)]
pub fn solve_part_01(input: &Input) -> u64 {
race(&input.races)
}
/* Part Two
*
* Here we combine all the race times and distance from the previous data into
* two large numbers. This means we only have one race, but since the time
* is longer, we have a lot more ways to beat the record.
*
*/
/*
/// ```
/// use advent_of_code_2023::day_06::*;
/// let data = include_str!("../input/2023/day6.txt");
/// assert_eq!(solve_part_02(&input_generator(data)), 28101347);
/// ```
*/
#[aoc(day6, part2)]
pub fn solve_part_02(input: &Input) -> u64 {
race(&input.races)
}
#[cfg(test)]
mod tests {
use super::*;
const DATA: &str = "Time: 7 15 30
Distance: 9 40 200
";
#[test]
fn sample_01() {
assert_eq!(solve_part_01(&input_generator(DATA)), 288)
}
#[test]
fn sample_02() {
assert_eq!(solve_part_02(&input_generator_part2(DATA)), 71503)
}
}