diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/day14.rs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/bin/day14.rs b/src/bin/day14.rs new file mode 100644 index 0000000..8df62e4 --- /dev/null +++ b/src/bin/day14.rs @@ -0,0 +1,79 @@ +use std::collections::HashMap; +use regex::Regex; + +fn main() { + let input = advent::read_lines(14); + println!("14a: {}", winning_distance(&input, 2503)); + println!("14b: {}", winning_points(&input, 2503)); +} + +struct Reindeer { + name: String, + speed: u32, + duration: u32, + rest: u32, +} + +impl Reindeer { + fn new(input: &str) -> Reindeer { + let re = Regex::new(r"^([A-Za-z]+) can fly ([0-9]+) km/s for ([0-9]+) seconds, but then must rest for ([0-9]+) seconds.$").unwrap(); + let cap = re.captures(input).unwrap(); + let name = cap[1].to_string(); + let speed = cap[2].parse::<u32>().unwrap(); + let duration = cap[3].parse::<u32>().unwrap(); + let rest = cap[4].parse::<u32>().unwrap(); + + Reindeer { name, speed, duration, rest } + } + + fn distance(&self, time: u32) -> u32 { + let cycle_time = self.duration + self.rest; + + let time_flown = (time / cycle_time) * self.duration + + std::cmp::min(self.duration, time % cycle_time); + + time_flown * self.speed + } +} + +fn winning_distance(input: &[String], time: u32) -> u32 { + input.iter() + .map(|line| Reindeer::new(line)) + .map(|reindeer| reindeer.distance(time)) + .max() + .unwrap() +} + +fn winning_points(input: &[String], time: u32) -> u32 { + let reindeers = input.iter() + .map(|line| Reindeer::new(line)) + .collect::<Vec<Reindeer>>(); + let mut scores = HashMap::new(); + + for t in 1..=time { + let mut winner = ("", 0); + for reindeer in &reindeers { + let distance = reindeer.distance(t); + if distance >= winner.1 { + winner = (&reindeer.name, distance); + } + } + *scores.entry(winner.0).or_insert(0) += 1; + } + *scores.values().max().unwrap() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = [ + "Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds.".to_string(), + "Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds.".to_string(), + ]; + assert_eq!(winning_distance(&input, 1000), 1120); + assert_eq!(winning_points(&input, 1000), 689); + } +} |
