diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index fb8ecde19..e3707e290 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -59,3 +59,4 @@ This file lists everyone, who contributed to this repo and wanted to show up her - Mahdi Sarikhani - Ridham177 - Hugo Salou +- Dimitri Belopopsky diff --git a/contents/flood_fill/code/cpp/flood_fill.cpp b/contents/flood_fill/code/cpp/flood_fill.cpp new file mode 100644 index 000000000..918566809 --- /dev/null +++ b/contents/flood_fill/code/cpp/flood_fill.cpp @@ -0,0 +1,156 @@ +#include +#include +#include +#include +#include +#include + +using CartesianIndex = std::array; + +auto inbounds(CartesianIndex size, CartesianIndex loc) { + if (loc[0] < 0 || loc[1] < 0) { + return false; + } else if (loc[0] >= size[0] || loc[1] >= size[1]) { + return false; + } + return true; +} + +auto find_neighbors( + std::vector> const& grid, + CartesianIndex loc, + float old_value, + float /* new_value */) { + + const std::vector possible_neighbors{ + {loc[0], loc[1] + 1}, + {loc[0] + 1, loc[1]}, + {loc[0], loc[1] - 1}, + {loc[0] - 1, loc[1]}}; + + std::vector neighbors; + + for (auto const& possible_neighbor : possible_neighbors) { + const auto size = CartesianIndex{ + static_cast(grid[0].size()), static_cast(grid.size())}; + const auto x = static_cast(possible_neighbor[0]); + const auto y = static_cast(possible_neighbor[1]); + if (inbounds(size, possible_neighbor) && grid[x][y] == old_value) { + neighbors.push_back(possible_neighbor); + } + } + + return neighbors; +} + +void recursive_fill( + std::vector>& grid, + CartesianIndex loc, + float old_value, + float new_value) { + if (old_value == new_value) { + return; + } + + const auto x = static_cast(loc[0]); + const auto y = static_cast(loc[1]); + + grid[x][y] = new_value; + + const auto possible_neighbors = find_neighbors(grid, loc, old_value, new_value); + for (auto const& possible_neighbor : possible_neighbors) { + recursive_fill(grid, possible_neighbor, old_value, new_value); + } +} + +void queue_fill( + std::vector>& grid, + CartesianIndex loc, + float old_value, + float new_value) { + if (old_value == new_value) { + return; + } + + auto q = std::queue{}; + q.push(loc); + const auto x = static_cast(loc[0]); + const auto y = static_cast(loc[1]); + grid[x][y] = new_value; + + while (q.size() > 0) { + const auto current_loc = q.front(); + q.pop(); + const auto possible_neighbors = + find_neighbors(grid, current_loc, old_value, new_value); + for (auto const& neighbor : possible_neighbors) { + const auto neighbor_x = static_cast(neighbor[0]); + const auto neighbor_y = static_cast(neighbor[1]); + grid[neighbor_x][neighbor_y] = new_value; + q.push(neighbor); + } + } +} + +void stack_fill( + std::vector>& grid, + CartesianIndex loc, + float old_value, + float new_value) { + if (old_value == new_value) { + return; + } + + auto s = std::stack{}; + s.push(loc); + + while (s.size() > 0) { + const auto current_loc = s.top(); + s.pop(); + + const auto x = static_cast(current_loc[0]); + const auto y = static_cast(current_loc[1]); + + if (grid[x][y] == old_value) { + grid[x][y] = new_value; + const auto possible_neighbors = + find_neighbors(grid, current_loc, old_value, new_value); + for (auto const& neighbor : possible_neighbors) { + s.push(neighbor); + } + } + } +} + +int main() { + + const std::vector> grid{ + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}, + {0, 0, 1, 0, 0}}; + + const std::vector> solution_grid{ + {1, 1, 1, 0, 0}, + {1, 1, 1, 0, 0}, + {1, 1, 1, 0, 0}, + {1, 1, 1, 0, 0}, + {1, 1, 1, 0, 0}}; + + const CartesianIndex start_loc{1, 1}; + + auto test_grid = grid; + recursive_fill(test_grid, start_loc, 0.0, 1.0); + assert(test_grid == solution_grid); + + test_grid = grid; + queue_fill(test_grid, start_loc, 0.0, 1.0); + assert(test_grid == solution_grid); + + test_grid = grid; + stack_fill(test_grid, start_loc, 0.0, 1.0); + assert(test_grid == solution_grid); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/contents/flood_fill/flood_fill.md b/contents/flood_fill/flood_fill.md index 185050fe1..4c7e5936e 100644 --- a/contents/flood_fill/flood_fill.md +++ b/contents/flood_fill/flood_fill.md @@ -90,6 +90,8 @@ In code, this might look like this: [import:23-41, lang:"julia"](code/julia/flood_fill.jl) {% sample lang="c" %} [import:28-46, lang:"c"](code/c/flood_fill.c) +{% sample lang="cpp" %} +[import:19-44, lang:"cpp"](code/cpp/flood_fill.cpp) {% sample lang="py" %} [import:10-25, lang="python"](code/python/flood_fill.py) {% sample lang="coco" %} @@ -110,6 +112,8 @@ In code, it might look like this: [import:92-104, lang:"julia"](code/julia/flood_fill.jl) {% sample lang="c" %} [import:174-189, lang:"c"](code/c/flood_fill.c) +{% sample lang="cpp" %} +[import:46-64, lang:"cpp"](code/cpp/flood_fill.cpp) {% sample lang="py" %} [import:55-63, lang="python"](code/python/flood_fill.py) {% sample lang="coco" %} @@ -125,6 +129,8 @@ Additionally, it is possible to do the same type of traversal by managing a stac [import:43-63, lang:"julia"](code/julia/flood_fill.jl) {% sample lang="c" %} [import:79-102, lang:"c"](code/c/flood_fill.c) +{% sample lang="cpp" %} +[import:95-123, lang:"cpp"](code/cpp/flood_fill.cpp) {% sample lang="py" %} [import:27-36, lang="python"](code/python/flood_fill.py) {% sample lang="coco" %} @@ -168,6 +174,8 @@ The code would look something like this: [import:66-90, lang:"julia"](code/julia/flood_fill.jl) {% sample lang="c" %} [import:149-172, lang:"c"](code/c/flood_fill.c) +{% sample lang="cpp" %} +[import:66-93, lang:"cpp"](code/cpp/flood_fill.cpp) {% sample lang="py" %} [import:38-53, lang="python"](code/python/flood_fill.py) {% sample lang="coco" %} @@ -250,6 +258,8 @@ After, we will fill in the left-hand side of the array to be all ones by choosin [import, lang:"julia"](code/julia/flood_fill.jl) {% sample lang="c" %} [import, lang:"c"](code/c/flood_fill.c) +{% sample lang="cpp" %} +[import, lang:"cpp"](code/cpp/flood_fill.cpp) {% sample lang="py" %} [import:, lang="python"](code/python/flood_fill.py) {% sample lang="coco" %}