use std::fmt::Display; pub fn process_part1(input: &str, time: u32) -> u32 { let mut reindeer_stats = vec![]; input.lines().for_each(|line| { let words = line.split_whitespace().collect::>(); let name = words[0].to_string(); let speed = words[3].parse::().unwrap(); let travel_time = words[6].parse::().unwrap(); let rest_time = words[13].parse::().unwrap(); let reindeer = Reindeer { name, speed, travel_time, rest_time, score: 0, distance: 0, }; reindeer_stats.push(reindeer.distance_traveled(time)); }); *reindeer_stats.iter().max().unwrap() } #[derive(Debug, Clone)] struct Reindeer { name: String, speed: u32, travel_time: u32, rest_time: u32, score: u32, distance: u32, } impl Display for Reindeer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let string = format!( "{}: Speed {} for {}, rest {}", self.name, self.speed, self.travel_time, self.rest_time ); writeln!(f, "{string}") } } impl Reindeer { fn distance_traveled(&self, seconds: u32) -> u32 { let timeframe = self.travel_time + self.rest_time; let mut traveled = (seconds / timeframe) * self.speed * self.travel_time; let last_timeframe = seconds % timeframe; if last_timeframe >= self.travel_time { traveled += self.speed * self.travel_time; } else { traveled += self.speed * last_timeframe; } traveled } } pub fn process_part2(input: &str, time: u32) -> u32 { let mut reindeer_stats = vec![]; input.lines().for_each(|line| { let words = line.split_whitespace().collect::>(); let name = words[0].to_string(); let speed = words[3].parse::().unwrap(); let travel_time = words[6].parse::().unwrap(); let rest_time = words[13].parse::().unwrap(); let reindeer = Reindeer { name, speed, travel_time, rest_time, score: 0, distance: 0, }; reindeer_stats.push(reindeer); }); for second in 1..=time { let mut furthest = (String::new(), 0); let mut reindeers = reindeer_stats .iter() .map(|reindeer| { let reindeer = reindeer.clone(); Reindeer { distance: reindeer.distance_traveled(second), ..reindeer } }) .collect::>(); reindeers.iter().for_each(|reindeer| { if reindeer.distance >= furthest.1 { furthest = (reindeer.name.clone(), reindeer.distance); } }); reindeers.iter_mut().for_each(|reindeer| { if reindeer.name == furthest.0 { reindeer.score += 1; } }); reindeer_stats = reindeers; } reindeer_stats .iter() .map(|reindeer| reindeer.score) .max() .unwrap() } #[cfg(test)] mod tests { use super::*; const INPUT: &str = "Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds. Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds."; #[test] fn part1() { let result = process_part1(INPUT, 1000); assert_eq!(result, 1120); } #[test] fn part2() { let result = process_part2(INPUT, 1000); assert_eq!(result, 689); } }