diff --git a/src/lib.rs b/src/lib.rs index 538c8dcc..311a4d19 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1534,6 +1534,7 @@ pub mod problem_2110_number_of_smooth_descent_periods_of_a_stock; pub mod problem_2114_maximum_number_of_words_found_in_sentences; pub mod problem_2116_check_if_a_parentheses_string_can_be_valid; pub mod problem_2119_a_number_after_a_double_reversal; +pub mod problem_2121_intervals_between_identical_elements; pub mod problem_2124_check_if_all_as_appears_before_all_bs; pub mod problem_2125_number_of_laser_beams_in_a_bank; pub mod problem_2126_destroying_asteroids; diff --git a/src/problem_2121_intervals_between_identical_elements/iterative.rs b/src/problem_2121_intervals_between_identical_elements/iterative.rs new file mode 100644 index 00000000..ae2ff071 --- /dev/null +++ b/src/problem_2121_intervals_between_identical_elements/iterative.rs @@ -0,0 +1,64 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use std::ptr; + +impl Solution { + fn address(value: &i64) -> usize { + ptr::from_ref(value) as _ + } + + pub fn get_distances(arr: Vec) -> Vec { + let mut result = vec![0; arr.len()]; + let mut indices = HashMap::<_, Vec<_>>::new(); + + for (num, target) in arr.into_iter().zip(&mut result) { + match indices.entry(num) { + Entry::Occupied(entry) => entry.into_mut().push(target), + Entry::Vacant(entry) => { + entry.insert(vec![target]); + } + } + } + + for targets in indices.values_mut() { + let mut sum = targets + .iter() + .fold(0_u64, |sum, index| sum + Self::address(index) as u64); + + let mut count_diff = (targets.len() as u64).wrapping_neg(); + let mut prev = 0; + + for target in targets { + let address = Self::address(target) as u64; + + sum = sum.wrapping_add((address - prev).wrapping_mul(count_diff)); + count_diff = count_diff.wrapping_add(2); + prev = address; + + **target = (sum / (u64::from(usize::BITS) / 8)) as _; + } + } + + result + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn get_distances(arr: Vec) -> Vec { + Self::get_distances(arr) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2121_intervals_between_identical_elements/mod.rs b/src/problem_2121_intervals_between_identical_elements/mod.rs new file mode 100644 index 00000000..76567024 --- /dev/null +++ b/src/problem_2121_intervals_between_identical_elements/mod.rs @@ -0,0 +1,21 @@ +pub mod iterative; + +pub trait Solution { + fn get_distances(arr: Vec) -> Vec; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + (&[2, 1, 3, 1, 2, 3, 3] as &[_], &[4_i64, 2, 7, 2, 4, 4, 5] as &[_]), + (&[10, 5, 10, 10], &[5, 0, 3, 4]), + ]; + + for (arr, expected) in test_cases { + assert_eq!(S::get_distances(arr.to_vec()), expected); + } + } +}