92 lines
2 KiB
Rust
92 lines
2 KiB
Rust
//! Day 6: Wait For It
|
|
|
|
use std::ops::RangeInclusive;
|
|
|
|
use itertools::Itertools;
|
|
|
|
pub const DAY: u8 = 6;
|
|
pub const TITLE: &str = "Wait For It";
|
|
|
|
#[derive(Debug)]
|
|
struct Race {
|
|
t: u64,
|
|
d: u64,
|
|
}
|
|
|
|
impl Race {
|
|
fn win_range(&self) -> RangeInclusive<u64> {
|
|
let t_r = self.t as f64;
|
|
let d = self.d as f64;
|
|
|
|
let discriminant = (t_r.powi(2) - (4.0 * d)).sqrt();
|
|
let a = (-t_r + discriminant) / -2.0;
|
|
let b = (-t_r - discriminant) / -2.0;
|
|
|
|
let min = a.min(b);
|
|
let max = a.max(b);
|
|
|
|
let mut l = min.ceil();
|
|
if l == min {
|
|
l += 1.0;
|
|
}
|
|
let mut h = max.floor();
|
|
if h == max {
|
|
h -= 1.0
|
|
}
|
|
|
|
l as u64..=h as u64
|
|
}
|
|
}
|
|
|
|
pub fn part1(input: Vec<String>) -> String {
|
|
let races = input[0]
|
|
.split_ascii_whitespace()
|
|
.skip(1)
|
|
.zip(input[1].split_ascii_whitespace().skip(1))
|
|
.map(|(a, b)| Race {
|
|
t: a.parse().unwrap(),
|
|
d: b.parse().unwrap(),
|
|
})
|
|
.collect_vec();
|
|
|
|
races
|
|
.iter()
|
|
.map(|r| r.win_range().try_len().unwrap())
|
|
.product::<usize>()
|
|
.to_string()
|
|
}
|
|
|
|
pub fn part2(input: Vec<String>) -> String {
|
|
let (_, l1) = input[0].split_once(' ').unwrap();
|
|
let (_, l2) = input[1].split_once(' ').unwrap();
|
|
let t = l1.replace(' ', "").parse::<u64>().unwrap();
|
|
let d = l2.replace(' ', "").parse::<u64>().unwrap();
|
|
let race = Race { t, d };
|
|
|
|
race.win_range().try_len().unwrap().to_string()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn t_example1() {
|
|
assert_eq!(part1(crate::read_example(DAY, 1)), "288");
|
|
}
|
|
|
|
#[test]
|
|
fn t_part1() {
|
|
assert_eq!(part1(crate::read_input(DAY)), "505494");
|
|
}
|
|
|
|
#[test]
|
|
fn t_example2() {
|
|
assert_eq!(part2(crate::read_example(DAY, 2)), "71503");
|
|
}
|
|
|
|
#[test]
|
|
fn t_part2() {
|
|
assert_eq!(part2(crate::read_input(DAY)), "23632299");
|
|
}
|
|
}
|