diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index 0e4393ba..e62d14ca 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -1,3 +1,17 @@ #include +#include +#include -int main() { return 0; } +#include "searching_sum.hpp" + +int main() { + int n, k; + std::cin >> n >> k; + std::vector vec(n); + for (int i = 0; i < n; i++) { + std::cin >> vec[i]; + } + std::pair ans = SearchingSum(vec, k); + std::cout << ans.first << " " << ans.second << std::endl; + return 0; +} diff --git a/task_01/src/searching_sum.cpp b/task_01/src/searching_sum.cpp new file mode 100644 index 00000000..666700c8 --- /dev/null +++ b/task_01/src/searching_sum.cpp @@ -0,0 +1,17 @@ +#include "searching_sum.hpp" + +#include + +std::pair SearchingSum(std::vector vec, int num) { + int start = 0; + int end = vec.size() - 1; + while (start < end) { + if (vec[start] + vec[end] > num) + --end; + else if (vec[start] + vec[end] < num) + ++start; + else + return std::make_pair(start, end); + } + return std::make_pair(-1, -1); +} \ No newline at end of file diff --git a/task_01/src/searching_sum.hpp b/task_01/src/searching_sum.hpp new file mode 100644 index 00000000..139727d5 --- /dev/null +++ b/task_01/src/searching_sum.hpp @@ -0,0 +1,9 @@ +#ifndef SEARCHING_SUM_HPP +#define SEARCHING_SUM_HPP + +#include +#include + +std::pair SearchingSum(std::vector vec, int num); + +#endif // define Searching_sum.hpp \ No newline at end of file diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index ef5a86ae..eb03eaeb 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -1,8 +1,48 @@ - #include -#include "topology_sort.hpp" +#include +#include + +#include "searching_sum.hpp" TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] + int sum1 = 6; + std::vector vec1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::pair ans1{0, 6}; + ASSERT_EQ(SearchingSum(vec1, sum1), ans1); + + int sum2 = 6; + std::vector vec2{0}; + std::pair ans2{-1, -1}; + ASSERT_EQ(SearchingSum(vec2, sum2), ans2); + + int sum3 = 4; + std::vector vec3{-11, -6, 0, 1, 2, 4, 10, 16}; + std::pair ans3{1, 6}; + ASSERT_EQ(SearchingSum(vec3, sum3), ans3); + + int sum4 = 0; + std::vector vec4{-17, -8, -1, 1, 2, 4, 10}; + std::pair ans4{2, 3}; + ASSERT_EQ(SearchingSum(vec4, sum4), ans4); + + int sum5 = -9; + std::vector vec5{-17, -8, -1, 1, 2, 4, 10}; + std::pair ans5{1, 2}; + ASSERT_EQ(SearchingSum(vec5, sum5), ans5); + + int sum6 = 17; + std::vector vec6{-17, -8, -1, 1, 2, 4, 10}; + std::pair ans6{-1, -1}; + ASSERT_EQ(SearchingSum(vec6, sum6), ans6); + + int sum7 = -1; + std::vector vec7{-18, -10, -1, -1, -1, 0, 3, 5, 10}; + std::pair ans7{2, 5}; + ASSERT_EQ(SearchingSum(vec7, sum7), ans7); + + int sum8 = 5; + std::vector vec8(0); + std::pair ans8{-1, -1}; + ASSERT_EQ(SearchingSum(vec8, sum8), ans8); } diff --git a/task_01/src/topology_sort.cpp b/task_01/src/topology_sort.cpp deleted file mode 100644 index e53f670c..00000000 --- a/task_01/src/topology_sort.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "topology_sort.hpp" diff --git a/task_01/src/topology_sort.hpp b/task_01/src/topology_sort.hpp deleted file mode 100644 index 6f70f09b..00000000 --- a/task_01/src/topology_sort.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/task_02/src/main.cpp b/task_02/src/main.cpp index 0e4393ba..7fbe48d8 100644 --- a/task_02/src/main.cpp +++ b/task_02/src/main.cpp @@ -1,3 +1,3 @@ -#include +#include "stack.hpp" -int main() { return 0; } +int main() { Stack stack; } diff --git a/task_02/src/stack.cpp b/task_02/src/stack.cpp deleted file mode 100644 index 8ca89902..00000000 --- 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 index 138ec40f..ae1df3c0 100644 --- a/task_02/src/stack.hpp +++ b/task_02/src/stack.hpp @@ -1,23 +1,107 @@ #pragma once -#include -#include +#include +template +struct Element { + explicit Element(T data, std::shared_ptr> prev = nullptr) + : element{data}, prev{prev} {} + + explicit Element() : element{}, prev{nullptr} {} + + T element; + + std::shared_ptr> prev; +}; + +template class Stack { public: - void Push(int value); - int Pop(); + explicit Stack() : data_{} {} + + void Push(T value); + + T Pop(); + + bool Empty() const; + + const T& Top() const; + + size_t Size() const; private: - std::stack data_; + Element data_; + + size_t size_ = 0; }; +template +void Stack::Push(T value) { + Element new_data{value, std::make_shared>(data_)}; + size_ += 1; + data_ = new_data; +} + +template +T Stack::Pop() { + T deleted_element = data_.element; + Element new_data = *data_.prev; + data_.prev = nullptr; + data_ = new_data; + size_ -= 1; + return deleted_element; +} + +template +bool Stack::Empty() const { + return data_.prev == nullptr; +} + +template +const T& Stack::Top() const { + return data_.element; +} + +template +size_t Stack::Size() const { + return size_; +} + +template class MinStack { public: - void Push(int value); - int Pop(); - int GetMin(); + void Push(T value); + T Pop(); + T GetMin() const; private: - std::vector data_; + Stack main_stack_; + Stack min_stack_; }; + +template +void MinStack::Push(T value) { + if (main_stack_.Size() == 0) { + min_stack_.Push(value); + main_stack_.Push(value); + } else { + main_stack_.Push(value); + if (value < min_stack_.Top()) + min_stack_.Push(value); + else + min_stack_.Push(min_stack_.Top()); + } +} + +template +T MinStack::Pop() { + T result = main_stack_.Top(); + main_stack_.Pop(); + min_stack_.Pop(); + return result; +} + +template +T MinStack::GetMin() const { + return min_stack_.Top(); +} \ No newline at end of file diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 54e7ce90..eebfa1e4 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -1,12 +1,9 @@ - #include -#include - #include "stack.hpp" TEST(StackTest, Simple) { - Stack stack; + Stack stack; stack.Push(1); // Stack [1] ASSERT_EQ(stack.Pop(), 1); // Stack [] stack.Push(1); // Stack [1] @@ -22,7 +19,7 @@ TEST(StackTest, Simple) { } TEST(MinStackTest, Simple) { - MinStack stack; + MinStack stack; stack.Push(1); // Stack [1] ASSERT_EQ(stack.GetMin(), 1); ASSERT_EQ(stack.Pop(), 1); // Stack [] @@ -39,4 +36,16 @@ TEST(MinStackTest, Simple) { ASSERT_EQ(stack.GetMin(), 1); ASSERT_EQ(stack.Pop(), 3); // Stack [1] ASSERT_EQ(stack.Pop(), 1); // Stack [] + stack.Push(2); // Stack [2] + ASSERT_EQ(stack.GetMin(), 2); + stack.Push(7); // Stack [2, 7] + ASSERT_EQ(stack.GetMin(), 2); + stack.Push(-2); // Stack [2, 7, -2] + ASSERT_EQ(stack.GetMin(), -2); + stack.Push(8); // Stack [2, 7, -2, 8] + ASSERT_EQ(stack.GetMin(), -2); + stack.Push(-2); // Stack [2, 7, -2, 8, -2] + ASSERT_EQ(stack.GetMin(), -2); + ASSERT_EQ(stack.Pop(), -2); // Stack [2, 7, -2, 8] + ASSERT_EQ(stack.GetMin(), -2); } \ No newline at end of file diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 0e4393ba..a46533a9 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -1,3 +1,3 @@ -#include +#include "temperature.hpp" int main() { return 0; } diff --git a/task_03/src/temperature.cpp b/task_03/src/temperature.cpp new file mode 100644 index 00000000..d78b7011 --- /dev/null +++ b/task_03/src/temperature.cpp @@ -0,0 +1,19 @@ +#include "temperature.hpp" + +#include +#include + +std::vector days_before_warming(std::vector daily_temp) { + std::vector days_amount(daily_temp.size()); + std::stack previous_days; + for (int day_index = 0; day_index < daily_temp.size(); ++day_index) { + days_amount[day_index] = 0; + while (!previous_days.empty() && + daily_temp[previous_days.top()] <= daily_temp[day_index]) { + days_amount[previous_days.top()] = day_index - previous_days.top(); + previous_days.pop(); + } + previous_days.push(day_index); + } + return days_amount; +} \ No newline at end of file diff --git a/task_03/src/temperature.hpp b/task_03/src/temperature.hpp new file mode 100644 index 00000000..c0e2c0a5 --- /dev/null +++ b/task_03/src/temperature.hpp @@ -0,0 +1,3 @@ +#include + +std::vector days_before_warming(std::vector daily_temp); \ No newline at end of file diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86ae..24dfa245 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,8 +1,33 @@ - #include -#include "topology_sort.hpp" +#include + +#include "temperature.hpp" + +TEST(temperature, Simple) { + std::vector daily_temp_1 = days_before_warming({1, 2, 3, 4, 5}); + std::vector result_1 = {1, 1, 1, 1, 0}; + ASSERT_EQ(daily_temp_1, result_1); + + std::vector daily_temp_2 = days_before_warming({0}); + std::vector result_2 = {0}; + ASSERT_EQ(daily_temp_2, result_2); + + std::vector daily_temp_3 = days_before_warming({}); + std::vector result_3 = {}; + ASSERT_EQ(daily_temp_3, result_3); + + std::vector daily_temp_4 = + days_before_warming({1, 2, -4, -5, -6, -8, 9}); + std::vector result_4 = {1, 5, 4, 3, 2, 1, 0}; + ASSERT_EQ(daily_temp_4, result_4); + + std::vector daily_temp_5 = days_before_warming({1, 2, 1, 2, 1, 2, 1, 2}); + std::vector result_5 = {1, 2, 1, 2, 1, 2, 1, 0}; + ASSERT_EQ(daily_temp_5, result_5); -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} + std::vector daily_temp_6 = + days_before_warming({2, 1, 3, 1, 4, 1, 3, 1, 2, 1, 5}); + std::vector result_6 = {2, 1, 2, 1, 6, 1, 4, 1, 2, 1, 0}; + ASSERT_EQ(daily_temp_6, result_6); +} \ No newline at end of file diff --git a/task_03/src/topology_sort.cpp b/task_03/src/topology_sort.cpp deleted file mode 100644 index e53f670c..00000000 --- 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 6f70f09b..00000000 --- a/task_03/src/topology_sort.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/task_04/src/heap.hpp b/task_04/src/heap.hpp new file mode 100644 index 00000000..85f2944b --- /dev/null +++ b/task_04/src/heap.hpp @@ -0,0 +1,61 @@ +#include +#include +#include + +template +class MinHeap { + public: + MinHeap() = default; + + MinHeap(const std::vector& data) { + for (auto& elem : data) Add(elem); + } + + size_t Size() { return data_.size(); } + + void Add(T elem) { + data_.push_back(elem); + SiftUp(); + } + + T ExtractMin() { + if (Empty()) throw std::out_of_range("empty heap"); + + T minimum = data_[0]; + std::swap(data_[0], data_[Size() - 1]); + data_.pop_back(); + SiftDown(0); + return minimum; + } + + bool Empty() { return Size() == 0; } + + private: + std::vector data_; + + size_t IndexParent(size_t index) const { return (index - 1) / 2; } + + size_t IndexLeftChild(size_t index) const { return (2 * index + 1); } + + size_t IndexRightChild(size_t index) const { return (2 * index + 2); } + + void SiftDown(size_t index) { + while (IndexLeftChild(index) < Size()) { + size_t minimum = IndexLeftChild(index); + if (IndexRightChild(index) < Size() && + data_[IndexRightChild(index)] < data_[minimum]) + minimum = IndexRightChild(index); + if (data_[index] < data_[minimum]) break; + std::swap(data_[index], data_[minimum]); + index = minimum; + } + } + + void SiftUp() { + size_t index = Size() - 1; + while (index > 0 && data_[index] < data_[IndexParent(index)]) { + std::swap(data_[index], data_[IndexParent(index)]); + index = IndexParent(index); + } + } +}; \ No newline at end of file diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 5e11617e..85c4bb5d 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,133 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include + +#include "heap.hpp" + +TEST(BinaryMinHeap_test, Empty) { + MinHeap heap; + ASSERT_EQ(heap.Empty(), true); + ASSERT_EQ(heap.Size(), 0); + heap.Add(1); + ASSERT_EQ(heap.Empty(), false); + ASSERT_EQ(heap.Size(), 1); + ASSERT_EQ(heap.ExtractMin(), 1); + EXPECT_THROW(heap.ExtractMin(), std::out_of_range); +} + +TEST(BinaryMinHeap_test, WithoutDuplicates) { + MinHeap heap{}; + for (int value : {3, 1, 2, 4, 5}) heap.Add(value); + ASSERT_EQ(heap.ExtractMin(), 1); + ASSERT_EQ(heap.ExtractMin(), 2); + ASSERT_EQ(heap.ExtractMin(), 3); + ASSERT_EQ(heap.ExtractMin(), 4); + ASSERT_EQ(heap.ExtractMin(), 5); +} + +TEST(BinaryMinHeap_test, WithDuplicates) { + MinHeap heap{}; + for (int value : {6, 7, 7, 3, 3, 3, 1, 2}) heap.Add(value); + ASSERT_EQ(heap.ExtractMin(), 1); + ASSERT_EQ(heap.ExtractMin(), 2); + ASSERT_EQ(heap.ExtractMin(), 3); + ASSERT_EQ(heap.ExtractMin(), 3); + ASSERT_EQ(heap.ExtractMin(), 3); + ASSERT_EQ(heap.ExtractMin(), 6); + ASSERT_EQ(heap.ExtractMin(), 7); + ASSERT_EQ(heap.ExtractMin(), 7); +} + +TEST(BinaryMinHeap_test, ConstructorTest) { + std::vector h{1, 2, 3}; + MinHeap heap{h}; + ASSERT_EQ(heap.ExtractMin(), 1); + ASSERT_EQ(heap.ExtractMin(), 2); + ASSERT_EQ(heap.ExtractMin(), 3); +} + +TEST(BinaryMinHeap_test, EmptyHeapTest) { + MinHeap heap; + EXPECT_TRUE(heap.Empty()); +} + +TEST(BinaryMinHeap_test, AddElementTest) { + MinHeap heap; + heap.Add(5); + EXPECT_EQ(heap.Size(), 1); + EXPECT_EQ(heap.ExtractMin(), 5); +} + +TEST(BinaryMinHeap_test, ExtractMinTest) { + MinHeap heap; + heap.Add(5); + heap.Add(3); + heap.Add(7); + EXPECT_EQ(heap.ExtractMin(), 3); + EXPECT_EQ(heap.Size(), 2); +} + +TEST(BinaryMinHeap_test, HeapPropertyAfterAddTest) { + MinHeap heap; + heap.Add(5); + heap.Add(3); + heap.Add(7); + heap.Add(2); + heap.Add(6); + EXPECT_EQ(heap.ExtractMin(), 2); +} + +TEST(BinaryMinHeap_test, HeapPropertyAfterExtractMinTest) { + MinHeap heap; + heap.Add(5); + heap.Add(3); + heap.Add(7); + heap.Add(2); + heap.Add(6); + heap.ExtractMin(); + EXPECT_EQ(heap.ExtractMin(), 3); +} + +TEST(BinaryMinHeap_test, AddDuplicateElementsTest) { + MinHeap heap; + heap.Add(5); + heap.Add(3); + heap.Add(5); + EXPECT_EQ(heap.ExtractMin(), 3); + EXPECT_EQ(heap.ExtractMin(), 5); + EXPECT_EQ(heap.ExtractMin(), 5); } + +TEST(BinaryMinHeap_test, ExtractMinFromEmptyHeap) { + MinHeap heap; + ASSERT_THROW(heap.ExtractMin(), std::out_of_range); +} + +TEST(BinaryMinHeap_test, AddAndExtractMinLargeData) { + MinHeap heap; + for (int i = 10000; i > 0; --i) { + heap.Add(i); + } + for (int i = 1; i <= 100; ++i) { + EXPECT_EQ(heap.ExtractMin(), i); + } +} + +TEST(BinaryMinHeap_test, ExtractMinWithDuplicates) { + MinHeap heap; + heap.Add(5); + heap.Add(3); + heap.Add(3); + heap.Add(7); + heap.Add(2); + EXPECT_EQ(heap.ExtractMin(), 2); + EXPECT_EQ(heap.ExtractMin(), 3); + EXPECT_EQ(heap.ExtractMin(), 3); +} + +TEST(BinaryMinHeap_test, ExtractMinAfterInitializationWithVector) { + std::vector data = {8, 2, 10, 3, 5}; + MinHeap heap(data); + EXPECT_EQ(heap.ExtractMin(), 2); +} \ No newline at end of file diff --git a/task_05/src/main.cpp b/task_05/src/main.cpp index 0e4393ba..104510d4 100644 --- a/task_05/src/main.cpp +++ b/task_05/src/main.cpp @@ -1,3 +1,11 @@ #include -int main() { return 0; } +#include "merge_sort.hpp" + +int main() { + constexpr int size = 8; + int arr[size] = {6, 5, 3, 1, 8, 7, 2, 4}; + MergeSort(arr, arr + size); + for (int i = 0; i < size; ++i) std::cout << arr[i] << " "; + return 0; +} diff --git a/task_05/src/merge_sort.hpp b/task_05/src/merge_sort.hpp new file mode 100644 index 00000000..d080e40b --- /dev/null +++ b/task_05/src/merge_sort.hpp @@ -0,0 +1,34 @@ +template +void MergeTwoSortdedArrays(T* first_arr_begin, T* second_arr_begin, T* end) { + int size = end - first_arr_begin; + T array[size]; + int index = 0; + T* middle = second_arr_begin; + T* start = first_arr_begin; + while ((start < second_arr_begin) || (middle < end)) { + if ((start < second_arr_begin) && (middle < end)) + if (*start <= *middle) { + array[index] = *(start++); + } else { + array[index] = *(middle++); + } + else if ((start < second_arr_begin) && (middle == end)) + array[index] = *(start++); + else if ((start == second_arr_begin) && (middle < end)) + array[index] = *(middle++); + ++index; + } + + index = 0; + for (T* element_ptr = first_arr_begin; element_ptr < end; ++element_ptr) + *element_ptr = array[index++]; +} + +template +void MergeSort(T* begin, T* end) { + if ((begin == end) || ((end - begin) == 1)) return; + int step = (end - begin) / 2; + MergeSort(begin, begin + step); + MergeSort(begin + step, end); + MergeTwoSortdedArrays(begin, begin + step, end); +} \ No newline at end of file diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617e..c64abeca 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,79 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include + +TEST(SortAlgos, Simple_Int) { + std::vector a1{5, 3, 4, 1, 2}; + MergeSort(&a1[0], &a1[a1.size()]); + EXPECT_TRUE(std::is_sorted(&a1[0], &a1[a1.size()])); + + std::vector a2{7, 7, -10, -9, 2, 5, -5}; + MergeSort(&a2[0], &a2[a2.size()]); + EXPECT_TRUE(std::is_sorted(&a2[0], &a2[a2.size()])); + + std::vector a3{3, 9, 3, -3, 1, 0, -3, -5, 0}; + MergeSort(&a3[0], &a3[a3.size()]); + EXPECT_TRUE(std::is_sorted(&a3[0], &a3[a3.size()])); + + std::vector a4{3, -3, 3, -3, 3, 3, -3, -3}; + MergeSort(&a4[0], &a4[a4.size()]); + EXPECT_TRUE(std::is_sorted(&a4[0], &a4[a4.size()])); + + std::vector a5{5, 4, 3, 2, 1}; + MergeSort(&a5[0], &a5[a5.size()]); + EXPECT_TRUE(std::is_sorted(&a5[0], &a5[a5.size()])); +} + +TEST(SortAlgos, Empty) { + std::vector a; + MergeSort(&a[0], &a[a.size()]); + EXPECT_TRUE(a.empty()); +} + +TEST(SortAlgos, Sorted) { + std::vector a{1, 2, 3, 4, 5}; + MergeSort(&a[0], &a[a.size()]); + EXPECT_TRUE(std::is_sorted(&a[0], &a[a.size()])); +} + +TEST(SortAlgos, Double) { + std::vector a{-9.4, -8.4, 8.7, 4.3, 5.8, 0.4}; + MergeSort(&a[0], &a[a.size()]); + EXPECT_TRUE(std::is_sorted(&a[0], &a[a.size()])); + + std::vector a2{-7.1, 0.3, 9.3, 9.6, -0.0, -3.2, 4.3, -9.2, 8.6, 2.7}; + MergeSort(&a2[0], &a2[a2.size()]); + EXPECT_TRUE(std::is_sorted(&a2[0], &a2[a2.size()])); + + std::vector a3{0.4, -6.2, 2.7, 6.9, -7.1, -1.5, 8.9, 5.8, 2.1}; + MergeSort(&a3[0], &a3[a3.size()]); + EXPECT_TRUE(std::is_sorted(&a3[0], &a3[a3.size()])); + + std::vector a4{5.2, -8.8, 3.6, 2.3, 9.5, 2.5, + -7.5, 5.0, -1.2, -3.8, -1.1}; + MergeSort(&a4[0], &a4[a4.size()]); + EXPECT_TRUE(std::is_sorted(&a4[0], &a4[a4.size()])); + + std::vector a5{50.1, 6.4, 8.7, 5.4, 9.1, -5.9, -4.8, -8.7, 5.6, + 8.4, 0.5, -0.7, -7.1, 3.7, -3.3, -7.8, -2.1}; + MergeSort(&a5[0], &a5[a5.size()]); + EXPECT_TRUE(std::is_sorted(&a5[0], &a5[a5.size()])); +} + +TEST(SortAlgos, Strings) { + std::vector a{"a", "b", "c", "d", "e"}; + MergeSort(&a[0], &a[a.size()]); + EXPECT_TRUE(std::is_sorted(&a[0], &a[a.size()])); +} + +TEST(SortAlgos, Duplicates) { + std::vector a{5, 3, 4, 1, 2, 3, 1, 4}; + MergeSort(&a[0], &a[a.size()]); + EXPECT_TRUE(std::is_sorted(&a[0], &a[a.size()])); +} + +TEST(SortAlgos, Characters) { + std::vector a{'e', 'a', 'c', 'a', 'd'}; + MergeSort(&a[0], &a[a.size()]); + EXPECT_TRUE(std::is_sorted(&a[0], &a[a.size()])); } diff --git a/task_06/src/find_order_statistic.hpp b/task_06/src/find_order_statistic.hpp new file mode 100644 index 00000000..dfd6661e --- /dev/null +++ b/task_06/src/find_order_statistic.hpp @@ -0,0 +1,62 @@ +#include + +template +std::size_t Division(std::vector data, std::size_t left, std::size_t right) { + std::size_t middle = (left + right - 1) / 2; + + if (data[left] < data[middle]) { + if (data[right] < data[left]) + return left; + else if (data[right] < data[middle]) + return right; + return middle; + } else { + if (data[right] < data[middle]) + return middle; + else if (data[right] < data[left]) + return right; + return left; + } +} + +template +std::size_t Partition(std::vector& data, std::size_t left, + std::size_t right) { + std::size_t pivotPos = Division(data, left, right); + + if (pivotPos != right - 1) { + std::swap(data[right - 1], data[pivotPos]); + } + + std::size_t left_index = left; + std::size_t right_index = left; + T pivot = data[right - 1]; + while (right_index < right - 1) { + if (data[right_index] <= pivot) { + std::swap(data[left_index++], data[right_index]); + } + ++right_index; + } + if (left_index != right - 1) { + std::swap(data[left_index], data[right - 1]); + } + return left_index; +} + +template +T FindOrderStatistic(std::vector& data, std::size_t k) { + std::size_t lastPivotPos = 0; + std::size_t left = 0; + std::size_t right = data.size(); + + while (left < right) { + if ((lastPivotPos = Partition(data, left, right)) == k) + return data[lastPivotPos]; + else if (lastPivotPos > k) { + right = lastPivotPos; + } else { + left = lastPivotPos + 1; + } + } + return data[lastPivotPos]; +} \ No newline at end of file diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617e..27acc29e 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,68 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include + +#include "find_order_statistic.hpp" + +TEST(OrderStats, Sorted) { + std::vector v{1, 2, 3, 4, 5, 6}; + ASSERT_EQ(FindOrderStatistic(v, 0), 1); + ASSERT_EQ(FindOrderStatistic(v, 1), 2); + ASSERT_EQ(FindOrderStatistic(v, 2), 3); + ASSERT_EQ(FindOrderStatistic(v, 3), 4); + ASSERT_EQ(FindOrderStatistic(v, 4), 5); + ASSERT_EQ(FindOrderStatistic(v, 5), 6); +} +TEST(OrderStats, InverseSorted) { + std::vector v{6, 5, 4, 3, 2, 1}; + ASSERT_EQ(FindOrderStatistic(v, 0), 1); + ASSERT_EQ(FindOrderStatistic(v, 1), 2); + ASSERT_EQ(FindOrderStatistic(v, 2), 3); + ASSERT_EQ(FindOrderStatistic(v, 3), 4); + ASSERT_EQ(FindOrderStatistic(v, 4), 5); + ASSERT_EQ(FindOrderStatistic(v, 5), 6); +} +//[8, 22, 37, 40, 60, 61, 63, 84, 97, 99] + +TEST(OrderStats, Simple1) { + std::vector v{1, 10, 2, 9, 3, 8, 4, 7, 5, 6}; + ASSERT_EQ(FindOrderStatistic(v, 0), 1); + ASSERT_EQ(FindOrderStatistic(v, 1), 2); + ASSERT_EQ(FindOrderStatistic(v, 2), 3); + ASSERT_EQ(FindOrderStatistic(v, 3), 4); + ASSERT_EQ(FindOrderStatistic(v, 4), 5); + ASSERT_EQ(FindOrderStatistic(v, 5), 6); + ASSERT_EQ(FindOrderStatistic(v, 6), 7); + ASSERT_EQ(FindOrderStatistic(v, 7), 8); + ASSERT_EQ(FindOrderStatistic(v, 8), 9); + ASSERT_EQ(FindOrderStatistic(v, 9), 10); +} +TEST(OrderStats, Simple2) { + std::vector v{37.75, 99.53, 63.24, 22.56, 37.74, + 60.32, 61.48, 8.15, 84.52, 97.93}; + ASSERT_EQ(FindOrderStatistic(v, 0), 8.15); + ASSERT_EQ(FindOrderStatistic(v, 1), 22.56); + ASSERT_EQ(FindOrderStatistic(v, 2), 37.74); + ASSERT_EQ(FindOrderStatistic(v, 3), 37.75); + ASSERT_EQ(FindOrderStatistic(v, 4), 60.32); + ASSERT_EQ(FindOrderStatistic(v, 5), 61.48); + ASSERT_EQ(FindOrderStatistic(v, 6), 63.24); + ASSERT_EQ(FindOrderStatistic(v, 7), 84.52); + ASSERT_EQ(FindOrderStatistic(v, 8), 97.93); + ASSERT_EQ(FindOrderStatistic(v, 9), 99.53); } + +TEST(OrderStats, Char) { + std::vector v{'d', 's', 'a', 'b'}; + ASSERT_EQ(FindOrderStatistic(v, 1), 'b'); +} + +TEST(OrderStats, SameNumbers) { + std::vector v{2, 2, 2, 2, 2, 2}; + ASSERT_EQ(FindOrderStatistic(v, 0), 2); + ASSERT_EQ(FindOrderStatistic(v, 1), 2); + ASSERT_EQ(FindOrderStatistic(v, 2), 2); + ASSERT_EQ(FindOrderStatistic(v, 3), 2); + ASSERT_EQ(FindOrderStatistic(v, 4), 2); + ASSERT_EQ(FindOrderStatistic(v, 5), 2); +} \ No newline at end of file diff --git a/task_07/src/AVL_tree.cpp b/task_07/src/AVL_tree.cpp new file mode 100644 index 00000000..383704a4 --- /dev/null +++ b/task_07/src/AVL_tree.cpp @@ -0,0 +1,98 @@ +#include "AVL_tree.hpp" + +#include +#include + +void AVL_Tree::Insert(int value) { root_ = Insert(root_, value); } +void AVL_Tree::Remove(int value) { root_ = Remove(root_, value); } +bool AVL_Tree::Contains(int value) const { return Contains(root_, value); } + +Node* AVL_Tree::Insert(Node* root, int value) { + if (!root) return new Node(value); + if (value < root->key) + root->left = Insert(root->left, value); + else + root->right = Insert(root->right, value); + return Balance(root); +} + +Node* AVL_Tree::Remove(Node* root, int value) { + if (!root) return 0; + if (value < root->key) + root->left = Remove(root->left, value); + else if (value > root->key) + root->right = Remove(root->right, value); + else if (value == root->key) { + Node* new_node_1 = root->left; + Node* new_node_2 = root->right; + delete root; + if (!new_node_2) return new_node_1; + Node* min = FindMin(new_node_2); + min->right = RemoveMin(new_node_2); + min->left = new_node_1; + return Balance(min); + } else { + throw std::runtime_error("AVL_Tree does not contain this element"); + } + return Balance(root); +} + +bool AVL_Tree::Contains(Node* node, int value) const { + if (!node) return false; + if (value < node->key) return Contains(node->left, value); + if (value > node->key) return Contains(node->right, value); + return true; +} + +Node* AVL_Tree::FindMin(Node* root) const { + return root->left ? FindMin(root->left) : root; +} + +Node* AVL_Tree::RemoveMin(Node* root) { + if (!root->left) return root->right; + root->left = RemoveMin(root->left); + return Balance(root); +} + +Node* AVL_Tree::Balance(Node* node) { + FixHeight(node); + if (Difference(node) == 2) { + if (Difference(node->right) < 0) node->right = RightRotate(node->right); + return LeftRotate(node); + } + if (Difference(node) == -2) { + if (Difference(node->left) > 0) node->left = LeftRotate(node->left); + return RightRotate(node); + } + return node; +} + +Node* AVL_Tree::RightRotate(Node* node) { + Node* new_node = node->left; + node->left = new_node->right; + new_node->right = node; + FixHeight(node); + FixHeight(new_node); + return new_node; +} + +Node* AVL_Tree::LeftRotate(Node* node) { + Node* new_node = node->right; + node->right = new_node->left; + new_node->left = node; + FixHeight(node); + FixHeight(new_node); + return new_node; +} + +unsigned AVL_Tree::Height(Node* node) const { return node ? node->height : 0; } + +int AVL_Tree::Difference(Node* node) const { + return Height(node->right) - Height(node->left); +} + +void AVL_Tree::FixHeight(Node* node) { + unsigned left_height = Height(node->left); + unsigned right_height = Height(node->right); + node->height = std::max(left_height, right_height) + 1; +} \ No newline at end of file diff --git a/task_07/src/AVL_tree.hpp b/task_07/src/AVL_tree.hpp new file mode 100644 index 00000000..2feee9f8 --- /dev/null +++ b/task_07/src/AVL_tree.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +struct Node { + Node(int k) : key{k} {} + int key; + unsigned height = 1; + Node* left = nullptr; + Node* right = nullptr; +}; + +class AVL_Tree { + public: + void Insert(int value); + void Remove(int value); + bool Contains(int value) const; + + private: + Node* root_ = nullptr; + + Node* Insert(Node* root, int value); + Node* Remove(Node* root, int value); + bool Contains(Node* node, int value) const; + + Node* FindMin(Node* root) const; + Node* RemoveMin(Node* root); + + Node* Balance(Node* node); + + Node* RightRotate(Node* node); + Node* LeftRotate(Node* node); + + unsigned Height(Node* node) const; + int Difference(Node* node) const; + void FixHeight(Node* node); +}; \ No newline at end of file diff --git a/task_07/src/test.cpp b/task_07/src/test.cpp index 5e11617e..5d86e36e 100644 --- a/task_07/src/test.cpp +++ b/task_07/src/test.cpp @@ -1,6 +1,86 @@ - +#include #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "AVL_tree.hpp" + +TEST(AVLTreeTest, InsertAndContains) { + AVL_Tree tree; + + tree.Insert(10); + tree.Insert(5); + tree.Insert(15); + + ASSERT_EQ(tree.Contains(10), true); + tree.Remove(10); + ASSERT_EQ(tree.Contains(5), true); + ASSERT_EQ(tree.Contains(15), true); + ASSERT_EQ(tree.Contains(20), false); + ASSERT_EQ(tree.Contains(10), false); +} + +TEST(AVLTreeTest, DuplicateInsert) { + AVL_Tree tree; + tree.Insert(5); + tree.Insert(5); + tree.Insert(5); + ASSERT_EQ(tree.Contains(5), true); +} + +TEST(AVLTreeTest, RemoveNonExisting) { + AVL_Tree tree; + tree.Insert(5); + tree.Remove(10); + ASSERT_EQ(tree.Contains(5), true); + ASSERT_EQ(tree.Contains(10), false); +} + +TEST(AVLTreeTest, LeftRotation) { + AVL_Tree tree; + tree.Insert(30); + tree.Insert(20); + tree.Insert(10); + ASSERT_EQ(tree.Contains(10), true); + ASSERT_EQ(tree.Contains(20), true); + ASSERT_EQ(tree.Contains(30), true); } + +TEST(AVLTreeTest, RightRotation) { + AVL_Tree tree; + tree.Insert(10); + tree.Insert(20); + tree.Insert(30); + ASSERT_EQ(tree.Contains(10), true); + ASSERT_EQ(tree.Contains(20), true); + ASSERT_EQ(tree.Contains(30), true); +} + +TEST(AVLTreeTest, RandomData) { + AVL_Tree tree; + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dist(1, 1000); + + std::vector data(100); + for (int i = 0; i < 100; ++i) { + data[i] = dist(gen); + } + + std::shuffle(data.begin(), data.end(), gen); + + for (int value : data) { + tree.Insert(value); + } + + for (int value : data) { + ASSERT_EQ(tree.Contains(value), true); + } + + std::shuffle(data.begin(), data.end(), gen); + for (int i = 0; i < 50; ++i) { + tree.Remove(data[i]); + } + + for (int i = 50; i < 100; ++i) { + ASSERT_EQ(tree.Contains(data[i]), true); + } +} \ No newline at end of file diff --git a/task_08/src/hash_table.cpp b/task_08/src/hash_table.cpp new file mode 100644 index 00000000..c18d0e37 --- /dev/null +++ b/task_08/src/hash_table.cpp @@ -0,0 +1,89 @@ +#include "hash_table.hpp" + +#include +#include + +void HashTable::Insert(int value) { + size_t hash = FirstHashFunction(value) % buffer_size_; + int attemps_count = 0; + while (cell_conditions_[hash] == Condition::Fill) { + if (container_[hash] == value) return; + ++attemps_count; + hash = + (FirstHashFunction(value) + attemps_count * SecondHashFunction(value)) % + buffer_size_; + } + container_[hash] = value; + cell_conditions_[hash] = Condition::Fill; + ++used_cell_; + ++size_; + + double used_cells_coef = double(used_cell_) / buffer_size_; + if (used_cells_coef >= rehash_coefficient) Rehash(); +} + +void HashTable::Remove(int value) { + size_t hash = FirstHashFunction(value) % buffer_size_; + int attemps_count = 0; + while (cell_conditions_[hash] != Condition::Empty) { + if (container_[hash] == value && + cell_conditions_[hash] == Condition::Fill) { + cell_conditions_[hash] = Condition::Deleted; + --size_; + break; + } + if (container_[hash] == value && + cell_conditions_[hash] == Condition::Deleted) + break; + ++attemps_count; + hash = + (FirstHashFunction(value) + attemps_count * SecondHashFunction(value)) % + buffer_size_; + } +} + +bool HashTable::Contains(int value) { + size_t hash = FirstHashFunction(value); + int attemps_count = 0; + while (cell_conditions_[hash] != Condition::Empty) { + if (container_[hash] == value && cell_conditions_[hash] == Condition::Fill) + return true; + ++attemps_count; + hash = + (FirstHashFunction(value) + attemps_count * SecondHashFunction(value)) % + buffer_size_; + } + return false; +} + +void HashTable::Clear() { + used_cell_ = 0; + size_ = 0; + for (auto& cell : cell_conditions_) cell = Condition::Empty; +} +size_t HashTable::Size() { return size_; } + +size_t HashTable::FirstHashFunction(int key) { + return floor(buffer_size_ * + ((key * hash_coeficent) - floor(key * hash_coeficent))); +} +size_t HashTable::SecondHashFunction(int key) { + return (key * buffer_size_ - 1) % buffer_size_; +} + +void HashTable::Resize() { + buffer_size_ *= 2; + container_.resize(buffer_size_); + cell_conditions_.resize(buffer_size_, Condition::Empty); +} + +void HashTable::Rehash() { + std::vector used_elem; + for (size_t i = 0; i < buffer_size_; ++i) + if (cell_conditions_[i] == Condition::Fill) + used_elem.push_back(container_[i]); + + Resize(); + Clear(); + for (auto& elem : used_elem) Insert(elem); +} \ No newline at end of file diff --git a/task_08/src/hash_table.hpp b/task_08/src/hash_table.hpp new file mode 100644 index 00000000..a6ba3da3 --- /dev/null +++ b/task_08/src/hash_table.hpp @@ -0,0 +1,36 @@ + + +#include +#include +class HashTable { + public: + HashTable() + : buffer_size_(default_buffer_size), + size_(0), + used_cell_(0), + container_(buffer_size_), + cell_conditions_(buffer_size_, Condition::Empty) {} + void Insert(int value); + void Remove(int value); + bool Contains(int value); + + void Clear(); + size_t Size(); + + private: + enum class Condition { Fill, Deleted, Empty }; + constexpr static const double rehash_coefficient = 0.75; + constexpr static const double default_buffer_size = 8; + constexpr static const double hash_coeficent = 0.86724813; + size_t buffer_size_; + size_t size_; + size_t used_cell_; + std::vector container_; + std::vector cell_conditions_; + + size_t FirstHashFunction(int key); + size_t SecondHashFunction(int key); + + void Resize(); + void Rehash(); +}; \ No newline at end of file diff --git a/task_08/src/test.cpp b/task_08/src/test.cpp index 5e11617e..00f5eaa4 100644 --- a/task_08/src/test.cpp +++ b/task_08/src/test.cpp @@ -1,6 +1,65 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include + +TEST(HashTableTest, ContainsElement) { + HashTable table; + table.Insert(5); + ASSERT_TRUE(table.Contains(5)); +} + +TEST(HashTableTest, InsertElement) { + HashTable table; + table.Insert(10); + ASSERT_TRUE(table.Contains(10)); +} + +TEST(HashTableTest, RemoveElement) { + HashTable table; + table.Insert(15); + table.Remove(15); + ASSERT_FALSE(table.Contains(15)); +} + +TEST(HashTableTest, ClearTable) { + HashTable table; + table.Insert(20); + table.Clear(); + ASSERT_EQ(table.Size(), 0); } + +TEST(HashTableTest, SizeAfterInsertion) { + HashTable table; + table.Insert(25); + table.Insert(30); + ASSERT_EQ(table.Size(), 2); +} + +TEST(HashTableTest, ClearTableWithManyElements) { + HashTable table; + for (int i = 0; i < 1000; ++i) { + table.Insert(i); + } + table.Clear(); + ASSERT_EQ(table.Size(), 0); +} + +TEST(HashTableTest, CollisionHandling) { + HashTable table; + table.Insert(5); + table.Insert(15); + ASSERT_TRUE(table.Contains(5)); + ASSERT_TRUE(table.Contains(15)); +} + +TEST(HashTableTest, SizeAfterRemoval) { + HashTable table; + for (int i = 0; i < 50; ++i) { + table.Insert(i); + } + for (int i = 0; i < 25; ++i) { + table.Remove(i); + } + ASSERT_EQ(table.Size(), 25); +} \ No newline at end of file diff --git a/task_09/src/MinimumCoinsAmount.cpp b/task_09/src/MinimumCoinsAmount.cpp new file mode 100644 index 00000000..414f762e --- /dev/null +++ b/task_09/src/MinimumCoinsAmount.cpp @@ -0,0 +1,10 @@ +#include "MinimumCoinsAmount.hpp" + +int MinimumCoinsAmount(int amount, std::vector& coins) { + std::vector amounts(amount + 1, amount + 1); + amounts[0] = 0; + for (int i = 1; i <= amount; ++i) + for (auto& coin : coins) + if (coin <= i) amounts[i] = std::min(amounts[i], amounts[i - coin] + 1); + return amounts[amount] > amount ? -1 : amounts[amount]; +} \ No newline at end of file diff --git a/task_09/src/MinimumCoinsAmount.hpp b/task_09/src/MinimumCoinsAmount.hpp new file mode 100644 index 00000000..a517a91a --- /dev/null +++ b/task_09/src/MinimumCoinsAmount.hpp @@ -0,0 +1,5 @@ +#pragma once +#include +#include + +int MinimumCoinsAmount(int amount, std::vector& coins); \ No newline at end of file diff --git a/task_09/src/test.cpp b/task_09/src/test.cpp index 869094dd..252a4e37 100644 --- a/task_09/src/test.cpp +++ b/task_09/src/test.cpp @@ -1,4 +1,49 @@ #include -TEST(TopologySort, Simple) { ASSERT_EQ(1, 1); } +#include "MinimumCoinsAmount.hpp" + +TEST(ChangeCoinsTest, Simple1) { + std::vector coins = {1, 2, 5}; + EXPECT_EQ(MinimumCoinsAmount(11, coins), 3); +} + +TEST(ChangeCoinsTest, Simple2) { + std::vector coins = {1, 2, 5, 7, 10}; + EXPECT_EQ(MinimumCoinsAmount(15, coins), 2); + EXPECT_EQ(MinimumCoinsAmount(14, coins), 2); + EXPECT_EQ(MinimumCoinsAmount(13, coins), 3); + EXPECT_EQ(MinimumCoinsAmount(114, coins), 12); + EXPECT_EQ(MinimumCoinsAmount(11, coins), 2); + EXPECT_EQ(MinimumCoinsAmount(5, coins), 1); +} + +TEST(ChangeCoinsTest, ImpossibleTest) { + std::vector coins = {2, 3}; + EXPECT_EQ(MinimumCoinsAmount(1, coins), -1); +} + +TEST(ChangeCoinsTest, ZeroTest) { + std::vector coins = {1, 2, 5}; + EXPECT_EQ(MinimumCoinsAmount(0, coins), 0); +} + +TEST(ChangeCoinsTest, LargeSumTest) { + std::vector coins = {1, 2, 5, 10, 20, 50, 100}; + EXPECT_EQ(MinimumCoinsAmount(35891468, coins), 358919); +} + +TEST(ChangeCoinsTest, SingleCoinTest) { + std::vector coins = {1}; + EXPECT_EQ(MinimumCoinsAmount(5, coins), 5); +} + +TEST(ChangeCoinsTest, NoCoinsTest) { + std::vector coins = {}; + EXPECT_EQ(MinimumCoinsAmount(10, coins), -1); +} + +TEST(ChangeCoinsTest, LargeCoinsTest) { + std::vector coins = {1, 2, 5, 10, 20, 50, 100, 200, 500, 1000}; + EXPECT_EQ(MinimumCoinsAmount(1279, coins), 7); +} \ No newline at end of file