From e91666715aeed7cdc7e32937721e8af411797e0a Mon Sep 17 00:00:00 2001 From: Ali Alimohammadi Date: Wed, 24 Dec 2025 14:53:57 -0800 Subject: [PATCH 1/4] Add integer partition algorithm using dynamic programming --- DIRECTORY.md | 1 + src/dynamic_programming/integer_partition.rs | 107 +++++++++++++++++++ src/dynamic_programming/mod.rs | 16 ++- 3 files changed, 115 insertions(+), 9 deletions(-) create mode 100644 src/dynamic_programming/integer_partition.rs diff --git a/DIRECTORY.md b/DIRECTORY.md index eb6cdc1525e..75c9beb28f2 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -103,6 +103,7 @@ * [Egg Dropping](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/egg_dropping.rs) * [Fibonacci](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/fibonacci.rs) * [Fractional Knapsack](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/fractional_knapsack.rs) + * [Integer Partition](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/integer_partition.rs) * [Is Subsequence](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/is_subsequence.rs) * [Knapsack](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/knapsack.rs) * [Longest Common Subsequence](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/longest_common_subsequence.rs) diff --git a/src/dynamic_programming/integer_partition.rs b/src/dynamic_programming/integer_partition.rs new file mode 100644 index 00000000000..dfe52908c27 --- /dev/null +++ b/src/dynamic_programming/integer_partition.rs @@ -0,0 +1,107 @@ +//! Integer partition using dynamic programming +//! +//! The number of partitions of a number n into at least k parts equals the number of +//! partitions into exactly k parts plus the number of partitions into at least k-1 parts. +//! Subtracting 1 from each part of a partition of n into k parts gives a partition of n-k +//! into k parts. These two facts together are used for this algorithm. +//! +//! More info: +//! * +//! * + +/// Calculates the number of partitions of a positive integer using dynamic programming. +/// +/// # Arguments +/// +/// * `m` - A positive integer to find the number of partitions for +/// +/// # Returns +/// +/// The number of partitions of `m` +/// +/// # Panics +/// +/// Panics if `m` is not a positive integer (0 or negative) +/// +/// # Examples +/// +/// ``` +/// # use the_algorithms_rust::dynamic_programming::partition; +/// assert_eq!(partition(5), 7); +/// assert_eq!(partition(7), 15); +/// assert_eq!(partition(100), 190569292); +/// ``` +pub fn partition(m: i32) -> u128 { + // Validate input + assert!(m > 0, "Input must be a positive integer greater than 0"); + + let m = m as usize; + + // Initialize memo table with zeros + let mut memo = vec![vec![0u128; m]; m + 1]; + + // Base case: there's one way to partition into 0 parts (empty partition) + for i in 0..=m { + memo[i][0] = 1; + } + + // Fill the memo table using dynamic programming + for n in 0..=m { + for k in 1..m { + // Add partitions from k-1 (partitions with at least k-1 parts) + memo[n][k] += memo[n][k - 1]; + + // Add partitions from n-k-1 with k parts (subtract 1 from each part) + if n > k { + memo[n][k] += memo[n - k - 1][k]; + } + } + } + + memo[m][m - 1] +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_partition_5() { + assert_eq!(partition(5), 7); + } + + #[test] + fn test_partition_7() { + assert_eq!(partition(7), 15); + } + + #[test] + fn test_partition_100() { + assert_eq!(partition(100), 190569292); + } + + #[test] + fn test_partition_1000() { + assert_eq!(partition(1000), 24061467864032622473692149727991); + } + + #[test] + #[should_panic(expected = "Input must be a positive integer greater than 0")] + fn test_partition_negative() { + partition(-7); + } + + #[test] + #[should_panic(expected = "Input must be a positive integer greater than 0")] + fn test_partition_zero() { + partition(0); + } + + #[test] + fn test_partition_small_values() { + assert_eq!(partition(1), 1); + assert_eq!(partition(2), 2); + assert_eq!(partition(3), 3); + assert_eq!(partition(4), 5); + } +} diff --git a/src/dynamic_programming/mod.rs b/src/dynamic_programming/mod.rs index 7f5de2be42c..c96f0ff820d 100644 --- a/src/dynamic_programming/mod.rs +++ b/src/dynamic_programming/mod.rs @@ -3,6 +3,7 @@ mod coin_change; mod egg_dropping; mod fibonacci; mod fractional_knapsack; +mod integer_partition; mod is_subsequence; mod knapsack; mod longest_common_subsequence; @@ -27,16 +28,13 @@ mod word_break; pub use self::catalan_numbers::catalan_numbers; pub use self::coin_change::coin_change; pub use self::egg_dropping::egg_drop; -pub use self::fibonacci::binary_lifting_fibonacci; -pub use self::fibonacci::classical_fibonacci; -pub use self::fibonacci::fibonacci; -pub use self::fibonacci::last_digit_of_the_sum_of_nth_fibonacci_number; -pub use self::fibonacci::logarithmic_fibonacci; -pub use self::fibonacci::matrix_fibonacci; -pub use self::fibonacci::memoized_fibonacci; -pub use self::fibonacci::nth_fibonacci_number_modulo_m; -pub use self::fibonacci::recursive_fibonacci; +pub use self::fibonacci::{ + binary_lifting_fibonacci, classical_fibonacci, fibonacci, + last_digit_of_the_sum_of_nth_fibonacci_number, logarithmic_fibonacci, matrix_fibonacci, + memoized_fibonacci, nth_fibonacci_number_modulo_m, recursive_fibonacci, +}; pub use self::fractional_knapsack::fractional_knapsack; +pub use self::integer_partition::partition; pub use self::is_subsequence::is_subsequence; pub use self::knapsack::knapsack; pub use self::longest_common_subsequence::longest_common_subsequence; From 8512d917b423ece61d0150ede3990f2644c35506 Mon Sep 17 00:00:00 2001 From: Ali Alimohammadi <41567902+AliAlimohammadi@users.noreply.github.com> Date: Wed, 24 Dec 2025 14:58:16 -0800 Subject: [PATCH 2/4] Update integer_partition.rs --- src/dynamic_programming/integer_partition.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dynamic_programming/integer_partition.rs b/src/dynamic_programming/integer_partition.rs index dfe52908c27..25903f77681 100644 --- a/src/dynamic_programming/integer_partition.rs +++ b/src/dynamic_programming/integer_partition.rs @@ -31,6 +31,7 @@ /// assert_eq!(partition(7), 15); /// assert_eq!(partition(100), 190569292); /// ``` +#[allow(clippy::large_stack_arrays)] pub fn partition(m: i32) -> u128 { // Validate input assert!(m > 0, "Input must be a positive integer greater than 0"); From bf22900b37c7cb026451781ee674f70979121274 Mon Sep 17 00:00:00 2001 From: Ali Alimohammadi <41567902+AliAlimohammadi@users.noreply.github.com> Date: Wed, 24 Dec 2025 15:01:30 -0800 Subject: [PATCH 3/4] Update integer_partition.rs --- src/dynamic_programming/integer_partition.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dynamic_programming/integer_partition.rs b/src/dynamic_programming/integer_partition.rs index 25903f77681..fbec8414c4f 100644 --- a/src/dynamic_programming/integer_partition.rs +++ b/src/dynamic_programming/integer_partition.rs @@ -9,6 +9,8 @@ //! * //! * +#![allow(clippy::large_stack_arrays)] + /// Calculates the number of partitions of a positive integer using dynamic programming. /// /// # Arguments @@ -31,7 +33,6 @@ /// assert_eq!(partition(7), 15); /// assert_eq!(partition(100), 190569292); /// ``` -#[allow(clippy::large_stack_arrays)] pub fn partition(m: i32) -> u128 { // Validate input assert!(m > 0, "Input must be a positive integer greater than 0"); From 976ae9defbd33a0dc840c1f47aa2ccd3cb8de7f9 Mon Sep 17 00:00:00 2001 From: Ali Alimohammadi <41567902+AliAlimohammadi@users.noreply.github.com> Date: Wed, 24 Dec 2025 15:11:54 -0800 Subject: [PATCH 4/4] Update integer_partition.rs --- src/dynamic_programming/integer_partition.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/dynamic_programming/integer_partition.rs b/src/dynamic_programming/integer_partition.rs index fbec8414c4f..d8e9b2f6461 100644 --- a/src/dynamic_programming/integer_partition.rs +++ b/src/dynamic_programming/integer_partition.rs @@ -33,14 +33,19 @@ /// assert_eq!(partition(7), 15); /// assert_eq!(partition(100), 190569292); /// ``` +#[allow(clippy::large_stack_arrays)] pub fn partition(m: i32) -> u128 { // Validate input assert!(m > 0, "Input must be a positive integer greater than 0"); let m = m as usize; - // Initialize memo table with zeros - let mut memo = vec![vec![0u128; m]; m + 1]; + // Initialize memo table with zeros using iterative construction + // to avoid large stack allocations + let mut memo: Vec> = Vec::with_capacity(m + 1); + for _ in 0..=m { + memo.push(vec![0u128; m]); + } // Base case: there's one way to partition into 0 parts (empty partition) for i in 0..=m { @@ -64,6 +69,7 @@ pub fn partition(m: i32) -> u128 { } #[cfg(test)] +#[allow(clippy::large_stack_arrays)] mod tests { use super::*; @@ -78,11 +84,13 @@ mod tests { } #[test] + #[allow(clippy::large_stack_arrays)] fn test_partition_100() { assert_eq!(partition(100), 190569292); } #[test] + #[allow(clippy::large_stack_arrays)] fn test_partition_1000() { assert_eq!(partition(1000), 24061467864032622473692149727991); }