Skip to content

Commit 4d0ff69

Browse files
feat: Add Catalan numbers implementation using dynamic programming
1 parent eaf895d commit 4d0ff69

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
* [Union Find](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/union_find.rs)
8888
* [Veb Tree](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/veb_tree.rs)
8989
* Dynamic Programming
90+
* [Catalan Numbers](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/catalan_numbers.rs)
9091
* [Coin Change](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/coin_change.rs)
9192
* [Egg Dropping](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/egg_dropping.rs)
9293
* [Fibonacci](https://github.com/TheAlgorithms/Rust/blob/master/src/dynamic_programming/fibonacci.rs)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//! Catalan Numbers using Dynamic Programming
2+
//!
3+
//! The Catalan numbers are a sequence of positive integers that appear in many
4+
//! counting problems in combinatorics. Such problems include counting:
5+
//! - The number of Dyck words of length 2n
6+
//! - The number of well-formed expressions with n pairs of parentheses
7+
//! (e.g., `()()` is valid but `())(` is not)
8+
//! - The number of different ways n + 1 factors can be completely parenthesized
9+
//! (e.g., for n = 2, C(n) = 2 and (ab)c and a(bc) are the two valid ways)
10+
//! - The number of full binary trees with n + 1 leaves
11+
//!
12+
//! A Catalan number satisfies the following recurrence relation:
13+
//! - C(0) = C(1) = 1
14+
//! - C(n) = sum(C(i) * C(n-i-1)), from i = 0 to n-1
15+
//!
16+
//! Sources:
17+
//! - [Brilliant.org](https://brilliant.org/wiki/catalan-numbers/)
18+
//! - [Wikipedia](https://en.wikipedia.org/wiki/Catalan_number)
19+
20+
/// Computes the Catalan number sequence from 0 through `upper_limit`.
21+
///
22+
/// # Arguments
23+
///
24+
/// * `upper_limit` - The upper limit for the Catalan sequence (must be ≥ 0)
25+
///
26+
/// # Returns
27+
///
28+
/// A vector containing Catalan numbers from C(0) to C(upper_limit)
29+
///
30+
/// # Examples
31+
///
32+
/// ```
33+
/// use the_algorithms_rust::dynamic_programming::catalan_numbers;
34+
///
35+
/// assert_eq!(catalan_numbers(5), vec![1, 1, 2, 5, 14, 42]);
36+
/// assert_eq!(catalan_numbers(2), vec![1, 1, 2]);
37+
/// assert_eq!(catalan_numbers(0), vec![1]);
38+
/// ```
39+
///
40+
/// # Panics
41+
///
42+
/// Panics if `upper_limit` would cause integer overflow during computation.
43+
pub fn catalan_numbers(upper_limit: usize) -> Vec<u64> {
44+
let mut catalan_list = vec![0u64; upper_limit + 1];
45+
46+
// Base case: C(0) = 1
47+
catalan_list[0] = 1;
48+
49+
// Base case: C(1) = 1
50+
if upper_limit > 0 {
51+
catalan_list[1] = 1;
52+
}
53+
54+
// Recurrence relation: C(i) = sum(C(j) * C(i-j-1)), from j = 0 to i-1
55+
for i in 2..=upper_limit {
56+
for j in 0..i {
57+
catalan_list[i] += catalan_list[j] * catalan_list[i - j - 1];
58+
}
59+
}
60+
61+
catalan_list
62+
}
63+
64+
#[cfg(test)]
65+
mod tests {
66+
use super::*;
67+
68+
#[test]
69+
fn test_catalan_numbers_basic() {
70+
assert_eq!(catalan_numbers(5), vec![1, 1, 2, 5, 14, 42]);
71+
assert_eq!(catalan_numbers(2), vec![1, 1, 2]);
72+
assert_eq!(catalan_numbers(0), vec![1]);
73+
}
74+
75+
#[test]
76+
fn test_catalan_numbers_single() {
77+
assert_eq!(catalan_numbers(1), vec![1, 1]);
78+
}
79+
80+
#[test]
81+
fn test_catalan_numbers_extended() {
82+
let result = catalan_numbers(10);
83+
assert_eq!(result.len(), 11);
84+
assert_eq!(result[0], 1);
85+
assert_eq!(result[1], 1);
86+
assert_eq!(result[2], 2);
87+
assert_eq!(result[3], 5);
88+
assert_eq!(result[4], 14);
89+
assert_eq!(result[5], 42);
90+
assert_eq!(result[6], 132);
91+
assert_eq!(result[7], 429);
92+
assert_eq!(result[8], 1430);
93+
assert_eq!(result[9], 4862);
94+
assert_eq!(result[10], 16796);
95+
}
96+
97+
#[test]
98+
fn test_catalan_first_few() {
99+
// Verify the first few Catalan numbers match known values
100+
assert_eq!(catalan_numbers(3), vec![1, 1, 2, 5]);
101+
assert_eq!(catalan_numbers(4), vec![1, 1, 2, 5, 14]);
102+
}
103+
}

src/dynamic_programming/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod catalan_numbers;
12
mod coin_change;
23
mod egg_dropping;
34
mod fibonacci;
@@ -21,6 +22,7 @@ mod task_assignment;
2122
mod trapped_rainwater;
2223
mod word_break;
2324

25+
pub use self::catalan_numbers::catalan_numbers;
2426
pub use self::coin_change::coin_change;
2527
pub use self::egg_dropping::egg_drop;
2628
pub use self::fibonacci::binary_lifting_fibonacci;

0 commit comments

Comments
 (0)