Day 6 initial solution
This commit is contained in:
parent
77a2c79f41
commit
b187600bb5
2
input/2023/day6.txt
Normal file
2
input/2023/day6.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Time: 46 68 98 66
|
||||
Distance: 358 1054 1807 1080
|
93
src/day06.rs
Normal file
93
src/day06.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use aoc_runner_derive::{aoc_generator, aoc};
|
||||
use nom::{sequence::{preceded, separated_pair, pair}, bytes::complete::tag, IResult, character::complete::{multispace0, line_ending}, multi::separated_list0};
|
||||
|
||||
|
||||
fn parse_number_list(start_tag: &str) -> impl Fn(&str) -> IResult<&str, Vec<u64>> + '_ {
|
||||
move |input| {
|
||||
preceded(pair(tag(start_tag), multispace0), separated_list0(pair(tag(" "), multispace0), nom::character::complete::u64))(input)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_input(input: &str) -> IResult<&str, (Vec<u64>, Vec<u64>)> {
|
||||
separated_pair(parse_number_list("Time:"), line_ending, parse_number_list("Distance:"))(input)
|
||||
}
|
||||
|
||||
#[aoc_generator(day6, part1)]
|
||||
fn input_generator_part1(input: &str) -> (Vec<u64>, Vec<u64>) {
|
||||
parse_input(input).unwrap().1
|
||||
}
|
||||
|
||||
#[aoc_generator(day6, part2)]
|
||||
fn input_generator_part2(input: &str) -> (u64, u64) {
|
||||
let mut lines = input.split('\n');
|
||||
let time_line = lines.next().unwrap();
|
||||
let dist_line = lines.next().unwrap();
|
||||
let time_line = time_line.replace(' ', "");
|
||||
let dist_line = dist_line.replace(' ', "");
|
||||
let time = time_line[5..].parse().unwrap();
|
||||
let dist = dist_line[9..].parse().unwrap();
|
||||
(time, dist)
|
||||
}
|
||||
|
||||
|
||||
fn race_dist(speed: u64, total_time: u64) -> u64 {
|
||||
speed*(total_time-speed)
|
||||
}
|
||||
|
||||
// let n be the number of ms you hold the button
|
||||
// let t be the race time
|
||||
// let d be the record distance
|
||||
// time units is ms unless specified, distance is mm unless specified
|
||||
// n(t-n)>d
|
||||
// nt-n^2>d
|
||||
// nt-n^2-d>0
|
||||
//
|
||||
// nt-n^2-d=0
|
||||
// -n^2+tn-d=0
|
||||
//
|
||||
// n=-t(+-)sqrt(t^2-4*1*-d)/2
|
||||
// n=-t(+-)sqrt(t^2+4d)/2
|
||||
//
|
||||
// Let the two values be n_1 and n_2
|
||||
//
|
||||
// d/dn(nt-n^2-d)=t-2n
|
||||
// d/dn(t-2n)=-2
|
||||
//
|
||||
// Function is always concave down
|
||||
// Concave down parabolas are >0 between their roots
|
||||
//
|
||||
// Range of winning times are ceil(n_1) to floor(n_2)
|
||||
// Excluding an n value if distance is = record distance
|
||||
fn ways_to_win_race(time: u64, dist: u64) -> u64 {
|
||||
let f_time = time as f64;
|
||||
let f_dist = dist as f64;
|
||||
let sqr_discr = ((f_time * f_time) - (4.0 * f_dist)).sqrt();
|
||||
let n_1 = (((-f_time) + sqr_discr)/(-2.0)).ceil() as u64;
|
||||
let n_2 = (((-f_time) - sqr_discr)/(-2.0)).floor() as u64;
|
||||
let (n_1, n_2) = if n_1 > n_2 {
|
||||
(n_2, n_1)
|
||||
} else {
|
||||
(n_1, n_2)
|
||||
};
|
||||
let excl_n1 = race_dist(n_1, time) == dist;
|
||||
let excl_n2 = race_dist(n_2, time) == dist;
|
||||
let total_offset = match (excl_n1, excl_n2) {
|
||||
(false, false) => 0,
|
||||
(false, true) => 1,
|
||||
(true, false) => 1,
|
||||
(true, true) => 2,
|
||||
};
|
||||
((n_2 - n_1) + 1) - total_offset
|
||||
}
|
||||
|
||||
#[aoc(day6, part1)]
|
||||
fn part1((times, dists): &(Vec<u64>, Vec<u64>)) -> u64 {
|
||||
times.iter().zip(dists.iter()).map(|(&time, &dist)| {
|
||||
ways_to_win_race(time, dist)
|
||||
}).product()
|
||||
}
|
||||
|
||||
#[aoc(day6, part2)]
|
||||
fn part2(&(time, dist): &(u64, u64)) -> u64 {
|
||||
ways_to_win_race(time, dist)
|
||||
}
|
@ -5,5 +5,6 @@ mod day02;
|
||||
mod day03;
|
||||
mod day04;
|
||||
mod day05;
|
||||
mod day06;
|
||||
|
||||
aoc_lib! { year = 2023 }
|
||||
|
Loading…
Reference in New Issue
Block a user