1use utils::prelude::*;
2
3#[derive(Clone, Debug)]
5pub struct Day14 {
6 reindeer: Vec<(u32, u32, u32)>,
7 duration: u32,
8}
9
10impl Day14 {
11 pub fn new(input: &str, input_type: InputType) -> Result<Self, InputError> {
12 Ok(Self {
13 reindeer: parser::u32()
14 .with_prefix(" can fly ")
15 .with_prefix(parser::take_while(u8::is_ascii_alphabetic))
16 .then(parser::u32().with_prefix(" km/s for "))
17 .then(parser::u32().with_prefix(" seconds, but then must rest for "))
18 .with_suffix(" seconds.")
19 .parse_lines(input)?,
20 duration: match input_type {
21 InputType::Example => 1000,
22 InputType::Real => 2503,
23 },
24 })
25 }
26
27 #[must_use]
28 pub fn part1(&self) -> u32 {
29 self.reindeer
30 .iter()
31 .map(|&r| Self::distance(self.duration, r))
32 .max()
33 .unwrap()
34 }
35
36 #[must_use]
37 pub fn part2(&self) -> u32 {
38 let mut scores = vec![0; self.reindeer.len()];
39 let mut distances = vec![0; self.reindeer.len()];
40 for t in 1..=self.duration {
41 let mut max_dist = 0;
42 for (&r, dist) in self.reindeer.iter().zip(distances.iter_mut()) {
43 *dist = Self::distance(t, r);
44 max_dist = max_dist.max(*dist);
45 }
46
47 for (score, dist) in scores.iter_mut().zip(distances.iter_mut()) {
48 if *dist == max_dist {
49 *score += 1;
50 }
51 }
52 }
53 scores.into_iter().max().unwrap()
54 }
55
56 fn distance(duration: u32, (speed, fly_time, rest_time): (u32, u32, u32)) -> u32 {
57 let cycle_time = fly_time + rest_time;
58 let cycles = duration / cycle_time;
59 speed * (cycles * fly_time + (duration - (cycles * cycle_time)).min(fly_time))
60 }
61}
62
63examples!(Day14 -> (u32, u32) [
64 {
65 input: "Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds.\n\
66 Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds.",
67 part1: 1120,
68 part2: 689,
69 },
70]);