/** * @file * @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. * @author [SOZEL](https://github.com/TruongNhanNguyen) */ #include /// For std::min and std::max #include /// For assert #include /// For std::size_t #include #include /// For std::vector /* * @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 */ 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); // Calculate the maximum height of wall to the left of each wall leftMax[0] = heights[0]; 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 (std::size_t i = n - 2; i < n; --i) { rightMax[i] = std::max(rightMax[i + 1], heights[i]); } // Calculate the trapped rainwater between walls 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]); } return trappedWater; } } // namespace dynamic_programming /** * @brief Self-test implementations * @returns void */ static void test() { 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}; assert(dynamic_programming::trappedRainwater(test_peak_under_water) == 7); std::vector test_bucket = {5, 1, 5}; assert(dynamic_programming::trappedRainwater(test_bucket) == 4); 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); } /** * @brief Main function * @returns 0 on exit */ int main() { test(); // run self-test implementations return 0; }