1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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);
}
}
|