solution: day14
This commit is contained in:
parent
0000025076
commit
00000260bf
|
@ -0,0 +1,118 @@
|
|||
use itertools::Itertools;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(
|
||||
r#"(?P<speed>\d+) km/s for (?P<duration>\d+) seconds, but then must rest for (?P<rest>\d+)"#
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
const DISTANCE: u32 = 2503;
|
||||
|
||||
struct Reindeer {
|
||||
speed: u32,
|
||||
duration: u32,
|
||||
rest: u32,
|
||||
}
|
||||
|
||||
impl Reindeer {
|
||||
fn cycle(&self) -> u32 {
|
||||
self.duration + self.rest
|
||||
}
|
||||
|
||||
fn running(&self, traveled: u32) -> bool {
|
||||
traveled % self.cycle() < self.duration
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Reindeer {
|
||||
fn from(value: &str) -> Self {
|
||||
let cap = RE.captures(value).unwrap();
|
||||
|
||||
let speed = cap["speed"].parse().unwrap();
|
||||
let duration = cap["duration"].parse().unwrap();
|
||||
let rest = cap["rest"].parse().unwrap();
|
||||
|
||||
Self {
|
||||
speed,
|
||||
duration,
|
||||
rest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part_one(input: &str) -> Option<u32> {
|
||||
input
|
||||
.split('\n')
|
||||
.map(|x| Reindeer::from(x))
|
||||
.map(|y| {
|
||||
((DISTANCE / y.cycle()) * y.duration
|
||||
+ vec![DISTANCE % y.cycle(), y.duration].iter().min().unwrap())
|
||||
* y.speed
|
||||
})
|
||||
.max()
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Scoreboard {
|
||||
current_distance: u32,
|
||||
score: u32,
|
||||
}
|
||||
|
||||
impl Scoreboard {
|
||||
fn empty() -> Self {
|
||||
Self {
|
||||
current_distance: 0,
|
||||
score: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn part_two(input: &str) -> Option<u32> {
|
||||
let reindeers = input.split('\n').map(|x| Reindeer::from(x)).collect_vec();
|
||||
let mut scoreboards = vec![Scoreboard::empty(); reindeers.len()];
|
||||
|
||||
for traveled in 0..DISTANCE {
|
||||
for (idx, r) in reindeers
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, x)| x.running(traveled))
|
||||
{
|
||||
scoreboards[idx].current_distance += r.speed;
|
||||
}
|
||||
|
||||
let win = scoreboards
|
||||
.iter()
|
||||
.map(|x| x.current_distance)
|
||||
.max()
|
||||
.unwrap();
|
||||
|
||||
for r in scoreboards.iter_mut().filter(|x| x.current_distance == win) {
|
||||
r.score += 1;
|
||||
}
|
||||
}
|
||||
scoreboards.iter().map(|x| x.score).max()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = &aoc::read_file("inputs", 14);
|
||||
RE.captures(input);
|
||||
aoc::solve!(1, part_one, input);
|
||||
aoc::solve!(2, part_two, input);
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_part_one() {
|
||||
let input = aoc::read_file("test_inputs", 14);
|
||||
assert_eq!(part_one(&input.trim()), Some(1120));
|
||||
}
|
||||
#[test]
|
||||
fn test_part_two() {
|
||||
let input = aoc::read_file("test_inputs", 14);
|
||||
assert_eq!(part_two(&input.trim()), None);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
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.
|
Loading…
Reference in New Issue