diff --git a/src/lib.rs b/src/lib.rs index 40c078fe..4a336acc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1327,6 +1327,7 @@ pub mod problem_1771_maximize_palindrome_length_from_subsequences; pub mod problem_1773_count_items_matching_a_rule; pub mod problem_1774_closest_dessert_cost; pub mod problem_1775_equal_sum_arrays_with_minimum_number_of_operations; +pub mod problem_1776_car_fleet_ii; pub mod problem_1779_find_nearest_point_that_has_the_same_x_or_y_coordinate; pub mod problem_1780_check_if_number_is_a_sum_of_powers_of_three; pub mod problem_1781_sum_of_beauty_of_all_substrings; diff --git a/src/problem_1776_car_fleet_ii/mod.rs b/src/problem_1776_car_fleet_ii/mod.rs new file mode 100644 index 00000000..3fa5afe9 --- /dev/null +++ b/src/problem_1776_car_fleet_ii/mod.rs @@ -0,0 +1,24 @@ +pub mod monotonic_stack; + +pub trait Solution { + fn get_collision_times(cars: Vec>) -> Vec; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + ( + &[[1, 2], [2, 1], [4, 3], [7, 2]] as &[_], + &[1.0, -1.0, 3.0, -1.0] as &[_], + ), + (&[[3, 4], [5, 4], [6, 3], [9, 1]], &[2.0, 1.0, 1.5, -1.0]), + ]; + + for (cars, expected) in test_cases { + assert_eq!(S::get_collision_times(cars.iter().map(Vec::from).collect()), expected); + } + } +} diff --git a/src/problem_1776_car_fleet_ii/monotonic_stack.rs b/src/problem_1776_car_fleet_ii/monotonic_stack.rs new file mode 100644 index 00000000..7a4bef33 --- /dev/null +++ b/src/problem_1776_car_fleet_ii/monotonic_stack.rs @@ -0,0 +1,58 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +// See . + +use std::convert::TryInto; + +impl Solution { + pub fn get_collision_times(cars: Vec>) -> Vec { + let mut result = vec![-1.0; cars.len()]; + let mut stack = Vec::<(u32, u32, u32, u32)>::new(); + + for (target, car) in result.iter_mut().zip(cars).rev() { + let [position, speed]: [_; 2] = car.try_into().ok().unwrap(); + let (position, speed) = (position as u32, speed as u32); + + let (distance, speed_diff) = loop { + if let Some(&(right_position, right_speed, numerator, denominator)) = stack.last() { + if speed > right_speed { + let distance = right_position - position; + let speed_diff = speed - right_speed; + + if u64::from(distance) * u64::from(denominator) < u64::from(numerator) * u64::from(speed_diff) { + *target = f64::from(distance) / f64::from(speed_diff); + + break (distance, speed_diff); + } + } + + stack.pop(); + } else { + break (u32::MAX, 0); + } + }; + + stack.push((position, speed, distance, speed_diff)); + } + + result + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn get_collision_times(cars: Vec>) -> Vec { + Self::get_collision_times(cars) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +}