Skip to content

Commit 43299ac

Browse files
Add integer partition algorithm using dynamic programming (#976)
* Add integer partition algorithm using dynamic programming * Update integer_partition.rs * Update integer_partition.rs * Update integer_partition.rs --------- Co-authored-by: Andrii Siriak <siryaka@gmail.com>
1 parent b77770e commit 43299ac

File tree

3 files changed

+125
-9
lines changed

3 files changed

+125
-9
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
* [Egg Dropping](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/egg_dropping.rs)
105105
* [Fibonacci](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/fibonacci.rs)
106106
* [Fractional Knapsack](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/fractional_knapsack.rs)
107+
* [Integer Partition](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/integer_partition.rs)
107108
* [Is Subsequence](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/is_subsequence.rs)
108109
* [Knapsack](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/knapsack.rs)
109110
* [Longest Common Subsequence](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/longest_common_subsequence.rs)
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//! Integer partition using dynamic programming
2+
//!
3+
//! The number of partitions of a number n into at least k parts equals the number of
4+
//! partitions into exactly k parts plus the number of partitions into at least k-1 parts.
5+
//! Subtracting 1 from each part of a partition of n into k parts gives a partition of n-k
6+
//! into k parts. These two facts together are used for this algorithm.
7+
//!
8+
//! More info:
9+
//! * <https://en.wikipedia.org/wiki/Partition_(number_theory)>
10+
//! * <https://en.wikipedia.org/wiki/Partition_function_(number_theory)>
11+
12+
#![allow(clippy::large_stack_arrays)]
13+
14+
/// Calculates the number of partitions of a positive integer using dynamic programming.
15+
///
16+
/// # Arguments
17+
///
18+
/// * `m` - A positive integer to find the number of partitions for
19+
///
20+
/// # Returns
21+
///
22+
/// The number of partitions of `m`
23+
///
24+
/// # Panics
25+
///
26+
/// Panics if `m` is not a positive integer (0 or negative)
27+
///
28+
/// # Examples
29+
///
30+
/// ```
31+
/// # use the_algorithms_rust::dynamic_programming::partition;
32+
/// assert_eq!(partition(5), 7);
33+
/// assert_eq!(partition(7), 15);
34+
/// assert_eq!(partition(100), 190569292);
35+
/// ```
36+
#[allow(clippy::large_stack_arrays)]
37+
pub fn partition(m: i32) -> u128 {
38+
// Validate input
39+
assert!(m > 0, "Input must be a positive integer greater than 0");
40+
41+
let m = m as usize;
42+
43+
// Initialize memo table with zeros using iterative construction
44+
// to avoid large stack allocations
45+
let mut memo: Vec<Vec<u128>> = Vec::with_capacity(m + 1);
46+
for _ in 0..=m {
47+
memo.push(vec![0u128; m]);
48+
}
49+
50+
// Base case: there's one way to partition into 0 parts (empty partition)
51+
for i in 0..=m {
52+
memo[i][0] = 1;
53+
}
54+
55+
// Fill the memo table using dynamic programming
56+
for n in 0..=m {
57+
for k in 1..m {
58+
// Add partitions from k-1 (partitions with at least k-1 parts)
59+
memo[n][k] += memo[n][k - 1];
60+
61+
// Add partitions from n-k-1 with k parts (subtract 1 from each part)
62+
if n > k {
63+
memo[n][k] += memo[n - k - 1][k];
64+
}
65+
}
66+
}
67+
68+
memo[m][m - 1]
69+
}
70+
71+
#[cfg(test)]
72+
#[allow(clippy::large_stack_arrays)]
73+
mod tests {
74+
use super::*;
75+
76+
#[test]
77+
fn test_partition_5() {
78+
assert_eq!(partition(5), 7);
79+
}
80+
81+
#[test]
82+
fn test_partition_7() {
83+
assert_eq!(partition(7), 15);
84+
}
85+
86+
#[test]
87+
#[allow(clippy::large_stack_arrays)]
88+
fn test_partition_100() {
89+
assert_eq!(partition(100), 190569292);
90+
}
91+
92+
#[test]
93+
#[allow(clippy::large_stack_arrays)]
94+
fn test_partition_1000() {
95+
assert_eq!(partition(1000), 24061467864032622473692149727991);
96+
}
97+
98+
#[test]
99+
#[should_panic(expected = "Input must be a positive integer greater than 0")]
100+
fn test_partition_negative() {
101+
partition(-7);
102+
}
103+
104+
#[test]
105+
#[should_panic(expected = "Input must be a positive integer greater than 0")]
106+
fn test_partition_zero() {
107+
partition(0);
108+
}
109+
110+
#[test]
111+
fn test_partition_small_values() {
112+
assert_eq!(partition(1), 1);
113+
assert_eq!(partition(2), 2);
114+
assert_eq!(partition(3), 3);
115+
assert_eq!(partition(4), 5);
116+
}
117+
}

src/dynamic_programming/mod.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod coin_change;
33
mod egg_dropping;
44
mod fibonacci;
55
mod fractional_knapsack;
6+
mod integer_partition;
67
mod is_subsequence;
78
mod knapsack;
89
mod longest_common_subsequence;
@@ -27,16 +28,13 @@ mod word_break;
2728
pub use self::catalan_numbers::catalan_numbers;
2829
pub use self::coin_change::coin_change;
2930
pub use self::egg_dropping::egg_drop;
30-
pub use self::fibonacci::binary_lifting_fibonacci;
31-
pub use self::fibonacci::classical_fibonacci;
32-
pub use self::fibonacci::fibonacci;
33-
pub use self::fibonacci::last_digit_of_the_sum_of_nth_fibonacci_number;
34-
pub use self::fibonacci::logarithmic_fibonacci;
35-
pub use self::fibonacci::matrix_fibonacci;
36-
pub use self::fibonacci::memoized_fibonacci;
37-
pub use self::fibonacci::nth_fibonacci_number_modulo_m;
38-
pub use self::fibonacci::recursive_fibonacci;
31+
pub use self::fibonacci::{
32+
binary_lifting_fibonacci, classical_fibonacci, fibonacci,
33+
last_digit_of_the_sum_of_nth_fibonacci_number, logarithmic_fibonacci, matrix_fibonacci,
34+
memoized_fibonacci, nth_fibonacci_number_modulo_m, recursive_fibonacci,
35+
};
3936
pub use self::fractional_knapsack::fractional_knapsack;
37+
pub use self::integer_partition::partition;
4038
pub use self::is_subsequence::is_subsequence;
4139
pub use self::knapsack::knapsack;
4240
pub use self::longest_common_subsequence::longest_common_subsequence;

0 commit comments

Comments
 (0)