year2015/
day14.rs

1use utils::prelude::*;
2
3/// Reindeer speeds.
4#[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]);