diff --git a/task_01/CMakeLists.txt b/task_01/CMakeLists.txt index 6612735..916bce7 100644 --- a/task_01/CMakeLists.txt +++ b/task_01/CMakeLists.txt @@ -33,7 +33,6 @@ add_executable(${PROJECT_NAME}_tests ${test_source_list}) target_link_libraries( ${PROJECT_NAME}_tests GTest::gtest_main - Utils ) include(GoogleTest) diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index 76e8197..81af8a1 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -1 +1,55 @@ -int main() { return 0; } +#include +#include +#include + +#include "solution.h" + +int main() { + std::vector nodes; + std::vector ans; + + int N = 5; + nodes.resize(N); + // список ребер + /*nodes[1 2);*/ + nodes[0].neighbours.push_back(1); + nodes[0].neighbours.push_back(4); + nodes[1].neighbours.push_back(2); + nodes[3].neighbours.push_back(0); + nodes[3].neighbours.push_back(4); + nodes[4].neighbours.push_back(1); + nodes[4].neighbours.push_back(2); + for (int i = 0; i < N; i++) { + nodes[i].id = i; + } + + for (int i = 0; i < ans.size(); i++) { + std::cout << ans[i] << "\n"; + } + + bool flag = true; + ans = solution(nodes); + + /*std::vector nodes;*/ + /*std::vector ans;*/ + /**/ + /*int n, k, tmp, N;*/ + /*std::cin >> N >> tmp; // колич*/ + /*nodes.resize(N);*/ + /*// список ребер*/ + /*while ((tmp--)>0) {*/ + /* std::cin >> n >> k;*/ + /* nodes[n].neighbours.push_back(k);*/ + /*}*/ + /*for(int i =0; i= 0; i--) { + std::cout << ans[i] << " "; + } + + return 0; +} diff --git a/task_01/src/solution.cpp b/task_01/src/solution.cpp new file mode 100644 index 0000000..beb3969 --- /dev/null +++ b/task_01/src/solution.cpp @@ -0,0 +1,47 @@ +#include "solution.h" + +std::vector solution(std::vector nodes) { + std::deque gray; + std::vector ans; + int N = nodes.size(), tmp = 0; + for (int i = 0; i < N; i++) { + nodes[i].id = i; + std::sort(nodes[i].neighbours.begin(), nodes[i].neighbours.end()); + } + + /*gray.push_back(0);*/ + node *current; + + tmp = 0; + int i = 0; + while (true) { + if (i >= N) { + break; + } + if (nodes[i].flag == false) { + i++; + continue; + } + gray.push_back(i); + current = &nodes[i]; + + while (gray.size()) { + current = &nodes[gray.back()]; + if (!current->flag) { + gray.pop_back(); + continue; + } + if (current->neighbours.size() <= current->last) { + ans.push_back(current->id); + current->flag = false; + gray.pop_back(); + continue; + } + tmp = current->neighbours[current->last]; + gray.push_back(tmp); + current->last++; + } + i++; + } + return ans; +} diff --git a/task_01/src/solution.h b/task_01/src/solution.h new file mode 100644 index 0000000..0db6886 --- /dev/null +++ b/task_01/src/solution.h @@ -0,0 +1,14 @@ + +#include +#include +#include + +class node { + public: + std::vector neighbours; + int last = 0; + int id; + bool flag = true; // белая +}; + +std::vector solution(std::vector nodes); diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index 87cef73..9f18306 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -1,5 +1,91 @@ #include +#include + +#include "solution.h" + TEST(Test, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} \ No newline at end of file + std::vector nodes; + std::vector ans; + + int N = 3; + nodes.resize(N); + // список ребер + nodes[1].neighbours.push_back(2); + nodes[0].neighbours.push_back(2); + nodes[0].neighbours.push_back(1); + for (int i = 0; i < N; i++) { + nodes[i].id = i; + } + + bool flag = true; + ans = solution(nodes); + std::vector assertion = {0, 1, 2}; + ASSERT_TRUE(assertion.size() == ans.size()); + for (int i = 0; i < ans.size(); i++) { + flag = flag && (ans[N - i - 1] == assertion[i]); + } + ASSERT_TRUE(flag) << ans[0] << " УЭЭЭЭЭЭ"; +} + +TEST(Test, Simple2) { + std::vector nodes; + std::vector ans; + + int N = 5; + nodes.resize(N); + // список ребер + /*nodes[1 2);*/ + nodes[0].neighbours.push_back(1); + nodes[0].neighbours.push_back(4); + nodes[1].neighbours.push_back(2); + nodes[3].neighbours.push_back(0); + nodes[3].neighbours.push_back(4); + nodes[4].neighbours.push_back(1); + nodes[4].neighbours.push_back(2); + for (int i = 0; i < N; i++) { + nodes[i].id = i; + } + + for (int i = 0; i < ans.size(); i++) { + std::cout << ans[i] << "\n"; + } + + bool flag = true; + ans = solution(nodes); + std::vector assertion = {3, 0, 4, 1, 2}; + ASSERT_TRUE(assertion.size() == ans.size()); + for (int i = 0; i < ans.size(); i++) { + flag = flag && (ans[N - i - 1] == assertion[i]); + } + ASSERT_TRUE(flag) << ans[0] << " УЭЭЭЭЭЭ"; +} + +TEST(Test, Simpl3) { + std::vector nodes; + std::vector ans; + + int N = 6; + nodes.resize(N); + // список ребер + // 0 -> 1 + // V Δ + // 3 -> 4 + // 5 -> 2 + nodes[0].neighbours.push_back(1); + nodes[5].neighbours.push_back(2); + nodes[3].neighbours.push_back(4); + nodes[0].neighbours.push_back(3); + nodes[4].neighbours.push_back(1); + for (int i = 0; i < N; i++) { + nodes[i].id = i; + } + bool flag = true; + ans = solution(nodes); + std::vector assertion = {5, 2, 0, 3, 4, 1}; + ASSERT_TRUE(assertion.size() == ans.size()); + for (int i = 0; i < ans.size(); i++) { + flag = flag && (ans[N - i - 1] == assertion[i]); + } + ASSERT_TRUE(flag) << ans[2] << " УЭЭЭЭЭЭ"; +} diff --git a/task_02/src/.clangd b/task_02/src/.clangd new file mode 100644 index 0000000..568658e --- /dev/null +++ b/task_02/src/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + Add: [-std=c++23] diff --git a/task_02/src/a.out b/task_02/src/a.out new file mode 100755 index 0000000..eedb860 Binary files /dev/null and b/task_02/src/a.out differ diff --git a/task_02/src/main.cpp b/task_02/src/main.cpp index 0e4393b..af67365 100644 --- a/task_02/src/main.cpp +++ b/task_02/src/main.cpp @@ -1,3 +1,63 @@ +#include #include +#include -int main() { return 0; } +#include "solution.h" + +/* + ______________________ +/ . \ +| ├── main.cpp | +| ├── solution.cpp | +| ├── solution.h | +| ├── stack.cpp | +| ├── stack.hpp | +| └── test.cpp | +| | +\ 1 directory, 6 files / + ---------------------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || +*/ +int main() { + std::vector nodes; + + int n, k = 0, tmp, N; + N = 4; + tmp = 4; // колич + nodes.resize(N); + // список ребер + std::vector> loh = {{0, 1}, {1, 2}, {2, 3}, {0, 2}}; + while (k < tmp) { + nodes[loh[k].first].neighbours.push_back(loh[k].second); + nodes[loh[k].second].neighbours.push_back(loh[k].first); + k++; + } + /*std::vector nodes;*/ + /**/ + /*int n, k, tmp, N;*/ + /*std::cin >> N >> tmp; // колич*/ + /*nodes.resize(N);*/ + /*// список ребер*/ + /*while ((tmp--)>0) {*/ + /* std::cin >> n >> k;*/ + /* nodes[n].neighbours.push_back(k);*/ + /* nodes[k].neighbours.push_back(n);*/ + /*}*/ + + auto ans = solution(nodes); + + std::cout << "\n\n" << ans.first.size() << "\n"; + for (int i = 0; i < ans.first.size(); i++) { + std::cout << ans.first[i].first << " " << ans.first[i].second << "\n"; + } + std::cout << "~~~~~~~~~~~~~~\n"; + for (int i = 0; i < ans.second.size(); i++) { + std::cout << ans.second[i] << " "; + } + + return 0; +} diff --git a/task_02/src/solution.cpp b/task_02/src/solution.cpp new file mode 100644 index 0000000..7cc43dd --- /dev/null +++ b/task_02/src/solution.cpp @@ -0,0 +1,69 @@ +#include "solution.h" + +#include +#include + +static std::vector h, d; +static std::vector used; +static std::vector lockers; +static std::vector> bridges; + +void dfs_lockers(std::vector &nodes, int v = 0, int p = -1) { + used[v] = 1; + d[v] = h[v] = (p == -1 ? 0 : h[p] + 1); + int children = 0; + for (auto u : nodes[v].neighbours) { + if (u != p) { + if (used[u]) + d[v] = std::min(d[v], h[u]); + else { + dfs_lockers(nodes, u, v); + d[v] = std::min(d[v], d[u]); + if (h[v] <= d[u]) { // корень (p == -1) обрабатываем отдельно + if (h[v] != d[u]) bridges.push_back(std::pair(v, u)); + if (p != -1) lockers.push_back(v); + } + children++; + } + } + } + if (p == -1 && children > 1) { + lockers.push_back(v); + } +} +void dfs_bridges(std::vector &nodes, int v = 0, int p = -1) { + used[v] = true; + d[v] = h[v] = (p == -1 ? 0 : h[p] + 1); + for (auto u : nodes[v].neighbours) { + if (u != p) { + if (used[u]) // если ребро обратное + d[v] = std::min(d[v], h[u]); + else { // если ребро прямое + dfs_bridges(nodes, u, v); + d[v] = std::min(d[v], d[u]); + if (h[v] < d[u]) { + bridges.push_back(std::pair(v, u)); + } + } + } + } +} + +std::pair>, std::vector> solution( + std::vector nodes) { + used.resize(nodes.size()); + h.resize(nodes.size()); + d.resize(nodes.size()); + lockers.clear(); + bridges.clear(); + for (int i = 0; i < nodes.size(); i++) { + used[i] = 0; + h[i] = d[i] = 0; + } + + std::vector nc = nodes; + dfs_lockers(nodes); + + return std::pair>, std::vector>(bridges, + lockers); +} diff --git a/task_02/src/solution.cpp.old b/task_02/src/solution.cpp.old new file mode 100644 index 0000000..85184a5 --- /dev/null +++ b/task_02/src/solution.cpp.old @@ -0,0 +1,76 @@ +#include "solution.h" +#include +#include +#include + + + +std::vector solution(std::vector &nodes){ + std::deque gray; + std::unordered_set visited; + std::vector lockers; + int N = nodes.size(),tmp; + std::cout<<"~~~~~~~~~~~~~~~~~~~~\n"; + + for(int i =0; ilast != current->neighbours.end()&&(*(current->last))->locked){current->last++;} + if(current->locked && current->last == current->neighbours.end()){ + /*current->locked = true;*/ + lockers.back()=current->id; + gray.pop_back(); + continue; + } + while(gray.size()){ + current = gray.back(); + std::cout<id<<" start\n"; + if(!visited.contains(current->id)){ + visited.insert(current->id); + std::cout<id<<" visited\n"; + } + std::cout<id<<" passed 1"<last == current->neighbours.end()){ + std::cout<id<<" was locked. break"<locked = true; + gray.pop_back(); + lockers.push_back(current->id); + break; + } + std::cout<id<<" passed 2"<last))->id)){ + std::cout<id<<" neighbot visited. continue"<id == 0){current->last++;continue;} + (*(current->last))->locked = gray[gray.size()-2]; + current->last++; + continue; + } + std::cout<id<<" passed 3"<last)); + } + if(gray.size()==1){ + break; + } + start.locked = true; + } + /*1*/ + + tmp=0; + return lockers; + +} + + diff --git a/task_02/src/solution.h b/task_02/src/solution.h new file mode 100644 index 0000000..a1211ba --- /dev/null +++ b/task_02/src/solution.h @@ -0,0 +1,21 @@ +#ifndef __SOLUTION_H__ +#define __SOLUTION_H__ + +#include +#include +#include +#include +#include + +class node { + public: + std::vector neighbours; + int id; + bool locked = false; // + bool flag = false; // белая +}; + +std::pair>, std::vector> solution( + std::vector nodes); + +#endif // __SOLUTION_H__ diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 54e7ce9..7f78732 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -1,42 +1,73 @@ #include -#include +#include -#include "stack.hpp" +#include "solution.h" 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 [] + std::vector nodes; + + int n, k = 0, tmp, N; + N = 4; + tmp = 4; // колич + nodes.resize(N); + // список ребер + std::vector> loh = {{0, 1}, {1, 2}, {2, 3}, {0, 2}}; + while (k < tmp) { + nodes[loh[k].first].neighbours.push_back(loh[k].second); + nodes[loh[k].second].neighbours.push_back(loh[k].first); + k++; + } + + auto ans = solution(nodes); + + bool flag = true; + ans = solution(nodes); + std::vector> assertionb = {{2, 3}}; + ASSERT_TRUE(assertionb.size() == ans.first.size()); + for (int i = 0; i < ans.first.size(); i++) { + flag = flag && (ans.first[i].first == assertionb[i].first) && + (ans.first[i].second == assertionb[i].second); + } + std::vector assertionn = {2}; + ASSERT_TRUE(assertionn.size() == ans.second.size()); + for (int i = 0; i < ans.first.size(); i++) { + flag = flag && (ans.second[i] == assertionn[i]); + } + ASSERT_TRUE(flag); } -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 [] -} \ No newline at end of file +TEST(MinStackTest, SimpleNoBriges) { + std::vector nodes; + + int n, k = 0, tmp, N; + N = 4; + nodes.resize(N); + // список ребер + std::vector> loh = { + {0, 1}, {1, 2}, {2, 3}, {0, 2}, {0, 3}}; + tmp = loh.size(); // колич + while (k < tmp) { + nodes[loh[k].first].neighbours.push_back(loh[k].second); + nodes[loh[k].second].neighbours.push_back(loh[k].first); + k++; + } + + auto ans = solution(nodes); + + bool flag = true; + ans = solution(nodes); + std::vector> assertionb = {}; + ASSERT_TRUE(assertionb.size() == ans.first.size()); + for (int i = 0; i < ans.first.size(); i++) { + flag = flag && (ans.first[i].first == assertionb[i].first) && + (ans.first[i].second == assertionb[i].second); + } + std::vector assertionn = {}; + ASSERT_TRUE(assertionn.size() == ans.second.size()); + for (int i = 0; i < ans.first.size(); i++) { + flag = flag && (ans.second[i] == assertionn[i]); + } + ASSERT_TRUE(flag); +} diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 0e4393b..e9457d4 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -1,3 +1,38 @@ #include -int main() { return 0; } +#include "solution.h" + +int main() { + std::vector> expected = {{0, -1, 2, -2, 1}, + {999, 0, 3, -1, 2}, + {1000, 998, 0, 997, 1000}, + {1000, 1, 4, 0, 3}, + {997, -2, 1, -3, 0}}; + std::vector nodes; + std::vector edges = {0, -1, 4, 1000, 1000, 1000, 0, 3, 2, + 2, 1000, 1000, 0, 1000, 1000, 1000, 1, 5, + 1000, 1000, 1000, 1000, 1000, -3, 1000}; + int n = 5, tmp; + nodes.resize(n); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + continue; + } + nodes[i].neighbours.push_back({j, edges[i * n + j]}); + } + } + auto ans = jonson(nodes); + for (int i = 0; i < ans.size(); i++) { + for (int j = 0; j < ans.size(); j++) { + if (i == j) { + continue; + } + if (ans[i][j] != expected[i][j]) + std::cout << " " << i << " " << j << " " << ans[i][j] << " " + << expected[i][j] << "\n"; + } + } + + return 0; +} diff --git a/task_03/src/solution.cpp b/task_03/src/solution.cpp new file mode 100644 index 0000000..de593fa --- /dev/null +++ b/task_03/src/solution.cpp @@ -0,0 +1,84 @@ +#include "solution.h" + +#include +#include +#include +#include + +void deixtra(std::vector &nodes, int start) { + std::priority_queue> qqe; // {len, id} + node *current; + int tmp; + for (auto &i : nodes) { + i.len = std::numeric_limits::max(); + } + nodes[start].len = 0; + + qqe.push({0, start}); + + while (!qqe.empty()) { + current = &nodes[qqe.top().second]; + int dst = qqe.top().first; + qqe.pop(); + if (current->len < dst) { + continue; + } + for (auto &i : current->neighbours) { + int n_dst = dst + i.second; + if (n_dst < nodes[i.first].len) { + nodes[i.first].len = n_dst; + qqe.push({n_dst, i.first}); + } + } + } +} + +bool bellford(std::vector &nodes /*, int start*/) { + int tmp = 0; + /*node s;*/ + bool flag = false; + for (auto &i : nodes) { + /*s.neighbours.push_back({i.id, 0});*/ + i.pot = 0; + } + while (nodes.size() >= (tmp++)) { + for (auto &i : nodes) { + for (auto &j : i.neighbours) { + int n_dst = i.pot + j.second; + if (n_dst < nodes[j.first].pot) { + /*std::cout<> jonson(std::vector nodes) { + std::vector> ret( + nodes.size(), + std::vector(nodes.size(), std::numeric_limits::min())); + if (!bellford(nodes)) { + /*std::cout<<"wrong!";*/ + return ret; + } + for (auto &i : nodes) { + for (auto &j : i.neighbours) { + j.second = j.second + nodes[j.first].pot - i.pot; + } + } + for (int i = 0; i < nodes.size(); i++) { + deixtra(nodes, i); + for (int j = 0; j < nodes.size(); j++) { + ret[i][j] = nodes[j].len - nodes[j].pot + nodes[i].pot; + } + } + return ret; +} diff --git a/task_03/src/solution.h b/task_03/src/solution.h new file mode 100644 index 0000000..092f61f --- /dev/null +++ b/task_03/src/solution.h @@ -0,0 +1,22 @@ +#ifndef __SOLUTION_H__ +#define __SOLUTION_H__ +#include +#include + +class node { + public: + std::vector> neighbours; // {id, size} + int id; + int len = 0; + int pot = 0; + bool locked = false; // + bool wisited = false; +}; + +void deixtra(std::vector &nodes, int start); + +bool bellford(std::vector &nodes /*, int start*/); + +std::vector> jonson(std::vector nodes); + +#endif // !__DEIXTRA_H__ diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86a..5fc5dc8 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,8 +1,73 @@ - #include -#include "topology_sort.hpp" +#include + +#include "solution.h" + +TEST(Deixtra, Simple) { + std::vector nodes; + std::vector edges = {0, 1, 1, 4, 0, 1, 2, 1, 0}; + int n = 3, start = 1, finish = 0, tmp; + nodes.resize(n); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + continue; + } + nodes[i].neighbours.push_back({j, edges[i * n + j]}); + } + } + deixtra(nodes, start - 1); + + ASSERT_TRUE(nodes[finish].len = 3); +} + +TEST(Deixtra, Simple2) { + std::vector nodes; + std::vector edges = {0, 1, 1, 4, 0, 7, 2, 1, 0}; + int n = 3, start = 1, finish = 0, tmp; + nodes.resize(n); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + continue; + } + nodes[i].neighbours.push_back({j, edges[i * n + j]}); + } + } + deixtra(nodes, start - 1); + + ASSERT_TRUE(nodes[finish].len = 4); +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(Jonson, Simple) { + std::vector> expected = {{0, -1, 2, -2, 1}, + {999, 0, 3, -1, 2}, + {1000, 998, 0, 997, 1000}, + {1000, 1, 4, 0, 3}, + {997, -2, 1, -3, 0}}; + std::vector nodes; + std::vector edges = {0, -1, 4, 1000, 1000, 1000, 0, 3, 2, + 2, 1000, 1000, 0, 1000, 1000, 1000, 1, 5, + 1000, 1000, 1000, 1000, 1000, -3, 1000}; + int n = 5, tmp; + nodes.resize(n); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + continue; + } + nodes[i].neighbours.push_back({j, edges[i * n + j]}); + } + } + auto ans = jonson(nodes); + for (int i = 0; i < ans.size(); i++) { + for (int j = 0; j < ans.size(); j++) { + if (i == j) { + continue; + } + ASSERT_TRUE(ans[i][j] == expected[i][j]) + << i << " " << j << " " << ans[i][j] << " " << expected[i][j]; + } + } } diff --git a/task_03/src/topology_sort.cpp b/task_03/src/topology_sort.cpp deleted file mode 100644 index e53f670..0000000 --- a/task_03/src/topology_sort.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "topology_sort.hpp" diff --git a/task_03/src/topology_sort.hpp b/task_03/src/topology_sort.hpp deleted file mode 100644 index 6f70f09..0000000 --- a/task_03/src/topology_sort.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/task_04/src/deixtra.cpp b/task_04/src/deixtra.cpp new file mode 100644 index 0000000..9e6113e --- /dev/null +++ b/task_04/src/deixtra.cpp @@ -0,0 +1,33 @@ +#include "deixtra.h" + +#include +#include +#include + +void deixtra(std::vector &nodes, int start) { + std::priority_queue> qqe; // {len, id} + node *current; + int tmp; + for (auto &i : nodes) { + i.len = std::numeric_limits::max(); + } + nodes[start].len = 0; + + qqe.push({0, start}); + + while (!qqe.empty()) { + current = &nodes[qqe.top().second]; + int dst = qqe.top().first; + qqe.pop(); + if (current->len < dst) { + continue; + } + for (auto &i : current->neighbours) { + int n_dst = dst + i.second; + if (n_dst < nodes[i.first].len) { + nodes[i.first].len = n_dst; + qqe.push({n_dst, i.first}); + } + } + } +} diff --git a/task_04/src/deixtra.h b/task_04/src/deixtra.h new file mode 100644 index 0000000..0b3b693 --- /dev/null +++ b/task_04/src/deixtra.h @@ -0,0 +1,18 @@ +#ifndef __DEIXTRA_H__ +#define __DEIXTRA_H__ + +#include +#include + +class node { + public: + std::vector> neighbours; // {id, size} + int id; + int len; + bool locked = false; // + bool wisited = false; +}; + +void deixtra(std::vector &nodes, int start); + +#endif // !__DEIXTRA_H__ diff --git a/task_04/src/main.cpp b/task_04/src/main.cpp index 0e4393b..06a6735 100644 --- a/task_04/src/main.cpp +++ b/task_04/src/main.cpp @@ -1,3 +1,25 @@ #include +#include -int main() { return 0; } +#include "deixtra.h" + +int main() { + std::vector nodes; + int n, start, finish, tmp; + std::cin >> n >> start >> finish; + nodes.resize(n); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + std::cin >> tmp; + if (i == j) { + continue; + } + nodes[i].neighbours.push_back({j, tmp}); + } + } + deixtra(nodes, start - 1); + + std::cout << nodes[finish - 1].len << std::endl; + + return 0; +} diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 5e11617..2784e73 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,39 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "deixtra.h" + +TEST(Deixtra, Simple) { + std::vector nodes; + std::vector edges = {0, 1, 1, 4, 0, 1, 2, 1, 0}; + int n = 3, start = 1, finish = 0, tmp; + nodes.resize(n); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + continue; + } + nodes[i].neighbours.push_back({j, edges[i * n + j]}); + } + } + deixtra(nodes, start - 1); + + ASSERT_TRUE(nodes[finish].len = 3); +} + +TEST(Deixtra, Simple2) { + std::vector nodes; + std::vector edges = {0, 1, 1, 4, 0, 7, 2, 1, 0}; + int n = 3, start = 1, finish = 0, tmp; + nodes.resize(n); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (i == j) { + continue; + } + nodes[i].neighbours.push_back({j, edges[i * n + j]}); + } + } + deixtra(nodes, start - 1); + + ASSERT_TRUE(nodes[finish].len = 4); } diff --git a/task_05/src/main.cpp b/task_05/src/main.cpp index 0e4393b..dd038b3 100644 --- a/task_05/src/main.cpp +++ b/task_05/src/main.cpp @@ -1,3 +1,9 @@ #include -int main() { return 0; } +#include "rmq.h" + +int main() { + int a[] = {1, 2, 3, -1, 5, 6}; + auto ans = rmq(a, 6, {{0, 2}}); + std::cout << ans[0]; +} diff --git a/task_05/src/rmq.cpp b/task_05/src/rmq.cpp new file mode 100644 index 0000000..44cfb80 --- /dev/null +++ b/task_05/src/rmq.cpp @@ -0,0 +1,71 @@ +#include "rmq.h" + +#include +#include +#include +#include + +const int powers[] = {1, 2, 4, 8, 16, 32, 64, + 128, 256, 512, 1024, 2048, 4096, 8192, + 16384, 32768, 65536, 131072, 262144}; + +std::vector rmq(int *A, int sz, std::vector> brd) { + std::vector> minn; + std::vector ret; + minn.push_back({}); + minn[0].assign(A, A + sz); + int tmp = 1; + while (minn[tmp - 1].size() > 2) { + minn.push_back({}); + for (int i = 1; i < minn[tmp - 1].size(); i += 2) { + minn[tmp].push_back(std::min(minn[tmp - 1][i - 1], minn[tmp - 1][i])); + } + minn[tmp].push_back(std::numeric_limits::max()); + tmp++; + } + + for (auto &i : brd) { + tmp = i.second - i.first; + int minC = std::numeric_limits::max(); + if (tmp < 8) { + for (int j = i.first; j <= i.second; j++) { + minC = std::min(minC, A[j]); + } + ret.push_back(minC); + continue; + } + int j = minn.size(); + while (powers[j] > tmp) { + j--; + } + j--; + int start = i.first / powers[j], stop = i.second / powers[j]; + + for (int k = start + 1; k < stop; k++) { + minC = std::min(minC, minn[j][k]); + } + int k = j; + if (minC > minn[k][stop] && k > 0) { + stop = stop * powers[j]; + while (k > 0) { + k--; + for (; stop + powers[k] <= i.second; stop += powers[k]) { + minC = std::min(minC, minn[k][stop / powers[k]]); + } + } + } + k = j; + if (minC > minn[k][start] && k > 0) { + start = (start + 1) * powers[j]; + while ((--k) >= 0) { + for (; start >= i.first; start -= powers[k]) { + minC = std::min(minC, minn[k][start / powers[k]]); + } + } + } + minC = std::min(minC, A[i.first]); + minC = std::min(minC, A[i.second]); + ret.push_back(minC); + } + return ret; +} diff --git a/task_05/src/rmq.h b/task_05/src/rmq.h new file mode 100644 index 0000000..13737b5 --- /dev/null +++ b/task_05/src/rmq.h @@ -0,0 +1,8 @@ +#include +#include +#ifndef __RMQ_H__ +#define __RMQ_H__ + +std::vector rmq(int *A, int size, std::vector> brd); + +#endif // !__RMQ_H__ diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617..0c0593e 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,42 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include +#include +#include + +#include "rmq.h" + +int ROFLS_KATKA(int *A, int start, int stop) { + int mn = std::numeric_limits::max(); + for (int i = start; i <= stop; i++) { + mn = std::min(A[i], mn); + } + return mn; +} + +TEST(Test, Simple) { + int a[] = {1, 2, 3, -1, 5, 6}; + auto ans = rmq(a, 6, {{0, 2}}); + ASSERT_TRUE(ans[0] == ROFLS_KATKA(a, 0, 2)); +} + +TEST(Test, Rand) { + int a[50], tmp = 0; + srand(22848); + std::vector> dd; + for (int i = 0; i <= 40; i++) { + for (int j = i; j <= 40; j++) { + dd.push_back({i, j}); + } + a[i] = rand(); + } + auto ans = rmq(a, 50, dd); + + for (int i = 0; i < 40; i++) { + for (int j = i; j <= 40; j++) { + ASSERT_TRUE(ans[tmp] == ROFLS_KATKA(a, i, j)) << i << " " << j; + tmp++; + } + } } diff --git a/task_06/src/lca.cpp b/task_06/src/lca.cpp new file mode 100644 index 0000000..0780d24 --- /dev/null +++ b/task_06/src/lca.cpp @@ -0,0 +1,49 @@ +#include +#include +#include + +static int l; +static std::vector tin, tout; +static int timer; +static std::vector> up; + +void dfs(int v, std::vector> &g, int p = 0) { + tin[v] = ++timer; + up[v][0] = p; + for (int i = 1; i <= l; ++i) up[v][i] = up[up[v][i - 1]][i - 1]; + for (size_t i = 0; i < g[v].size(); ++i) { + int to = g[v][i]; + if (to != p) dfs(to, g, v); + } + tout[v] = ++timer; +} + +bool upper(int a, int b) { return tin[a] <= tin[b] && tout[a] >= tout[b]; } + +std::vector lca(std::vector> &g, + std::vector> dd) { + tin.clear(), tout.clear(), up.clear(); + l = 0; + tin.resize(g.size()), tout.resize(g.size()), up.resize(g.size()); + std::vector ret = {}; + l = 0; + while ((1 << l) <= g.size()) ++l; + for (int i = 0; i < g.size(); ++i) up[i].resize(l + 1); + dfs(0, g); + for (auto &dds : dd) { + int a = dds.first, b = dds.second; + std::cout << "as" << std::endl; + if (upper(a, b)) { + ret.push_back(a); + continue; + } + if (upper(b, a)) { + ret.push_back(b); + continue; + } + for (int i = l; i >= 0; --i) + if (!upper(up[a][i], b)) a = up[a][i]; + ret.push_back(up[a][0]); + } + return ret; +} diff --git a/task_06/src/lca.h b/task_06/src/lca.h new file mode 100644 index 0000000..d0c17fb --- /dev/null +++ b/task_06/src/lca.h @@ -0,0 +1,8 @@ +#ifndef __LCA_H__ +#define __LCA_H__ +#include + +std::vector lca(std::vector> &g, + std::vector> dd); + +#endif // !__LCA_H__ diff --git a/task_06/src/main.cpp b/task_06/src/main.cpp index 0e4393b..8ee3b84 100644 --- a/task_06/src/main.cpp +++ b/task_06/src/main.cpp @@ -1,3 +1,12 @@ #include +#include -int main() { return 0; } +#include "lca.h" + +int main() { + std::vector> g = {{0, 1, 2}, {3, 4}, {}, {}, {}}; + std::cout << "as"; + auto a = lca(g, {{3, 4}, {3, 5}}); + std::cout << a[0] << " " << a[1]; + return 0; +} diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617..8d839ee 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,16 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "lca.h" + +TEST(TEST, Simple) { + std::vector> g = {{1, 2}, {3, 4}, {}, {}, {}}; + std::cout << "as"; + auto a = lca(g, {{3, 4}, {3, 5}}); + ASSERT_TRUE(a[0] = 1 && a[1] == 0); +} +TEST(TEST, Simple1) { + std::vector> g = {{1}, {2}, {3}, {4}, {}}; + std::cout << "as"; + auto a = lca(g, {{3, 4}, {1, 4}, {4, 1}}); + ASSERT_TRUE(a[0] = 3 && a[1] == 1 && a[2] == 1) << a[1]; } diff --git a/tidi.yaml b/tidi.yaml new file mode 100644 index 0000000..1c752ab --- /dev/null +++ b/tidi.yaml @@ -0,0 +1,138 @@ +--- +# Configure clang-tidy for this project. + +# Here is an explanation for why some of the checks are disabled: +# +# -google-readability-namespace-comments: the *_CLIENT_NS is a macro, and +# clang-tidy fails to match it against the initial value. +# +# -modernize-use-trailing-return-type: clang-tidy recommends using +# `auto Foo() -> std::string { return ...; }`, we think the code is less +# readable in this form. +# +# --modernize-concat-nested-namespaces: clang-tidy recommends +# `namespace google::cloud {}` over `namespace google { namespace cloud { } }` +# We need to support C++14, which does not supported nested namespaces. +# +# --modernize-use-nodiscard: clang-tidy recommends adding a nodiscard annotation +# to functions where the return value should not be ignored. +# We need to support C++14, which does not supported the annotation. +# +# -modernize-return-braced-init-list: We think removing typenames and using +# only braced-init can hurt readability. +# +# -modernize-avoid-c-arrays: We only use C arrays when they seem to be the +# right tool for the job, such as `char foo[] = "hello"`. In these cases, +# avoiding C arrays often makes the code less readable, and std::array is +# not a drop-in replacement because it doesn't deduce the size. +# +# -performance-move-const-arg: This warning requires the developer to +# know/care more about the implementation details of types/functions than +# should be necessary. For example, `A a; F(std::move(a));` will trigger a +# warning IFF `A` is a trivial type (and therefore the move is +# meaningless). It would also warn if `F` accepts by `const&`, which is +# another detail that the caller need not care about. +# +# -performance-avoid-endl: we would like to turn this on, but there are too +# many legitimate uses in our samples. +# +# -performance-enum-size: Smaller enums may or not may be faster, it depends on +# the architechture. If data size was a consideration, we might decide to +# enable the warnings. +# +# -readability-redundant-declaration: A friend declaration inside a class +# counts as a declaration, so if we also declare that friend outside the +# class in order to document it as part of the public API, that will +# trigger a redundant declaration warning from this check. +# +# -readability-avoid-return-with-void-value: We believe this is idiomatic +# and saves typing, and the intent is obvious. +# +# -readability-function-cognitive-complexity: too many false positives with +# clang-tidy-12. We need to disable this check in macros, and that setting +# only appears in clang-tidy-13. +# +# -bugprone-narrowing-conversions: too many false positives around +# `std::size_t` vs. `*::difference_type`. +# +# -bugprone-easily-swappable-parameters: too many false positives. +# +# -bugprone-implicit-widening-of-multiplication-result: too many false positives. +# Almost any expression of the form `2 * variable` or `long x = a_int * b_int;` +# generates an error. +# +# -bugprone-unchecked-optional-access: too many false positives in tests. +# Despite what the documentation says, this warning appears after +# `ASSERT_TRUE(variable)` or `ASSERT_TRUE(variable.has_value())`. +# +# TODO(#14162): Enable clang-tidy checks. We initially omitted these checks +# because they require large cleanup efforts or were blocking the clang-tidy +# X update. +Checks: > + -*, + abseil-*, + bugprone-*, + google-*, + misc-*, + modernize-*, + performance-*, + portability-*, + readability-*, + -google-readability-braces-around-statements, + -google-readability-namespace-comments, + -google-runtime-references, + -misc-non-private-member-variables-in-classes, + -misc-const-correctness, + -misc-include-cleaner, + -modernize-return-braced-init-list, + -modernize-use-trailing-return-type, + -modernize-concat-nested-namespaces, + -modernize-use-nodiscard, + -modernize-avoid-c-arrays, + -performance-move-const-arg, + -performance-avoid-endl, + -performance-enum-size, + -readability-braces-around-statements, + -readability-identifier-length, + -readability-magic-numbers, + -readability-named-parameter, + -readability-redundant-declaration, + -readability-avoid-return-with-void-value, + -readability-function-cognitive-complexity, + -bugprone-narrowing-conversions, + -bugprone-easily-swappable-parameters, + -bugprone-inc-dec-in-conditions, + -bugprone-implicit-widening-of-multiplication-result, + -bugprone-unchecked-optional-access, + -bugprone-unused-local-non-trivial-variable, + -bugprone-unused-return-value + +# Turn all the warnings from the checks above into errors. +WarningsAsErrors: "*" + +HeaderFilterRegex: "(google/cloud/|generator/).*\\.h$" + +CheckOptions: + - { key: readability-identifier-naming.NamespaceCase, value: lower_case } + - { key: readability-identifier-naming.ClassCase, value: CamelCase } + - { key: readability-identifier-naming.StructCase, value: CamelCase } + - { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase } + - { key: readability-identifier-naming.FunctionCase, value: aNy_CasE } + - { key: readability-identifier-naming.VariableCase, value: lower_case } + - { key: readability-identifier-naming.ClassMemberCase, value: lower_case } + - { key: readability-identifier-naming.ClassMemberSuffix, value: _ } + - { key: readability-identifier-naming.PrivateMemberSuffix, value: _ } + - { key: readability-identifier-naming.ProtectedMemberSuffix, value: _ } + - { key: readability-identifier-naming.EnumConstantCase, value: CamelCase } + - { key: readability-identifier-naming.EnumConstantPrefix, value: k } + - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase } + - { key: readability-identifier-naming.ConstexprVariablePrefix, value: k } + - { key: readability-identifier-naming.GlobalConstantCase, value: CamelCase } + - { key: readability-identifier-naming.GlobalConstantPrefix, value: k } + - { key: readability-identifier-naming.MemberConstantCase, value: CamelCase } + - { key: readability-identifier-naming.MemberConstantPrefix, value: k } + - { key: readability-identifier-naming.StaticConstantCase, value: CamelCase } + - { key: readability-identifier-naming.StaticConstantPrefix, value: k } + - { key: readability-implicit-bool-conversion.AllowIntegerConditions, value: 1 } + - { key: readability-implicit-bool-conversion.AllowPointerConditions, value: 1 } + - { key: readability-function-cognitive-complexity.IgnoreMacros, value: 1 }