diff --git a/CMakeLists.txt b/CMakeLists.txt index fb5abf3a..f20a8d11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ include(cmake/function.cmake) # подхватываем функции, # и для создания исполняемого проекта в отдельные функции add_subdirectory(lib_easy_example) # подключаем дополнительный CMakeLists.txt из подкаталога с именем lib_easy_example - +add_subdirectory(lib_DSU) add_subdirectory(main) # подключаем дополнительный CMakeLists.txt из подкаталога с именем main option(BTEST "build test?" ON) # указываем подключаем ли google-тесты (ON или YES) или нет (OFF или NO) diff --git a/lib_DSU/CMakeLists.txt b/lib_DSU/CMakeLists.txt new file mode 100644 index 00000000..424d2417 --- /dev/null +++ b/lib_DSU/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(DSU) \ No newline at end of file diff --git a/lib_DSU/DSU.cpp b/lib_DSU/DSU.cpp new file mode 100644 index 00000000..e69de29b diff --git a/lib_DSU/DSU.h b/lib_DSU/DSU.h new file mode 100644 index 00000000..c0c908de --- /dev/null +++ b/lib_DSU/DSU.h @@ -0,0 +1,47 @@ +class DSU { + int* _parent; + int* _rank; + size_t _size; + +public: + + DSU(size_t size) : _size(size) { + _parent = new int[size]; + _rank = new int[size]; + for (int i = 0; i < size; i++) { + _parent[i] = i; + _rank[i] = 0; + } + } + + ~DSU() { + delete[] _parent; + delete[] _rank; + } + + int find(int x) { + if (x < 0 || x >= _size) return -1; + if (_parent[x] != x) { + _parent[x] = find(_parent[x]); + } + return _parent[x]; + } + + void unite(int x, int y) { + int rootX = find(x); + int rootY = find(y); + + if (rootX == rootY || rootX == -1 || rootY == -1) return; + + if (_rank[rootX] < _rank[rootY]) { + _parent[rootX] = rootY; + } + else if (_rank[rootX] > _rank[rootY]) { + _parent[rootY] = rootX; + } + else { + _parent[rootY] = rootX; + _rank[rootX]++; + } + } +}; \ No newline at end of file diff --git a/main/main.cpp b/main/main.cpp index 217f8971..5cb733a1 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,37 +1,74 @@ // Copyright 2024 Marina Usova -#define EASY_EXAMPLE -#ifdef EASY_EXAMPLE + #include -#include -#include "../lib_easy_example/easy_example.h" +#include "DSU.h" +#include -int main() { - int a, b; - float result; - - a = 1; b = 4; - - try { - result = division(a, b); - std::cout << a << " / " << b << " = " - << std::setprecision(2) << result << std::endl; - } catch (std::exception err) { - std::cerr << err.what() << std::endl; - } - - a = 1; b = 0; - - try { - result = division(a, b); - std::cout << a << " / " << b << " = " - << std::setprecision(2) << result << std::endl; - } catch (std::exception err) { - std::cerr << err.what() << std::endl; - } - - return 0; +int countIslands(std::vector>& grid) { + if (grid.empty() || grid[0].empty()) return 0; + + int rows = grid.size(); + int cols = grid[0].size(); + + DSU dsu(rows * cols); + + int directions[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; + + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (grid[i][j] == 1) { + int currentIndex = i * cols + j; + + for (int k = 0; k < 4; k++) { + int newRow = i + directions[k][0]; + int newCol = j + directions[k][1]; + + if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && grid[newRow][newCol] == 1) { + int neighborIndex = newRow * cols + newCol; + dsu.unite(currentIndex, neighborIndex); + } + } + } + } + } + + int totalCells = rows * cols; + bool* seen = new bool[totalCells]; + for (int i = 0; i < totalCells; i++) { + seen[i] = false; + } + + int count = 0; + for (int i = 0; i < rows; i++) { + for (int j = 0; j < cols; j++) { + if (grid[i][j] == 1) { + int index = i * cols + j; + int root = dsu.find(index); + if (root != -1 && !seen[root]) { + seen[root] = true; + count++; + } + } + } + } + + delete[] seen; + return count; } -#endif // EASY_EXAMPLE +int main() { + std::vector> grid = { + {0, 1, 0, 0, 1}, + {0, 1, 1, 0, 1}, + {1, 1, 0, 1, 1}, + {0, 0, 0, 0, 1}, + {1, 0, 1, 1, 1} + }; + + int islandsCount = countIslands(grid); + std::cout << "Number of islands: " << islandsCount << std::endl; + + return 0; +} diff --git a/tests/test_DSU.cpp b/tests/test_DSU.cpp new file mode 100644 index 00000000..b1cf3086 --- /dev/null +++ b/tests/test_DSU.cpp @@ -0,0 +1,56 @@ +#include +#include "DSU.h" + + + + +TEST(DSUTest, BasicUnion) { + DSU dsu(10); + dsu.unite(0, 1); + EXPECT_EQ(dsu.find(0), dsu.find(1)); + + dsu.unite(2, 3); + EXPECT_EQ(dsu.find(2), dsu.find(3)); + + EXPECT_NE(dsu.find(0), dsu.find(2)); + EXPECT_NE(dsu.find(1), dsu.find(3)); +} + +TEST(DSUTest, TransitiveUnion) { + DSU dsu(10); + dsu.unite(0, 1); + dsu.unite(1, 2); + + EXPECT_EQ(dsu.find(0), dsu.find(1)); + EXPECT_EQ(dsu.find(1), dsu.find(2)); + EXPECT_EQ(dsu.find(0), dsu.find(2)); +} + +TEST(DSUTest, MultipleUnions) { + DSU dsu(10); + dsu.unite(0, 1); + dsu.unite(2, 3); + dsu.unite(0, 2); + + EXPECT_EQ(dsu.find(0), dsu.find(1)); + EXPECT_EQ(dsu.find(0), dsu.find(2)); + EXPECT_EQ(dsu.find(0), dsu.find(3)); +} + +TEST(DSUTest, SelfUnion) { + DSU dsu(10); + int original_root = dsu.find(5); + dsu.unite(5, 5); + EXPECT_EQ(dsu.find(5), original_root); +} + + +TEST(DSUTest, RankTest) { + DSU small_dsu(3); + + small_dsu.unite(0, 1); + small_dsu.unite(0, 2); + + EXPECT_EQ(small_dsu.find(0), small_dsu.find(1)); + EXPECT_EQ(small_dsu.find(0), small_dsu.find(2)); +} \ No newline at end of file diff --git a/tests/test_easy_example.cpp b/tests/test_easy_example.cpp index 3a67b612..01aab1a8 100644 --- a/tests/test_easy_example.cpp +++ b/tests/test_easy_example.cpp @@ -2,49 +2,11 @@ #include #include "../lib_easy_example/easy_example.h" - #define EPSILON 0.000001 -TEST(TestEasyExampleLib, can_div) { - // Arrange - int x = 10; - int y = 2; - - // Act & Assert - ASSERT_NO_THROW(division(x, y)); -} - -TEST(TestEasyExampleLib, can_div_correctly) { - // Arrange - int x = 6; - int y = 2; - - // Act - int actual_result = division(x, y); - - // Assert - int expected_result = 3; - EXPECT_EQ(expected_result, actual_result); -} - -TEST(TestEasyExampleLib, can_div_correctly_with_remainder) { - // Arrange - int x = 5; - int y = 4; - - // Act - float actual_result = division(x, y); - - // Assert - float expected_result = 1.25; - EXPECT_NEAR(expected_result, actual_result, EPSILON); -} - -TEST(TestEasyExampleLib, throw_when_try_div_by_zero) { - // Arrange - int x = 10; - int y = 0; - - // Act & Assert - ASSERT_ANY_THROW(division(x, y)); -} + + + + + +