AdventOfCode/y2015/src/days/d14.rs
2024-10-30 13:05:13 +01:00

126 lines
3.6 KiB
Rust

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::<Vec<&str>>();
let name = words[0].to_string();
let speed = words[3].parse::<u32>().unwrap();
let travel_time = words[6].parse::<u32>().unwrap();
let rest_time = words[13].parse::<u32>().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::<Vec<&str>>();
let name = words[0].to_string();
let speed = words[3].parse::<u32>().unwrap();
let travel_time = words[6].parse::<u32>().unwrap();
let rest_time = words[13].parse::<u32>().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::<Vec<Reindeer>>();
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);
}
}