Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f789e3b

Browse files
authored
style: cleanup catalan_numbers.cpp (TheAlgorithms#2740)
* style: cleanup `catalan_numbers.cpp` * docs: update file level docs * style: use `std::transform_reduce`
1 parent 9374b00 commit f789e3b

File tree

1 file changed

+70
-64
lines changed

1 file changed

+70
-64
lines changed

‎dynamic_programming/catalan_numbers.cpp

Lines changed: 70 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,81 @@
1-
/** Print all the Catalan numbers from 0 to n, n being the user input.
2-
3-
* A Catalan number satifies the following two properties:
4-
* C(0) = C(1) = 1; C(n) = sum(C(i).C(n-i-1)), from i = 0 to n-1
1+
/**
2+
* @file
3+
* @brief Provides utilities to compute Catalan numbers using dynamic
4+
programming.
5+
* A Catalan numbers satisfy these recurrence relations:
6+
* C(0) = C(1) = 1; C(n) = sum(C(i).C(n-i-1)), for i = 0 to n-1
57
* Read more about Catalan numbers here:
68
https://en.wikipedia.org/wiki/Catalan_number
9+
https://oeis.org/A000108/
710
*/
811

9-
#include <iostream>
10-
using namespace std;
11-
12-
int *cat; // global array to hold catalan numbers
13-
14-
unsigned long int catalan_dp(int n) {
15-
/** Using the tabulation technique in dynamic programming,
16-
this function computes the first `n+1` Catalan numbers
17-
18-
Parameter
19-
---------
20-
n: The number of catalan numbers to be computed.
12+
#include <cassert> /// for assert
13+
#include <cstdint> /// for std::uint64_t
14+
#include <cstdlib> /// for std::size_t
15+
#include <numeric> /// for std::transform_reduce
16+
#include <vector> /// for std::vector
2117

22-
Returns
23-
-------
24-
cat[n]: An array containing the first `n+1` Catalan numbers
25-
*/
26-
27-
// By definition, the first two Catalan numbers are 1
28-
cat[0] = cat[1] = 1;
29-
30-
// Compute the remaining numbers from index 2 to index n, using tabulation
31-
for (int i = 2; i <= n; i++) {
32-
cat[i] = 0;
33-
for (int j = 0; j < i; j++)
34-
cat[i] += cat[j] * cat[i - j - 1]; // applying the definition here
18+
/**
19+
* @brief computes and caches Catalan numbers
20+
*/
21+
class catalan_numbers {
22+
using value_type = std::uint64_t;
23+
std::vector<value_type> known{1, 1};
24+
25+
value_type compute_next() {
26+
return std::transform_reduce(known.begin(), known.end(), known.rbegin(),
27+
static_cast<value_type>(), std::plus<>(),
28+
std::multiplies<>());
3529
}
3630

37-
// Return the result
38-
return cat[n];
39-
}
40-
41-
int main(int argc, char *argv[]) {
42-
int n;
43-
cout << "Enter n: ";
44-
cin >> n;
45-
46-
cat = new int[n + 1];
47-
48-
cout << "Catalan numbers from 0 to " << n << " are:\n";
49-
for (int i = 0; i <= n; i++) {
50-
cout << "catalan (" << i << ") = " << catalan_dp(i) << endl;
51-
// NOTE: Since `cat` is a global array, calling `catalan_dp`
52-
// repeatedly will not recompute the the values already computed
53-
// as in case of pre-computed values, the array will simply return them,
54-
// instead of recomputing them.
31+
void add() { known.push_back(this->compute_next()); }
32+
33+
public:
34+
/**
35+
* @brief computes the n-th Catalan number and updates the cache.
36+
* @return the n-th Catalan number
37+
*/
38+
value_type get(std::size_t n) {
39+
while (known.size() <= n) {
40+
this->add();
41+
}
42+
return known[n];
5543
}
56-
57-
return 0;
44+
};
45+
46+
void test_catalan_numbers_up_to_20() {
47+
// data verified with https://oeis.org/A000108/
48+
catalan_numbers cn;
49+
assert(cn.get(0) == 1ULL);
50+
assert(cn.get(1) == 1ULL);
51+
assert(cn.get(2) == 2ULL);
52+
assert(cn.get(3) == 5ULL);
53+
assert(cn.get(4) == 14ULL);
54+
assert(cn.get(5) == 42ULL);
55+
assert(cn.get(6) == 132ULL);
56+
assert(cn.get(7) == 429ULL);
57+
assert(cn.get(8) == 1430ULL);
58+
assert(cn.get(9) == 4862ULL);
59+
assert(cn.get(10) == 16796ULL);
60+
assert(cn.get(11) == 58786ULL);
61+
assert(cn.get(12) == 208012ULL);
62+
assert(cn.get(13) == 742900ULL);
63+
assert(cn.get(14) == 2674440ULL);
64+
assert(cn.get(15) == 9694845ULL);
65+
assert(cn.get(16) == 35357670ULL);
66+
assert(cn.get(17) == 129644790ULL);
67+
assert(cn.get(18) == 477638700ULL);
68+
assert(cn.get(19) == 1767263190ULL);
69+
assert(cn.get(20) == 6564120420ULL);
5870
}
5971

60-
/** Sample Test Case:
61-
62-
$ cd "Dynamic Programming"
63-
$ g++ Catalan-Numbers.cpp
64-
$ ./a.exe
65-
66-
Enter n: 5
67-
Catalan numbers from 0 to 5 are:
68-
catalan (0) = 1
69-
catalan (1) = 1
70-
catalan (2) = 2
71-
catalan (3) = 5
72-
catalan (4) = 14
73-
catalan (5) = 42
72+
void test_catalan_numbers_25() {
73+
// data verified with https://oeis.org/A000108/
74+
catalan_numbers cn;
75+
assert(cn.get(25) == 4861946401452ULL);
76+
}
7477

75-
*/
78+
int main() {
79+
test_catalan_numbers_up_to_20();
80+
test_catalan_numbers_25();
81+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /