diff --git a/build/task_02/CMakeFiles/task_02.dir/src/main.cpp.o b/build/task_02/CMakeFiles/task_02.dir/src/main.cpp.o new file mode 100644 index 0000000..f3364ed Binary files /dev/null and b/build/task_02/CMakeFiles/task_02.dir/src/main.cpp.o differ diff --git a/build/task_02/CMakeFiles/task_02.dir/src/stack.cpp.o b/build/task_02/CMakeFiles/task_02.dir/src/stack.cpp.o new file mode 100644 index 0000000..dd365f2 Binary files /dev/null and b/build/task_02/CMakeFiles/task_02.dir/src/stack.cpp.o differ diff --git a/build/task_02/CMakeFiles/task_02.dir/src/task_02.cpp.o b/build/task_02/CMakeFiles/task_02.dir/src/task_02.cpp.o new file mode 100644 index 0000000..3f06539 Binary files /dev/null and b/build/task_02/CMakeFiles/task_02.dir/src/task_02.cpp.o differ diff --git a/build/task_02/CMakeFiles/task_02_tests.dir/src/stack.cpp.o b/build/task_02/CMakeFiles/task_02_tests.dir/src/stack.cpp.o new file mode 100644 index 0000000..dd365f2 Binary files /dev/null and b/build/task_02/CMakeFiles/task_02_tests.dir/src/stack.cpp.o differ diff --git a/build/task_02/CMakeFiles/task_02_tests.dir/src/task_02.cpp.o b/build/task_02/CMakeFiles/task_02_tests.dir/src/task_02.cpp.o new file mode 100644 index 0000000..3f06539 Binary files /dev/null and b/build/task_02/CMakeFiles/task_02_tests.dir/src/task_02.cpp.o differ diff --git a/build/task_02/CMakeFiles/task_02_tests.dir/src/test.cpp.o b/build/task_02/CMakeFiles/task_02_tests.dir/src/test.cpp.o new file mode 100644 index 0000000..0ced7b5 Binary files /dev/null and b/build/task_02/CMakeFiles/task_02_tests.dir/src/test.cpp.o differ diff --git a/build/task_02/CTestTestfile.cmake b/build/task_02/CTestTestfile.cmake new file mode 100644 index 0000000..ba67c76 --- /dev/null +++ b/build/task_02/CTestTestfile.cmake @@ -0,0 +1,7 @@ +# CMake generated Testfile for +# Source directory: /workspaces/autumn_homework/task_02 +# Build directory: /workspaces/autumn_homework/build/task_02 +# +# This file includes the relevant testing commands required for +# testing this directory and lists subdirectories to be tested as well. +include("/workspaces/autumn_homework/build/task_02/task_02_tests[1]_include.cmake") diff --git a/build/task_02/cmake_install.cmake b/build/task_02/cmake_install.cmake new file mode 100644 index 0000000..b8f29ae --- /dev/null +++ b/build/task_02/cmake_install.cmake @@ -0,0 +1,44 @@ +# Install script for directory: /workspaces/autumn_homework/task_02 + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Debug") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/usr/bin/llvm-objdump") +endif() + diff --git a/build/task_02/task_02 b/build/task_02/task_02 new file mode 100755 index 0000000..e59b0eb Binary files /dev/null and b/build/task_02/task_02 differ diff --git a/build/task_02/task_02_tests b/build/task_02/task_02_tests new file mode 100755 index 0000000..45f2e9d Binary files /dev/null and b/build/task_02/task_02_tests differ diff --git a/build/task_02/task_02_tests[1]_include.cmake b/build/task_02/task_02_tests[1]_include.cmake new file mode 100644 index 0000000..260e145 --- /dev/null +++ b/build/task_02/task_02_tests[1]_include.cmake @@ -0,0 +1,5 @@ +if(EXISTS "/workspaces/autumn_homework/build/task_02/task_02_tests[1]_tests.cmake") + include("/workspaces/autumn_homework/build/task_02/task_02_tests[1]_tests.cmake") +else() + add_test(task_02_tests_NOT_BUILT task_02_tests_NOT_BUILT) +endif() diff --git a/build/task_02/task_02_tests[1]_tests.cmake b/build/task_02/task_02_tests[1]_tests.cmake new file mode 100644 index 0000000..7af056d --- /dev/null +++ b/build/task_02/task_02_tests[1]_tests.cmake @@ -0,0 +1,5 @@ +add_test([=[SimpleGraph1.Simple]=] /workspaces/autumn_homework/build/task_02/task_02_tests [==[--gtest_filter=SimpleGraph1.Simple]==] --gtest_also_run_disabled_tests) +set_tests_properties([=[SimpleGraph1.Simple]=] PROPERTIES WORKING_DIRECTORY /workspaces/autumn_homework/build/task_02 SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]) +add_test([=[SimpleGraph2.Simple]=] /workspaces/autumn_homework/build/task_02/task_02_tests [==[--gtest_filter=SimpleGraph2.Simple]==] --gtest_also_run_disabled_tests) +set_tests_properties([=[SimpleGraph2.Simple]=] PROPERTIES WORKING_DIRECTORY /workspaces/autumn_homework/build/task_02 SKIP_REGULAR_EXPRESSION [==[\[ SKIPPED \]]==]) +set( task_02_tests_TESTS SimpleGraph1.Simple SimpleGraph2.Simple) diff --git a/lib/src/util.hpp b/lib/src/graph.cpp similarity index 100% rename from lib/src/util.hpp rename to lib/src/graph.cpp diff --git a/lib/src/graph.hpp b/lib/src/graph.hpp new file mode 100644 index 0000000..a65bc40 --- /dev/null +++ b/lib/src/graph.hpp @@ -0,0 +1,151 @@ +#pragma once + +#include +#include +#include +#include + +// UUG - undirected unweighted graph +// UWG - undirected weighted graph +// DUG - directed unweighted graph +// DWG - directed weighted graph + +class UUGraph { + public: + std::vector> graph; // невзвешенный + std::vector used; // массив для обхода + + std::vector cutPoints; // мосты + std::vector> bridges; // точки сочленения + + std::vector h, + d; // вспомогательные массивы для поиска мостов и точек сочленения + + std::vector topSort; // массив для топологической сортировки + std::vector color; // массив для цветов вершин + + void UUGAddEdge(int u, int v) { + if (0 < u && u <= graph.size() && 0 < v && v <= graph.size()) { + graph[u].push_back(v); + graph[v].push_back(u); + } else { + std::cerr << "Uncorrected values"; + } + } + + void UUGReadGraph(int &vertices, int &edges, + std::vector> &vecEdges) { + graph.resize(vertices + 1); + used.resize(vertices + 1, 0); + color.resize(vertices + 1, 0); + d.resize(vertices + 1, 1e9); + h.resize(vertices + 1, 0); + for (int i = 0; i < edges; i++) { + UUGAddEdge(vecEdges[i].first, vecEdges[i].second); + } + } + + void DFSBridgesAndCutPoints(int v, int parent = -1) { + used[v] = true; + d[v] = h[v] = (parent == -1 ? 0 : h[parent] + 1); + int children = 0; + for (int u : graph[v]) { + if (u != parent) { + if (used[u]) { + d[v] = std::min(d[v], h[u]); + } else { + DFSBridgesAndCutPoints(u, v); + d[v] = std::min(d[v], d[u]); + if (h[v] < d[u]) { + std::pair bridge{u, v}; + bridges.push_back(bridge); + } + if (h[v] <= d[u] && parent != -1) { + int cutPoint{v}; + cutPoints.push_back(cutPoint); + } + children++; + } + } + } + if (parent == -1 && children > 1) { + int cutPoint{v}; + cutPoints.push_back(cutPoint); + } + + std::set tmp(cutPoints.begin(), cutPoints.end()); + cutPoints = std::vector(tmp.begin(), tmp.end()); + } +}; + +class UWGraph { + public: + std::vector>> edgeList; // взвешенный + + void UWGAddEdge(int u, int v, double weight) { + if (0 < u && u <= edgeList.size() && 0 < v && v <= edgeList.size()) { + edgeList[u].push_back({v, weight}); + edgeList[v].push_back({u, weight}); + } else { + std::cerr << "Uncorrected values"; + } + } +}; + +class DUGraph { + public: + std::vector> graph; // невзвешенный + std::vector used; // массив для обхода + + std::vector topSort; // массив для топологической сортировки + std::vector color; // массив для цветов вершин + + void DUGAddEdge(int u, int v) { + if (0 < u && u <= graph.size() && 0 < v && v <= graph.size()) { + graph[u].push_back(v); + } else { + std::cerr << "Uncorrected values"; + } + } + + void DUGReadGraph(int &vertices, int &edges, + std::vector> &vecEdges) { + graph.resize(vertices + 1); + used.resize(vertices + 1, 0); + color.resize(vertices + 1, 0); + for (int i = 0; i < edges; i++) { + DUGAddEdge(vecEdges[i].first, vecEdges[i].second); + } + } + + bool DUGDfsCycle(int v) { + used[v] = 1; + color[v] = 1; + for (int edge : graph[v]) { + int to = edge; + if (!used[to]) { + if (DUGDfsCycle(to)) { + return true; + } + } else if (color[to] == 1) { + return true; + } + } + color[v] = 2; + topSort.push_back(v); + return false; + } +}; + +class DWGraph { + std::vector>> edgeListW; // взвешенный + std::vector visited; + + void DWGAddEdge(int u, int v, double weight) { + if (0 < u && u <= edgeListW.size() && 0 < v && v <= edgeListW.size()) { + edgeListW[u].push_back({v, weight}); + } else { + std::cerr << "Uncorrected values"; + } + } +}; \ No newline at end of file diff --git a/lib/src/util.cpp b/lib/src/util.cpp deleted file mode 100644 index 81e15bd..0000000 --- a/lib/src/util.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "util.hpp" diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index 87cef73..0431109 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -1,5 +1,33 @@ #include -TEST(Test, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} \ No newline at end of file +#include "top_sort.hpp" + +TEST(SimpleGraph, Simple) { + int const vertices = 3; + int const edges = 2; + std::vector> edge = {{1, 2}, {2, 3}}; + + std::vector result = TopologySort(vertices, edges, edge); + std::vector expected = {1, 2, 3}; + + ASSERT_EQ(result, expected); +} + +TEST(DisconnectedGraph, Simple) { + int const vertices = 5; + int const edges = 3; + std::vector> edge = {{1, 2}, {3, 4}, {3, 5}}; + + std::vector result = TopologySort(vertices, edges, edge); + std::vector expected = {3, 5, 4, 1, 2}; + + ASSERT_EQ(result, expected); +} + +TEST(GraphWithCycle, Simple) { + int vertices = 3; + int edges = 3; + std::vector> edge = {{1, 3}, {3, 2}, {2, 1}}; + + EXPECT_THROW(TopologySort(vertices, edges, edge);, CycleDetectedException); +} diff --git a/task_01/src/top_sort.cpp b/task_01/src/top_sort.cpp new file mode 100644 index 0000000..af27128 --- /dev/null +++ b/task_01/src/top_sort.cpp @@ -0,0 +1,21 @@ +#include "top_sort.hpp" + +#include + +std::vector TopologySort(int vertices, int edges, + std::vector> &vecEdges) { + DUGraph graph; + graph.DUGReadGraph(vertices, edges, vecEdges); + bool is_cycle = false; + for (int i = 1; i <= vertices; i++) { + if (!graph.used[i]) { + is_cycle = graph.DUGDfsCycle(i); + } + if (is_cycle) { + throw CycleDetectedException( + "Topological sorting is not possible with cycle graph"); + } + } + std::reverse(graph.topSort.begin(), graph.topSort.end()); + return graph.topSort; +} diff --git a/task_01/src/top_sort.hpp b/task_01/src/top_sort.hpp new file mode 100644 index 0000000..8e1af10 --- /dev/null +++ b/task_01/src/top_sort.hpp @@ -0,0 +1,9 @@ +#pragma once +#include + +class CycleDetectedException : public std::logic_error { + using std::logic_error::logic_error; +}; + +std::vector TopologySort(int vertices, int edges, + std::vector> &vecEdges); \ No newline at end of file diff --git a/task_02/src/main.cpp b/task_02/src/main.cpp index 0e4393b..76e8197 100644 --- a/task_02/src/main.cpp +++ b/task_02/src/main.cpp @@ -1,3 +1 @@ -#include - int main() { return 0; } diff --git a/task_02/src/stack.cpp b/task_02/src/stack.cpp deleted file mode 100644 index 8ca8990..0000000 --- a/task_02/src/stack.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "stack.hpp" - -#include - -void Stack::Push(int value) { data_.push(value); } - -int Stack::Pop() { - auto result = data_.top(); - data_.pop(); - return result; -} - -void MinStack::Push(int value) { data_.push_back(value); } - -int MinStack::Pop() { - auto result = data_.back(); - data_.pop_back(); - return result; -} - -int MinStack::GetMin() { return *std::min_element(data_.begin(), data_.end()); } \ No newline at end of file diff --git a/task_02/src/stack.hpp b/task_02/src/stack.hpp deleted file mode 100644 index 138ec40..0000000 --- a/task_02/src/stack.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include - -class Stack { - public: - void Push(int value); - int Pop(); - - private: - std::stack data_; -}; - -class MinStack { - public: - void Push(int value); - int Pop(); - int GetMin(); - - private: - std::vector data_; -}; diff --git a/task_02/src/task_02.cpp b/task_02/src/task_02.cpp new file mode 100644 index 0000000..8aebb90 --- /dev/null +++ b/task_02/src/task_02.cpp @@ -0,0 +1,21 @@ +#include "task_02.hpp" + +#include + +std::pair>, std::vector> +BridgesAndCutPoints(int vertices, int edges, + std::vector> &vecEdges) { + UUGraph graph; + graph.UUGReadGraph(vertices, edges, vecEdges); + + for (int i = 1; i <= vertices; i++) { + if (!graph.used[i]) { + graph.DFSBridgesAndCutPoints(i); + } + } + + std::pair>, std::vector> ans; + ans.first = graph.bridges; + ans.second = graph.cutPoints; + return ans; +} diff --git a/task_02/src/task_02.hpp b/task_02/src/task_02.hpp new file mode 100644 index 0000000..4a3598d --- /dev/null +++ b/task_02/src/task_02.hpp @@ -0,0 +1,6 @@ +#pragma once +#include + +std::pair>, std::vector> +BridgesAndCutPoints(int vertices, int edges, + std::vector> &vecEdges); \ No newline at end of file diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 54e7ce9..90839f0 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -1,42 +1,44 @@ - #include -#include - -#include "stack.hpp" - -TEST(StackTest, Simple) { - Stack stack; - stack.Push(1); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - stack.Push(3); // Stack [1, 3] - ASSERT_EQ(stack.Pop(), 3); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] +#include "task_02.hpp" + +TEST(SimpleGraph1, Simple) { + int const vertices = 6; + int const edges = 6; + std::vector> edge = {{1, 2}, {2, 3}, {3, 4}, + {3, 5}, {1, 5}, {2, 6}}; + + std::pair>, std::vector> result = + BridgesAndCutPoints(vertices, edges, edge); + std::pair>, std::vector> expected = { + {{4, 3}, {6, 2}}, {2, 3}}; + + ASSERT_EQ(result, expected); +} + +TEST(SimpleGraph2, Simple) { + int const vertices = 3; + int const edges = 2; + std::vector> edge = {{3, 2}, {2, 1}}; + + std::pair>, std::vector> result = + BridgesAndCutPoints(vertices, edges, edge); + std::pair>, std::vector> expected = { + {{3, 2}, {2, 1}}, {2}}; + + ASSERT_EQ(result, expected); } -TEST(MinStackTest, Simple) { - MinStack stack; - stack.Push(1); // Stack [1] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - stack.Push(3); // Stack [1, 3] - ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 3); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] +TEST(SimpleGraph3, Simple) { + int const vertices = 8; + int const edges = 8; + std::vector> edge = {{1, 2}, {3, 4}, {3, 2}, {3, 1}, + {2, 5}, {2, 6}, {3, 7}, {7, 8}}; + + std::pair>, std::vector> result = + BridgesAndCutPoints(vertices, edges, edge); + std::pair>, std::vector> expected = { + {{4, 3}, {8, 7}, {7, 3}, {5, 2}, {6, 2}}, {2, 3, 7}}; + + ASSERT_EQ(result, expected); } \ No newline at end of file