@@ 0,0 1,9 @@
+Vixen can fly 8 km/s for 8 seconds, but then must rest for 53 seconds.
+Blitzen can fly 13 km/s for 4 seconds, but then must rest for 49 seconds.
+Rudolph can fly 20 km/s for 7 seconds, but then must rest for 132 seconds.
+Cupid can fly 12 km/s for 4 seconds, but then must rest for 43 seconds.
+Donner can fly 9 km/s for 5 seconds, but then must rest for 38 seconds.
+Dasher can fly 10 km/s for 4 seconds, but then must rest for 37 seconds.
+Comet can fly 3 km/s for 37 seconds, but then must rest for 76 seconds.
+Prancer can fly 9 km/s for 12 seconds, but then must rest for 97 seconds.
+Dancer can fly 37 km/s for 1 seconds, but then must rest for 36 seconds.
@@ 0,0 1,86 @@
+#[macro_use]
+extern crate lazy_static;
+
+use regex::Regex;
+use std::io::{BufReader, BufRead};
+use std::collections::{HashMap, HashSet};
+
+lazy_static! {
+ static ref RE : Regex =
+ Regex::new(r"(.+) can fly (\d+) km/s for (\d+) seconds, but then must rest for (\d+) seconds.").unwrap();
+}
+
+#[derive(Debug)]
+struct Reindeer {
+ speed: i64,
+ move_time: i64,
+ rest_time: i64,
+}
+
+fn parse(s: &str) -> (String, Reindeer) {
+ let c = RE.captures(s).unwrap();
+ (c[1].to_owned(), Reindeer{
+ speed: c[2].parse().unwrap(),
+ move_time: c[3].parse().unwrap(),
+ rest_time: c[4].parse().unwrap(),
+ })
+}
+
+#[derive(Debug)]
+enum State {
+ Moving(i64),
+ Resting(i64),
+}
+
+fn best_names(pos: &HashMap<String, i64>) -> HashSet<String> {
+ let best = pos.values().max().unwrap();
+ pos.iter().filter(|(n,v)| *v == best).map(|(n,_)| n).cloned().collect()
+}
+
+fn run(deers: &HashMap<String, Reindeer>, time: usize) -> (i64,usize) {
+ let mut pos : HashMap<String, i64> = deers
+ .keys().map(|name| (name.clone(), 0)).collect();
+ let mut global_state : HashMap<String, State> =
+ deers.iter().map(|(name, state)| (name.clone(), State::Moving(state.move_time))).collect();
+ let mut points : HashMap<String, usize> = deers
+ .keys().map(|name| (name.clone(), 0)).collect();
+ for i in 0..time {
+ let mut new_state : HashMap<String, State> = HashMap::new();
+ for (name, state) in global_state.iter() {
+ match state {
+ State::Moving(n) => {
+ /*
+ println!("{:3}/{} Moving {} by {} from {} to {}",
+ i, time, name, deers[name].speed, pos[name], pos[name] + deers[name].speed);
+ */
+ pos.insert(name.clone(), pos[name] + deers[name].speed);
+ if *n > 1 {
+ new_state.insert(name.clone(), State::Moving(n-1));
+ } else {
+ new_state.insert(name.clone(), State::Resting(deers[name].rest_time));
+ }
+ },
+ State::Resting(n) => {
+ if *n == 1 {
+ new_state.insert(name.clone(), State::Moving(deers[name].move_time));
+ } else {
+ new_state.insert(name.clone(), State::Resting(n-1));
+ }
+ },
+ }
+ }
+ println!("{:3}/{} {:?} {:?}", i, time, pos, global_state);
+ global_state = new_state;
+ for name in best_names(&pos) {
+ points.insert(name.clone(), points[&name] + 1);
+ }
+ }
+ (*pos.values().max().unwrap(), *points.values().max().unwrap())
+}
+
+fn main() {
+ println!("Hello, world!");
+ let deers : HashMap<_,_> = BufReader::new(std::io::stdin())
+ .lines().map(|l| parse(&l.unwrap())).collect();
+ dbg!(run(&deers, 2503));
+}