~ttt/aoc2015

b14fa93618712acff4cd483b59c4f694783827c0 — Tomasz Kłak 4 years ago 70f8b3b
Day 14
3 files changed, 106 insertions(+), 0 deletions(-)

A day14/Cargo.toml
A day14/input
A day14/src/main.rs
A day14/Cargo.toml => day14/Cargo.toml +11 -0
@@ 0,0 1,11 @@
[package]
name = "day14"
version = "0.1.0"
authors = ["Tomasz Kłak <tomasz@tomaszklak.pl>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
regex = "1"
lazy_static = "1.4"

A day14/input => day14/input +9 -0
@@ 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.

A day14/src/main.rs => day14/src/main.rs +86 -0
@@ 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));
}