solution: day14

This commit is contained in:
Matej Janezic 2022-12-06 21:44:50 +01:00
parent 0000025076
commit 00000260bf
Signed by: janezicmatej
GPG Key ID: 4298E230ED37B2C0
2 changed files with 120 additions and 0 deletions

118
src/bin/14.rs Normal file
View File

@ -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);
}
}

2
src/test_inputs/14.txt Normal file
View File

@ -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.