From ba7a0408099a70bb014316156239027f5b7aced0 Mon Sep 17 00:00:00 2001 From: EFanZh Date: Tue, 28 Jan 2025 11:31:18 +0800 Subject: [PATCH] [STAGING] --- src/lib.rs | 11 ++ .../bfs.rs | 64 +++++++++ .../mod.rs | 33 +++++ .../mod.rs | 24 ++++ .../trie.rs | 74 +++++++++++ src/problem_2418_sort_the_people/mod.rs | 27 ++++ .../sort_by_key.rs | 42 ++++++ .../iterative.rs | 71 ++++++++++ .../mod.rs | 64 +++++++++ .../iterative.rs | 75 +++++++++++ src/problem_2420_find_all_good_indices/mod.rs | 35 +++++ src/problem_2421_number_of_good_paths/mod.rs | 32 +++++ .../union_find.rs | 123 ++++++++++++++++++ .../iterative.rs | 45 +++++++ .../mod.rs | 18 +++ .../mathematical.rs | 36 +++++ .../mod.rs | 23 ++++ .../gcd.rs | 50 +++++++ .../mod.rs | 18 +++ .../brute_force.rs | 42 ++++++ .../mod.rs | 25 ++++ src/problem_2429_minimize_xor/greedy.rs | 61 +++++++++ src/problem_2429_minimize_xor/mod.rs | 18 +++ 23 files changed, 1011 insertions(+) create mode 100644 src/problem_2415_reverse_odd_levels_of_binary_tree/bfs.rs create mode 100644 src/problem_2415_reverse_odd_levels_of_binary_tree/mod.rs create mode 100644 src/problem_2416_sum_of_prefix_scores_of_strings/mod.rs create mode 100644 src/problem_2416_sum_of_prefix_scores_of_strings/trie.rs create mode 100644 src/problem_2418_sort_the_people/mod.rs create mode 100644 src/problem_2418_sort_the_people/sort_by_key.rs create mode 100644 src/problem_2419_longest_subarray_with_maximum_bitwise_and/iterative.rs create mode 100644 src/problem_2419_longest_subarray_with_maximum_bitwise_and/mod.rs create mode 100644 src/problem_2420_find_all_good_indices/iterative.rs create mode 100644 src/problem_2420_find_all_good_indices/mod.rs create mode 100644 src/problem_2421_number_of_good_paths/mod.rs create mode 100644 src/problem_2421_number_of_good_paths/union_find.rs create mode 100644 src/problem_2423_remove_letter_to_equalize_frequency/iterative.rs create mode 100644 src/problem_2423_remove_letter_to_equalize_frequency/mod.rs create mode 100644 src/problem_2425_bitwise_xor_of_all_pairings/mathematical.rs create mode 100644 src/problem_2425_bitwise_xor_of_all_pairings/mod.rs create mode 100644 src/problem_2427_number_of_common_factors/gcd.rs create mode 100644 src/problem_2427_number_of_common_factors/mod.rs create mode 100644 src/problem_2428_maximum_sum_of_an_hourglass/brute_force.rs create mode 100644 src/problem_2428_maximum_sum_of_an_hourglass/mod.rs create mode 100644 src/problem_2429_minimize_xor/greedy.rs create mode 100644 src/problem_2429_minimize_xor/mod.rs diff --git a/src/lib.rs b/src/lib.rs index e6cf6274..2344abf9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1799,6 +1799,17 @@ pub mod problem_2411_smallest_subarrays_with_maximum_bitwise_or; pub mod problem_2412_minimum_money_required_before_transactions; pub mod problem_2413_smallest_even_multiple; pub mod problem_2414_length_of_the_longest_alphabetical_continuous_substring; +pub mod problem_2415_reverse_odd_levels_of_binary_tree; +pub mod problem_2416_sum_of_prefix_scores_of_strings; +pub mod problem_2418_sort_the_people; +pub mod problem_2419_longest_subarray_with_maximum_bitwise_and; +pub mod problem_2420_find_all_good_indices; +pub mod problem_2421_number_of_good_paths; +pub mod problem_2423_remove_letter_to_equalize_frequency; +pub mod problem_2425_bitwise_xor_of_all_pairings; +pub mod problem_2427_number_of_common_factors; +pub mod problem_2428_maximum_sum_of_an_hourglass; +pub mod problem_2429_minimize_xor; #[cfg(test)] mod test_utilities; diff --git a/src/problem_2415_reverse_odd_levels_of_binary_tree/bfs.rs b/src/problem_2415_reverse_odd_levels_of_binary_tree/bfs.rs new file mode 100644 index 00000000..08bfa0e5 --- /dev/null +++ b/src/problem_2415_reverse_odd_levels_of_binary_tree/bfs.rs @@ -0,0 +1,64 @@ +use crate::data_structures::TreeNode; + +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +use std::cell::RefCell; +use std::collections::VecDeque; +use std::mem; +use std::rc::Rc; + +impl Solution { + pub fn reverse_odd_levels(root: Option>>) -> Option>> { + let mut queue = VecDeque::from([Rc::clone(root.as_ref().unwrap())]); + + 'outer: loop { + for _ in 0..queue.len() { + let node = queue.pop_front().unwrap(); + let node = node.borrow(); + + if let (Some(left), Some(right)) = (&node.left, &node.right) { + queue.extend([Rc::clone(left), Rc::clone(right)]); + } else { + break 'outer; + } + } + + let mut iter = queue.iter(); + + while let (Some(left), Some(right)) = (iter.next(), iter.next_back()) { + mem::swap(&mut left.borrow_mut().val, &mut right.borrow_mut().val); + } + + for _ in 0..queue.len() { + let node = queue.pop_front().unwrap(); + let node = node.borrow(); + + if let (Some(left), Some(right)) = (&node.left, &node.right) { + queue.extend([Rc::clone(left), Rc::clone(right)]); + } else { + break 'outer; + } + } + } + + root + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn reverse_odd_levels(root: Option>>) -> Option>> { + Self::reverse_odd_levels(root) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2415_reverse_odd_levels_of_binary_tree/mod.rs b/src/problem_2415_reverse_odd_levels_of_binary_tree/mod.rs new file mode 100644 index 00000000..5e271a21 --- /dev/null +++ b/src/problem_2415_reverse_odd_levels_of_binary_tree/mod.rs @@ -0,0 +1,33 @@ +use crate::data_structures::TreeNode; +use std::cell::RefCell; +use std::rc::Rc; + +pub mod bfs; + +pub trait Solution { + fn reverse_odd_levels(root: Option>>) -> Option>>; +} + +#[cfg(test)] +mod tests { + use super::Solution; + use crate::test_utilities; + + pub fn run() { + let test_cases = [ + (&[2, 3, 5, 8, 13, 21, 34] as &[_], &[2, 5, 3, 8, 13, 21, 34] as &[_]), + (&[7, 13, 11], &[7, 11, 13]), + ( + &[0, 1, 2, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], + &[0, 2, 1, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1], + ), + ]; + + for (root, expected) in test_cases { + assert_eq!( + S::reverse_odd_levels(test_utilities::make_tree(root.iter().copied().map(Some))), + test_utilities::make_tree(expected.iter().copied().map(Some)), + ); + } + } +} diff --git a/src/problem_2416_sum_of_prefix_scores_of_strings/mod.rs b/src/problem_2416_sum_of_prefix_scores_of_strings/mod.rs new file mode 100644 index 00000000..75801d5a --- /dev/null +++ b/src/problem_2416_sum_of_prefix_scores_of_strings/mod.rs @@ -0,0 +1,24 @@ +pub mod trie; + +pub trait Solution { + fn sum_prefix_scores(words: Vec) -> Vec; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + (&["abc", "ab", "bc", "b"] as &[_], &[5, 4, 3, 2] as &[_]), + (&["abcd"], &[4]), + ]; + + for (words, expected) in test_cases { + assert_eq!( + S::sum_prefix_scores(words.iter().copied().map(str::to_string).collect()), + expected, + ); + } + } +} diff --git a/src/problem_2416_sum_of_prefix_scores_of_strings/trie.rs b/src/problem_2416_sum_of_prefix_scores_of_strings/trie.rs new file mode 100644 index 00000000..12e9ece4 --- /dev/null +++ b/src/problem_2416_sum_of_prefix_scores_of_strings/trie.rs @@ -0,0 +1,74 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +struct Node { + count: u32, + children: [u32; 26], +} + +impl Solution { + pub fn sum_prefix_scores(words: Vec) -> Vec { + let mut allocator = Vec::::with_capacity(words.len() * 2); + let mut allocator_len = 0; + let mut root = [u32::MAX; 26]; + + for word in &words { + let mut node = &mut root; + + for c in word.bytes() { + let c = usize::from(c - b'a'); + let mut child_index = node[c] as usize; + + if child_index < allocator_len { + allocator[child_index].count += 1; + } else { + node[c] = allocator_len as _; + child_index = allocator_len; + + allocator.push(Node { + count: 1, + children: [u32::MAX; 26], + }); + + allocator_len += 1; + }; + + node = &mut allocator[child_index].children; + } + } + + words + .into_iter() + .map(|word| { + let mut count = 0; + let mut node = &root; + + for c in word.into_bytes() { + let child = &allocator[node[usize::from(c) - usize::from(b'a')] as usize]; + + count += child.count; + node = &child.children; + } + + count as _ + }) + .collect() + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn sum_prefix_scores(words: Vec) -> Vec { + Self::sum_prefix_scores(words) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2418_sort_the_people/mod.rs b/src/problem_2418_sort_the_people/mod.rs new file mode 100644 index 00000000..16503108 --- /dev/null +++ b/src/problem_2418_sort_the_people/mod.rs @@ -0,0 +1,27 @@ +pub mod sort_by_key; + +pub trait Solution { + fn sort_people(names: Vec, heights: Vec) -> Vec; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + ( + (&["Mary", "John", "Emma"] as &[_], &[180, 165, 170] as &[_]), + &["Mary", "Emma", "John"] as &[_], + ), + ((&["Alice", "Bob", "Bob"], &[155, 185, 150]), &["Bob", "Alice", "Bob"]), + ]; + + for ((names, heights), expected) in test_cases { + assert_eq!( + S::sort_people(names.iter().copied().map(str::to_string).collect(), heights.to_vec()), + expected, + ); + } + } +} diff --git a/src/problem_2418_sort_the_people/sort_by_key.rs b/src/problem_2418_sort_the_people/sort_by_key.rs new file mode 100644 index 00000000..a6573e28 --- /dev/null +++ b/src/problem_2418_sort_the_people/sort_by_key.rs @@ -0,0 +1,42 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +use std::cmp::Reverse; +use std::mem; + +impl Solution { + pub fn sort_people(names: Vec, heights: Vec) -> Vec { + let mut names = names; + + let mut sorting = names + .iter_mut() + .zip(heights) + .map(|(name, height)| (height, mem::take(name))) + .collect::>(); + + sorting.sort_unstable_by_key(|&(height, _)| Reverse(height as u32)); + + for (target, (_, mut name)) in names.iter_mut().zip(sorting) { + mem::swap(target, &mut name); + } + + names + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn sort_people(names: Vec, heights: Vec) -> Vec { + Self::sort_people(names, heights) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2419_longest_subarray_with_maximum_bitwise_and/iterative.rs b/src/problem_2419_longest_subarray_with_maximum_bitwise_and/iterative.rs new file mode 100644 index 00000000..72846208 --- /dev/null +++ b/src/problem_2419_longest_subarray_with_maximum_bitwise_and/iterative.rs @@ -0,0 +1,71 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +use std::cmp::Ordering; + +impl Solution { + pub fn longest_subarray(nums: Vec) -> i32 { + let mut max_value = 0; + let mut max_value_length = 0; + let mut length = 0; + let mut iter = nums.iter().map(|&x| x as u32); + + 'outer: loop { + if let Some(num) = iter.next() { + match num.cmp(&max_value) { + Ordering::Less => { + max_value_length = max_value_length.max(length); + + loop { + if let Some(num) = iter.next() { + match num.cmp(&max_value) { + Ordering::Less => continue, + Ordering::Equal => {} + Ordering::Greater => { + max_value = num; + max_value_length = 1; + } + } + + length = 1; + + break; + } + + break 'outer; + } + } + Ordering::Equal => length += 1, + Ordering::Greater => { + max_value = num; + max_value_length = 1; + length = 1; + } + } + } else { + max_value_length = max_value_length.max(length); + + break; + } + } + + max_value_length + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn longest_subarray(nums: Vec) -> i32 { + Self::longest_subarray(nums) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2419_longest_subarray_with_maximum_bitwise_and/mod.rs b/src/problem_2419_longest_subarray_with_maximum_bitwise_and/mod.rs new file mode 100644 index 00000000..be50cad4 --- /dev/null +++ b/src/problem_2419_longest_subarray_with_maximum_bitwise_and/mod.rs @@ -0,0 +1,64 @@ +pub mod iterative; + +pub trait Solution { + fn longest_subarray(nums: Vec) -> i32; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + (&[1, 2, 3, 3, 2, 2] as &[_], 2), + (&[1, 2, 3, 4], 1), + ( + &[ + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, + 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, + 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, 516_529, + 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, + 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, + 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, + 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, + 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, 55_816, + 55_816, 55_816, 55_816, 55_816, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, + 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 586_730, 232_392, 232_392, 294_503, + ], + 125, + ), + ( + &[ + 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, + 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, + 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, + 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, + 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, + 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 117_793, 109_282, 109_282, 109_282, 109_282, + 109_282, 109_282, 109_282, 109_282, 109_282, 109_282, 109_282, 109_282, 109_282, 169_349, + ], + 1, + ), + ]; + + for (nums, expected) in test_cases { + assert_eq!(S::longest_subarray(nums.to_vec()), expected); + } + } +} diff --git a/src/problem_2420_find_all_good_indices/iterative.rs b/src/problem_2420_find_all_good_indices/iterative.rs new file mode 100644 index 00000000..5a2a5ce0 --- /dev/null +++ b/src/problem_2420_find_all_good_indices/iterative.rs @@ -0,0 +1,75 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + pub fn good_indices(nums: Vec, k: i32) -> Vec { + if k == 1 { + let mut nums = nums; + let n = nums.len() as i32; + + nums.clear(); + nums.extend(k..n - k); + + return nums; + } + + let nums = nums.into_iter().map(|num| num as u32).collect::>(); + let k = k as u32 as usize; + let mut left_length = 0; + let mut left_prev = 0; + + for &num in nums[..k - 1].iter().rev() { + if num < left_prev { + break; + } + + left_prev = num; + left_length += 1; + } + + left_prev = nums.get(k.wrapping_sub(2)).copied().unwrap_or(0); + + let mut right_length = 0; + let mut right_prev = u32::MAX; + + for &num in nums[k + 1..k * 2].iter().rev() { + if right_prev < num { + break; + } + + right_prev = num; + right_length += 1; + } + + right_prev = nums[k * 2 - 1]; + + (k..) + .zip(nums[k - 1..].iter().zip(&nums[k * 2..])) + .filter_map(|(i, (&left_num, &right_num))| { + left_length = if left_prev < left_num { 1 } else { left_length + 1 }; + left_prev = left_num; + right_length = if right_num < right_prev { 1 } else { right_length + 1 }; + right_prev = right_num; + + (left_length >= k && right_length >= k).then_some(i as _) + }) + .collect() + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn good_indices(nums: Vec, k: i32) -> Vec { + Self::good_indices(nums, k) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2420_find_all_good_indices/mod.rs b/src/problem_2420_find_all_good_indices/mod.rs new file mode 100644 index 00000000..ed8d7842 --- /dev/null +++ b/src/problem_2420_find_all_good_indices/mod.rs @@ -0,0 +1,35 @@ +pub mod iterative; + +pub trait Solution { + fn good_indices(nums: Vec, k: i32) -> Vec; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + ((&[2, 1, 1, 1, 3, 4, 1] as &[_], 2), &[2, 3] as &[_]), + ((&[2, 1, 1, 2], 2), &[]), + ((&[440_043, 276_285, 336_957], 1), &[1]), + ( + (&[253_747, 459_932, 263_592, 354_832, 60_715, 408_350, 959_296], 2), + &[3], + ), + ( + ( + &[ + 388_589, 17_165, 726_687, 401_298, 600_033, 537_254, 301_052, 151_069, 399_955, + ], + 4, + ), + &[], + ), + ]; + + for ((nums, k), expected) in test_cases { + assert_eq!(S::good_indices(nums.to_vec(), k), expected); + } + } +} diff --git a/src/problem_2421_number_of_good_paths/mod.rs b/src/problem_2421_number_of_good_paths/mod.rs new file mode 100644 index 00000000..7e91059b --- /dev/null +++ b/src/problem_2421_number_of_good_paths/mod.rs @@ -0,0 +1,32 @@ +pub mod union_find; + +pub trait Solution { + fn number_of_good_paths(vals: Vec, edges: Vec>) -> i32; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + ((&[1, 3, 2, 1, 3] as &[_], &[[0, 1], [0, 2], [2, 3], [2, 4]] as &[_]), 6), + ((&[1, 1, 2, 2, 3], &[[0, 1], [1, 2], [2, 3], [2, 4]]), 7), + ((&[1], &[]), 1), + ( + ( + &[2, 4, 1, 2, 2, 5, 3, 4, 4], + &[[0, 1], [2, 1], [0, 3], [4, 1], [4, 5], [3, 6], [7, 5], [2, 8]], + ), + 11, + ), + ]; + + for ((vals, edges), expected) in test_cases { + assert_eq!( + S::number_of_good_paths(vals.to_vec(), edges.iter().map(Vec::from).collect()), + expected, + ); + } + } +} diff --git a/src/problem_2421_number_of_good_paths/union_find.rs b/src/problem_2421_number_of_good_paths/union_find.rs new file mode 100644 index 00000000..d97889e4 --- /dev/null +++ b/src/problem_2421_number_of_good_paths/union_find.rs @@ -0,0 +1,123 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +use std::cell::Cell; +use std::cmp::Ordering; +use std::{mem, ptr}; + +struct Node { + parent: Cell, + rank: Cell, + max_value: Cell, + max_value_count: Cell, +} + +impl Solution { + fn get_node(union_find: &[Node], node: &Node) -> usize { + (ptr::from_ref(node) as usize - union_find.as_ptr() as usize) / mem::size_of::() + } + + fn find_root<'a>(union_find: &'a [Node], node: &'a Node) -> &'a Node { + let parent = node.parent.get(); + + union_find.get(parent as usize).map_or(node, |parent_node| { + let root = Self::find_root(union_find, parent_node); + + node.parent.set(Self::get_node(union_find, root) as _); + + root + }) + } + + fn union(union_find: &[Node], left_node: &Node, right_node: &Node, result: &mut u32) { + let left_root = Self::find_root(union_find, left_node); + let right_root = Self::find_root(union_find, right_node); + let left_rank = left_root.rank.get(); + let right_rank = right_root.rank.get(); + + let (child, parent) = if left_rank < right_rank { + (left_root, right_root) + } else { + if left_rank == right_rank { + left_root.rank.set(left_rank + 1); + } + + (right_root, left_root) + }; + + match child.max_value.cmp(&parent.max_value) { + Ordering::Less => {} + Ordering::Equal => { + let child_max_value_count = child.max_value_count.get(); + let parent_max_value_count = parent.max_value_count.get(); + + *result += child_max_value_count * parent_max_value_count; + + parent + .max_value_count + .set(parent_max_value_count + child_max_value_count); + } + Ordering::Greater => { + parent.max_value.set(child.max_value.get()); + parent.max_value_count.set(child.max_value_count.get()); + } + } + + child.parent.set(Self::get_node(union_find, parent) as _); + } + + pub fn number_of_good_paths(vals: Vec, edges: Vec>) -> i32 { + let as_u32 = |x| x as u32; + + let mut edges = edges + .into_iter() + .map(|edge| { + let [x, y] = <[_; 2]>::map(edge.try_into().ok().unwrap(), as_u32); + + (u32::max(vals[x as usize] as _, vals[y as usize] as _), x, y) + }) + .collect::>(); + + edges.sort_unstable_by_key(|&(val, ..)| val); + + let union_find = vals + .into_iter() + .map(|val| Node { + parent: Cell::new(u32::MAX), + rank: Cell::new(0), + max_value: Cell::new(val as _), + max_value_count: Cell::new(1), + }) + .collect::>(); + + let mut result = union_find.len() as u32; + + for &(_, x, y) in &*edges { + Self::union( + &union_find, + &union_find[x as usize], + &union_find[y as usize], + &mut result, + ); + } + + result as _ + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn number_of_good_paths(vals: Vec, edges: Vec>) -> i32 { + Self::number_of_good_paths(vals, edges) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2423_remove_letter_to_equalize_frequency/iterative.rs b/src/problem_2423_remove_letter_to_equalize_frequency/iterative.rs new file mode 100644 index 00000000..0b759745 --- /dev/null +++ b/src/problem_2423_remove_letter_to_equalize_frequency/iterative.rs @@ -0,0 +1,45 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + pub fn equal_frequency(word: String) -> bool { + let mut counts = [0_u8; 26]; + + for c in word.into_bytes() { + counts[usize::from(c) - usize::from(b'a')] += 1; + } + + counts.sort_unstable(); + + let start = counts.iter().rposition(|&count| count == 0).map_or(0, |i| i + 1); + + if counts[start] == 1 + && counts.get(start + 1).map_or(true, |&first_count| { + counts[start + 2..].iter().all(|&count| count == first_count) + }) + { + return true; + } + + let target = *counts.last().unwrap() - 1; + + counts[start..25].iter().all(|&count| count == target) + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn equal_frequency(word: String) -> bool { + Self::equal_frequency(word) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2423_remove_letter_to_equalize_frequency/mod.rs b/src/problem_2423_remove_letter_to_equalize_frequency/mod.rs new file mode 100644 index 00000000..18ef2bde --- /dev/null +++ b/src/problem_2423_remove_letter_to_equalize_frequency/mod.rs @@ -0,0 +1,18 @@ +pub mod iterative; + +pub trait Solution { + fn equal_frequency(word: String) -> bool; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [("abcc", true), ("aazz", false), ("bac", true)]; + + for (word, expected) in test_cases { + assert_eq!(S::equal_frequency(word.to_string()), expected); + } + } +} diff --git a/src/problem_2425_bitwise_xor_of_all_pairings/mathematical.rs b/src/problem_2425_bitwise_xor_of_all_pairings/mathematical.rs new file mode 100644 index 00000000..b729d975 --- /dev/null +++ b/src/problem_2425_bitwise_xor_of_all_pairings/mathematical.rs @@ -0,0 +1,36 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + fn reduce_xor(init: i32, nums: &[i32]) -> i32 { + nums.iter().fold(init, |xor, value| xor ^ value) + } + + pub fn xor_all_nums(nums1: Vec, nums2: Vec) -> i32 { + let (init, nums) = match (nums1.len() % 2 == 0, nums2.len() % 2 == 0) { + (false, false) => (Self::reduce_xor(0, &nums1), &nums2), + (false, true) => (0, &nums2), + (true, false) => (0, &nums1), + (true, true) => return 0, + }; + + Self::reduce_xor(init, nums) + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn xor_all_nums(nums1: Vec, nums2: Vec) -> i32 { + Self::xor_all_nums(nums1, nums2) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2425_bitwise_xor_of_all_pairings/mod.rs b/src/problem_2425_bitwise_xor_of_all_pairings/mod.rs new file mode 100644 index 00000000..08aecb91 --- /dev/null +++ b/src/problem_2425_bitwise_xor_of_all_pairings/mod.rs @@ -0,0 +1,23 @@ +pub mod mathematical; + +pub trait Solution { + fn xor_all_nums(nums1: Vec, nums2: Vec) -> i32; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + ((&[2, 1, 3] as &[_], &[10, 2, 5, 0] as &[_]), 13), + ((&[1, 2], &[3, 4]), 0), + ((&[8, 6, 29, 2, 26, 16, 15, 29], &[24, 12, 12]), 9), + ((&[25, 29, 3, 10, 0, 15, 2], &[12]), 12), + ]; + + for ((nums1, nums2), expected) in test_cases { + assert_eq!(S::xor_all_nums(nums1.to_vec(), nums2.to_vec()), expected); + } + } +} diff --git a/src/problem_2427_number_of_common_factors/gcd.rs b/src/problem_2427_number_of_common_factors/gcd.rs new file mode 100644 index 00000000..8a1700ed --- /dev/null +++ b/src/problem_2427_number_of_common_factors/gcd.rs @@ -0,0 +1,50 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + fn gcd(mut x: u16, mut y: u16) -> u16 { + while y != 0 { + (x, y) = (y, x % y); + } + + x + } + + pub fn common_factors(a: i32, b: i32) -> i32 { + let a = a as u16; + let b = b as u16; + let gcd = Self::gcd(a, b); + let middle = f32::from(gcd).sqrt() as u16; + let mut result = 0; + + for i in 1..middle { + result += u8::from(gcd % i == 0); + } + + result = result * 2 + + if middle * middle == gcd { + 1 + } else { + u8::from(gcd % middle == 0) * 2 + }; + + i32::from(result) + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn common_factors(a: i32, b: i32) -> i32 { + Self::common_factors(a, b) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2427_number_of_common_factors/mod.rs b/src/problem_2427_number_of_common_factors/mod.rs new file mode 100644 index 00000000..db5b14b9 --- /dev/null +++ b/src/problem_2427_number_of_common_factors/mod.rs @@ -0,0 +1,18 @@ +pub mod gcd; + +pub trait Solution { + fn common_factors(a: i32, b: i32) -> i32; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [((12, 6), 4), ((25, 30), 2)]; + + for ((a, b), expected) in test_cases { + assert_eq!(S::common_factors(a, b), expected); + } + } +} diff --git a/src/problem_2428_maximum_sum_of_an_hourglass/brute_force.rs b/src/problem_2428_maximum_sum_of_an_hourglass/brute_force.rs new file mode 100644 index 00000000..acd59975 --- /dev/null +++ b/src/problem_2428_maximum_sum_of_an_hourglass/brute_force.rs @@ -0,0 +1,42 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + pub fn max_sum(grid: Vec>) -> i32 { + grid.windows(3).fold(0, |max, rows| { + let [row_0, row_1, row_2]: &[_; 3] = rows.try_into().ok().unwrap(); + + row_0 + .windows(3) + .zip(row_1.windows(3)) + .zip(row_2.windows(3)) + .fold(max, |max, ((top, middle), bottom)| { + let top: &[_; 3] = top.try_into().ok().unwrap(); + let middle: &[_; 3] = middle.try_into().ok().unwrap(); + let bottom: &[_; 3] = bottom.try_into().ok().unwrap(); + + u32::max( + max, + (top.iter().sum::() + middle[1] + bottom.iter().sum::()) as _, + ) + }) + }) as _ + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn max_sum(grid: Vec>) -> i32 { + Self::max_sum(grid) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2428_maximum_sum_of_an_hourglass/mod.rs b/src/problem_2428_maximum_sum_of_an_hourglass/mod.rs new file mode 100644 index 00000000..b60ff338 --- /dev/null +++ b/src/problem_2428_maximum_sum_of_an_hourglass/mod.rs @@ -0,0 +1,25 @@ +pub mod brute_force; + +pub trait Solution { + fn max_sum(grid: Vec>) -> i32; +} + +#[cfg(test)] +mod tests { + use super::Solution; + use crate::test_utilities::Matrix; + + pub fn run() { + let test_cases = [ + ( + &[[6, 2, 1, 3], [4, 2, 1, 5], [9, 2, 8, 7], [4, 1, 2, 9]] as &dyn Matrix<_>, + 30, + ), + (&[[1, 2, 3], [4, 5, 6], [7, 8, 9]], 35), + ]; + + for (grid, expected) in test_cases { + assert_eq!(S::max_sum(grid.to_vec()), expected); + } + } +} diff --git a/src/problem_2429_minimize_xor/greedy.rs b/src/problem_2429_minimize_xor/greedy.rs new file mode 100644 index 00000000..46104d20 --- /dev/null +++ b/src/problem_2429_minimize_xor/greedy.rs @@ -0,0 +1,61 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + pub fn minimize_xor(num1: i32, num2: i32) -> i32 { + let ones_1 = num1.count_ones(); + let ones_2 = num2.count_ones(); + let mut probe = 1; + + let min_value = if ones_1 < ones_2 { + let mut required_zeros = ones_2 - ones_1; + + loop { + while num1 & probe != 0 { + probe <<= 1; + } + + required_zeros -= 1; + probe <<= 1; + + if required_zeros == 0 { + break; + } + } + + !num1 + } else { + let mut required_ones = ones_1 - ones_2; + + while required_ones != 0 { + while num1 & probe == 0 { + probe <<= 1; + } + + required_ones -= 1; + probe <<= 1; + } + + num1 + }; + + num1 ^ (min_value & (probe - 1)) + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn minimize_xor(num1: i32, num2: i32) -> i32 { + Self::minimize_xor(num1, num2) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2429_minimize_xor/mod.rs b/src/problem_2429_minimize_xor/mod.rs new file mode 100644 index 00000000..a88cc078 --- /dev/null +++ b/src/problem_2429_minimize_xor/mod.rs @@ -0,0 +1,18 @@ +pub mod greedy; + +pub trait Solution { + fn minimize_xor(num1: i32, num2: i32) -> i32; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [((3, 5), 3), ((1, 12), 3), ((25, 72), 24)]; + + for ((num1, num2), expected) in test_cases { + assert_eq!(S::minimize_xor(num1, num2), expected); + } + } +}