Skip to content

Commit

Permalink
Add problem 1655: Distribute Repeating Integers
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Oct 29, 2023
1 parent c8257b9 commit 376e589
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,7 @@ pub mod problem_1648_sell_diminishing_valued_colored_balls;
pub mod problem_1649_create_sorted_array_through_instructions;
pub mod problem_1652_defuse_the_bomb;
pub mod problem_1653_minimum_deletions_to_make_string_balanced;
pub mod problem_1655_distribute_repeating_integers;
pub mod problem_1656_design_an_ordered_stream;
pub mod problem_1657_determine_if_two_strings_are_close;
pub mod problem_1658_minimum_operations_to_reduce_x_to_zero;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

use std::mem;

impl Solution {
fn count_nums(nums: Vec<i32>) -> Box<[u32]> {
let mut counts = [0; 1000];
let mut unique_numbers = Vec::with_capacity(50);

for num in nums {
let index = num as u32 as usize - 1;
let count = &mut counts[index];

if *count == 0 {
unique_numbers.push(index as _);
}

*count += 1;
}

let mut unique_numbers = unique_numbers.into_boxed_slice();

for slot in &mut *unique_numbers {
*slot = counts[*slot as usize];
}

unique_numbers
}

fn get_quantity_sums(value: Vec<i32>) -> ([u32; 1024], usize) {
let n = value.len();
let mut result = [0_u32; 1024];

assert!(n <= 10);

for bits in 1..(1 << n) {
result[bits] = result[bits & (bits - 1)] + value[bits.trailing_zeros() as usize] as u32;
}

(result, n)
}

pub fn can_distribute(nums: Vec<i32>, quantity: Vec<i32>) -> bool {
let counts = Self::count_nums(nums);
let (quantity_sums, n) = Self::get_quantity_sums(quantity);
let cache_size = 1 << n;
let mut buffer = [false; 2048];
let (mut cache, mut temp) = buffer[..cache_size * 2].split_at_mut(cache_size);

cache[0] = true;

for &count in &*counts {
for (target_bits, target) in (0_u16..).zip(&mut *temp) {
let mut selected_bits = target_bits;

// See <https://cp-algorithms.com/algebra/all-submasks.html>.

*target = loop {
if quantity_sums[usize::from(selected_bits)] <= count
&& cache[usize::from(target_bits ^ selected_bits)]
{
break true;
}

if selected_bits == 0 {
break false;
}

selected_bits = (selected_bits - 1) & target_bits;
};
}

mem::swap(&mut cache, &mut temp);
}

*cache.last().unwrap()
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn can_distribute(nums: Vec<i32>, quantity: Vec<i32>) -> bool {
Self::can_distribute(nums, quantity)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
36 changes: 36 additions & 0 deletions src/problem_1655_distribute_repeating_integers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
pub mod dynamic_programming;

pub trait Solution {
fn can_distribute(nums: Vec<i32>, quantity: Vec<i32>) -> bool;
}

#[cfg(test)]
mod tests {
use super::Solution;

pub fn run<S: Solution>() {
let test_cases = [
((&[1, 2, 3, 4] as &[_], &[2] as &[_]), false),
((&[1, 2, 3, 3], &[2]), true),
((&[1, 1, 2, 2], &[2, 2]), true),
(
(
&[
1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26,
27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38,
39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50,
],
&[2, 2, 2, 2, 2, 2, 2, 2, 2, 3],
),
false,
),
((&[1, 1, 2, 2, 1], &[2, 2, 1]), true),
((&[1, 1, 1, 1, 2, 2, 2], &[3, 2, 2]), true),
];

for ((nums, quantity), expected) in test_cases {
assert_eq!(S::can_distribute(nums.to_vec(), quantity.to_vec()), expected);
}
}
}

0 comments on commit 376e589

Please sign in to comment.