Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,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)
Expand Down
117 changes: 117 additions & 0 deletions src/dynamic_programming/integer_partition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//! 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:
//! * <https://en.wikipedia.org/wiki/Partition_(number_theory)>
//! * <https://en.wikipedia.org/wiki/Partition_function_(number_theory)>

#![allow(clippy::large_stack_arrays)]

/// 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);
/// ```
#[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 using iterative construction
// to avoid large stack allocations
let mut memo: Vec<Vec<u128>> = 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 {
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)]
#[allow(clippy::large_stack_arrays)]
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]
#[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);
}

#[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);
}
}
16 changes: 7 additions & 9 deletions src/dynamic_programming/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down