From a977badeee37a64deb07c3e66fd9467014e5a298 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Sat, 6 Apr 2024 15:58:14 +0700 Subject: [PATCH 01/10] chore: add `trapped_rainwater.cpp` to DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index bda68918d88..41f9be01a53 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -11,6 +11,7 @@ * [Rat Maze](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/rat_maze.cpp) * [Subarray Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/subarray_sum.cpp) * [Subset Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/subset_sum.cpp) + * [Trapped Rain Water](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/trapped_rainwater.cpp) * [Sudoku Solver](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/sudoku_solver.cpp) * [Wildcard Matching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/wildcard_matching.cpp) From 5c4c54d29cac8ddb6bd1d0cb0622b9b56fa0d694 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Sat, 6 Apr 2024 15:58:47 +0700 Subject: [PATCH 02/10] feat: implement Trapped Rain Water algorithm --- dynamic_programming/trapped_rainwater.cpp | 77 +++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 dynamic_programming/trapped_rainwater.cpp diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp new file mode 100644 index 00000000000..4c73266697f --- /dev/null +++ b/dynamic_programming/trapped_rainwater.cpp @@ -0,0 +1,77 @@ +/** + * @file + * @brief Implementation of the Trapped Rainwater Problem + * @details + * This implementation calculates the amount of rainwater that can be trapped + * between walls represented by an array of heights. + */ + +#include /// For std::min and std::max +#include /// For assert +#include /// For IO operations +#include /// For vector container + +/* + * @namespace + * @brief Dynamic Programming Algorithms + */ +namespace dynamic_programming { +/** + * @brief Function to calculate the trapped rainwater + * @param heights Array representing the heights of walls + * @return The amount of trapped rainwater + */ +int trappedRainwater(const std::vector& heights) { + int n = heights.size(); + if (n <= 2) + return 0; // No water can be trapped with less than 3 walls + + std::vector leftMax(n), rightMax(n); + + // Calculate the maximum height of wall to the left of each wall + leftMax[0] = heights[0]; + for (int i = 1; i < n; ++i) { + leftMax[i] = std::max(leftMax[i - 1], heights[i]); + } + + // Calculate the maximum height of wall to the right of each wall + rightMax[n - 1] = heights[n - 1]; + for (int i = n - 2; i >= 0; --i) { + rightMax[i] = std::max(rightMax[i + 1], heights[i]); + } + + // Calculate the trapped rainwater between walls + int trappedWater = 0; + for (int i = 0; i < n; ++i) { + trappedWater += + std::max(0, std::min(leftMax[i], rightMax[i]) - heights[i]); + } + + return trappedWater; +} + +} // namespace dynamic_programming + +/** + * @brief Self-test implementations + * @returns void + */ +static void test() { + std::vector heights1 = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; + assert(dynamic_programming::trappedRainwater(heights1) == 6); + + std::vector heights2 = {3, 0, 0, 2, 0, 4}; + assert(dynamic_programming::trappedRainwater(heights2) == 10); + + std::vector heights3 = {1, 2, 3, 4, 5}; + assert(dynamic_programming::trappedRainwater(heights3) == 0); +} + +/** + * @brief Main function + * @returns 0 on exit + */ +int main() { + test(); // run self-test implementations + return 0; +} From b8891e26cf718fb19b508f0b60867765aa51fc55 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Tue, 30 Apr 2024 19:01:46 +0700 Subject: [PATCH 03/10] chore: add links to the trapped rain water problem --- dynamic_programming/trapped_rainwater.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp index 4c73266697f..10ccc2f7706 100644 --- a/dynamic_programming/trapped_rainwater.cpp +++ b/dynamic_programming/trapped_rainwater.cpp @@ -1,6 +1,7 @@ /** * @file - * @brief Implementation of the Trapped Rainwater Problem + * @brief Implementation of the [Trapped Rainwater + * Problem](https://www.geeksforgeeks.org/trapping-rain-water/) * @details * This implementation calculates the amount of rainwater that can be trapped * between walls represented by an array of heights. @@ -57,6 +58,9 @@ int trappedRainwater(const std::vector& heights) { * @returns void */ static void test() { + std::vector heights0 = {0, 1}; + assert(dynamic_programming::trappedRainwater(heights0) == 0); + std::vector heights1 = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; assert(dynamic_programming::trappedRainwater(heights1) == 6); From 2f1beb496a15c89942d3bbe9ee927d72cd4cfc79 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Tue, 30 Apr 2024 19:02:35 +0700 Subject: [PATCH 04/10] chore(docs): remove Trapped Rain Water dir --- DIRECTORY.md | 1 - 1 file changed, 1 deletion(-) diff --git a/DIRECTORY.md b/DIRECTORY.md index 41f9be01a53..bda68918d88 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -11,7 +11,6 @@ * [Rat Maze](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/rat_maze.cpp) * [Subarray Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/subarray_sum.cpp) * [Subset Sum](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/subset_sum.cpp) - * [Trapped Rain Water](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/trapped_rainwater.cpp) * [Sudoku Solver](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/sudoku_solver.cpp) * [Wildcard Matching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/HEAD/backtracking/wildcard_matching.cpp) From 4995696f992072d0b23dc3d929d0bff92c1a2a09 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Sat, 31 Aug 2024 09:43:50 +0700 Subject: [PATCH 05/10] ref: add edges tests --- dynamic_programming/trapped_rainwater.cpp | 38 +++++++++++++++++------ 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp index 10ccc2f7706..88e68779afb 100644 --- a/dynamic_programming/trapped_rainwater.cpp +++ b/dynamic_programming/trapped_rainwater.cpp @@ -9,7 +9,6 @@ #include /// For std::min and std::max #include /// For assert -#include /// For IO operations #include /// For vector container /* @@ -58,17 +57,38 @@ int trappedRainwater(const std::vector& heights) { * @returns void */ static void test() { - std::vector heights0 = {0, 1}; - assert(dynamic_programming::trappedRainwater(heights0) == 0); + std::vector test_basic = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; + assert(dynamic_programming::trappedRainwater(test_basic) == 6); - std::vector heights1 = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; - assert(dynamic_programming::trappedRainwater(heights1) == 6); + std::vector test_peak_under_water = {3, 0, 2, 0, 4}; + assert(dynamic_programming::trappedRainwater(test_peak_under_water) == 7); - std::vector heights2 = {3, 0, 0, 2, 0, 4}; - assert(dynamic_programming::trappedRainwater(heights2) == 10); + std::vector test_bucket = {5, 1, 5}; + assert(dynamic_programming::trappedRainwater(test_bucket) == 4); - std::vector heights3 = {1, 2, 3, 4, 5}; - assert(dynamic_programming::trappedRainwater(heights3) == 0); + std::vector test_skewed_bucket = {4, 1, 5}; + assert(dynamic_programming::trappedRainwater(test_skewed_bucket) == 3); + + std::vector test_empty = {}; + assert(dynamic_programming::trappedRainwater(test_empty) == 0); + + std::vector test_flat = {0, 0, 0, 0, 0}; + assert(dynamic_programming::trappedRainwater(test_flat) == 0); + + std::vector test_no_trapped_water = {1, 1, 2, 4, 0, 0, 0}; + assert(dynamic_programming::trappedRainwater(test_no_trapped_water) == 0); + + std::vector test_single_elevation = {5}; + assert(dynamic_programming::trappedRainwater(test_single_elevation) == 0); + + std::vector test_two_point_elevation = {5, 1}; + assert(dynamic_programming::trappedRainwater(test_two_point_elevation) == + 0); + + std::vector test_large_elevation_map_difference = {5, 1, 6, 1, + 7, 1, 8}; + assert(dynamic_programming::trappedRainwater( + test_large_elevation_map_difference) == 15); } /** From d8bf45b42eaa82439e2f5d8ea09d87e921be03fd Mon Sep 17 00:00:00 2001 From: realstealthninja <68815218+realstealthninja@users.noreply.github.com> Date: Sat, 31 Aug 2024 09:43:43 +0530 Subject: [PATCH 06/10] doc: adding Sozel as author --- dynamic_programming/trapped_rainwater.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp index 88e68779afb..df99fc19092 100644 --- a/dynamic_programming/trapped_rainwater.cpp +++ b/dynamic_programming/trapped_rainwater.cpp @@ -5,6 +5,7 @@ * @details * This implementation calculates the amount of rainwater that can be trapped * between walls represented by an array of heights. + * @author [SOZEL](https://github.com/TruongNhanNguyen) */ #include /// For std::min and std::max From 5be0b5844669a9de038f8a82c75096dbffb41590 Mon Sep 17 00:00:00 2001 From: realstealthninja <68815218+realstealthninja@users.noreply.github.com> Date: Sat, 31 Aug 2024 09:44:13 +0530 Subject: [PATCH 07/10] doc: includes documentatino --- dynamic_programming/trapped_rainwater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp index df99fc19092..3e379e5c8da 100644 --- a/dynamic_programming/trapped_rainwater.cpp +++ b/dynamic_programming/trapped_rainwater.cpp @@ -10,7 +10,7 @@ #include /// For std::min and std::max #include /// For assert -#include /// For vector container +#include /// For std::vector /* * @namespace From 05f506294e3ca88408af12e656f7988fb08699d8 Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Sat, 31 Aug 2024 11:20:08 +0700 Subject: [PATCH 08/10] ref: use `unsigned int` for height of walls --- dynamic_programming/trapped_rainwater.cpp | 39 ++++++++++++----------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp index 3e379e5c8da..1493bc91a7e 100644 --- a/dynamic_programming/trapped_rainwater.cpp +++ b/dynamic_programming/trapped_rainwater.cpp @@ -10,6 +10,7 @@ #include /// For std::min and std::max #include /// For assert +#include /// For std::size_t #include /// For std::vector /* @@ -22,30 +23,30 @@ namespace dynamic_programming { * @param heights Array representing the heights of walls * @return The amount of trapped rainwater */ -int trappedRainwater(const std::vector& heights) { - int n = heights.size(); +unsigned int trappedRainwater(const std::vector& heights) { + std::size_t n = heights.size(); if (n <= 2) return 0; // No water can be trapped with less than 3 walls - std::vector leftMax(n), rightMax(n); + std::vector leftMax(n), rightMax(n); // Calculate the maximum height of wall to the left of each wall leftMax[0] = heights[0]; - for (int i = 1; i < n; ++i) { + for (std::size_t i = 1; i < n; ++i) { leftMax[i] = std::max(leftMax[i - 1], heights[i]); } // Calculate the maximum height of wall to the right of each wall rightMax[n - 1] = heights[n - 1]; - for (int i = n - 2; i >= 0; --i) { + for (std::size_t i = n - 2; i < n; --i) { rightMax[i] = std::max(rightMax[i + 1], heights[i]); } // Calculate the trapped rainwater between walls - int trappedWater = 0; - for (int i = 0; i < n; ++i) { + unsigned int trappedWater = 0; + for (std::size_t i = 0; i < n; ++i) { trappedWater += - std::max(0, std::min(leftMax[i], rightMax[i]) - heights[i]); + std::max(0u, std::min(leftMax[i], rightMax[i]) - heights[i]); } return trappedWater; @@ -58,36 +59,36 @@ int trappedRainwater(const std::vector& heights) { * @returns void */ static void test() { - std::vector test_basic = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; + std::vector test_basic = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; assert(dynamic_programming::trappedRainwater(test_basic) == 6); - std::vector test_peak_under_water = {3, 0, 2, 0, 4}; + std::vector test_peak_under_water = {3, 0, 2, 0, 4}; assert(dynamic_programming::trappedRainwater(test_peak_under_water) == 7); - std::vector test_bucket = {5, 1, 5}; + std::vector test_bucket = {5, 1, 5}; assert(dynamic_programming::trappedRainwater(test_bucket) == 4); - std::vector test_skewed_bucket = {4, 1, 5}; + std::vector test_skewed_bucket = {4, 1, 5}; assert(dynamic_programming::trappedRainwater(test_skewed_bucket) == 3); - std::vector test_empty = {}; + std::vector test_empty = {}; assert(dynamic_programming::trappedRainwater(test_empty) == 0); - std::vector test_flat = {0, 0, 0, 0, 0}; + std::vector test_flat = {0, 0, 0, 0, 0}; assert(dynamic_programming::trappedRainwater(test_flat) == 0); - std::vector test_no_trapped_water = {1, 1, 2, 4, 0, 0, 0}; + std::vector test_no_trapped_water = {1, 1, 2, 4, 0, 0, 0}; assert(dynamic_programming::trappedRainwater(test_no_trapped_water) == 0); - std::vector test_single_elevation = {5}; + std::vector test_single_elevation = {5}; assert(dynamic_programming::trappedRainwater(test_single_elevation) == 0); - std::vector test_two_point_elevation = {5, 1}; + std::vector test_two_point_elevation = {5, 1}; assert(dynamic_programming::trappedRainwater(test_two_point_elevation) == 0); - std::vector test_large_elevation_map_difference = {5, 1, 6, 1, - 7, 1, 8}; + std::vector test_large_elevation_map_difference = {5, 1, 6, 1, + 7, 1, 8}; assert(dynamic_programming::trappedRainwater( test_large_elevation_map_difference) == 15); } From d6b091e4a5d488c5195df43403e5c7f199a124d3 Mon Sep 17 00:00:00 2001 From: realstealthninja <68815218+realstealthninja@users.noreply.github.com> Date: Sat, 31 Aug 2024 11:51:45 +0530 Subject: [PATCH 09/10] fix: use fixed-width integers instead of unsigned int --- dynamic_programming/trapped_rainwater.cpp | 27 ++++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp index 1493bc91a7e..16d4d842cfa 100644 --- a/dynamic_programming/trapped_rainwater.cpp +++ b/dynamic_programming/trapped_rainwater.cpp @@ -12,6 +12,7 @@ #include /// For assert #include /// For std::size_t #include /// For std::vector +#include /// For integral typedefs /* * @namespace @@ -23,12 +24,12 @@ namespace dynamic_programming { * @param heights Array representing the heights of walls * @return The amount of trapped rainwater */ -unsigned int trappedRainwater(const std::vector& heights) { +uint32_t trappedRainwater(const std::vector& heights) { std::size_t n = heights.size(); if (n <= 2) return 0; // No water can be trapped with less than 3 walls - std::vector leftMax(n), rightMax(n); + std::vector leftMax(n), rightMax(n); // Calculate the maximum height of wall to the left of each wall leftMax[0] = heights[0]; @@ -43,7 +44,7 @@ unsigned int trappedRainwater(const std::vector& heights) { } // Calculate the trapped rainwater between walls - unsigned int trappedWater = 0; + uint32_t trappedWater = 0; for (std::size_t i = 0; i < n; ++i) { trappedWater += std::max(0u, std::min(leftMax[i], rightMax[i]) - heights[i]); @@ -59,35 +60,35 @@ unsigned int trappedRainwater(const std::vector& heights) { * @returns void */ static void test() { - std::vector test_basic = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; + std::vector test_basic = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; assert(dynamic_programming::trappedRainwater(test_basic) == 6); - std::vector test_peak_under_water = {3, 0, 2, 0, 4}; + std::vector test_peak_under_water = {3, 0, 2, 0, 4}; assert(dynamic_programming::trappedRainwater(test_peak_under_water) == 7); - std::vector test_bucket = {5, 1, 5}; + std::vector test_bucket = {5, 1, 5}; assert(dynamic_programming::trappedRainwater(test_bucket) == 4); - std::vector test_skewed_bucket = {4, 1, 5}; + std::vector test_skewed_bucket = {4, 1, 5}; assert(dynamic_programming::trappedRainwater(test_skewed_bucket) == 3); - std::vector test_empty = {}; + std::vector test_empty = {}; assert(dynamic_programming::trappedRainwater(test_empty) == 0); - std::vector test_flat = {0, 0, 0, 0, 0}; + std::vector test_flat = {0, 0, 0, 0, 0}; assert(dynamic_programming::trappedRainwater(test_flat) == 0); - std::vector test_no_trapped_water = {1, 1, 2, 4, 0, 0, 0}; + std::vector test_no_trapped_water = {1, 1, 2, 4, 0, 0, 0}; assert(dynamic_programming::trappedRainwater(test_no_trapped_water) == 0); - std::vector test_single_elevation = {5}; + std::vector test_single_elevation = {5}; assert(dynamic_programming::trappedRainwater(test_single_elevation) == 0); - std::vector test_two_point_elevation = {5, 1}; + std::vector test_two_point_elevation = {5, 1}; assert(dynamic_programming::trappedRainwater(test_two_point_elevation) == 0); - std::vector test_large_elevation_map_difference = {5, 1, 6, 1, + std::vector test_large_elevation_map_difference = {5, 1, 6, 1, 7, 1, 8}; assert(dynamic_programming::trappedRainwater( test_large_elevation_map_difference) == 15); From 04b65139537423fb4ce9cb378b9a28513a4b422c Mon Sep 17 00:00:00 2001 From: Truong Nhan Nguyen Date: Sat, 31 Aug 2024 14:28:15 +0700 Subject: [PATCH 10/10] chore: rearrange included libraries --- dynamic_programming/trapped_rainwater.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dynamic_programming/trapped_rainwater.cpp b/dynamic_programming/trapped_rainwater.cpp index 16d4d842cfa..8ac80835180 100644 --- a/dynamic_programming/trapped_rainwater.cpp +++ b/dynamic_programming/trapped_rainwater.cpp @@ -11,8 +11,8 @@ #include /// For std::min and std::max #include /// For assert #include /// For std::size_t -#include /// For std::vector #include /// For integral typedefs +#include /// For std::vector /* * @namespace @@ -89,7 +89,7 @@ static void test() { 0); std::vector test_large_elevation_map_difference = {5, 1, 6, 1, - 7, 1, 8}; + 7, 1, 8}; assert(dynamic_programming::trappedRainwater( test_large_elevation_map_difference) == 15); }