diff --git a/task_01/src/get_two_nums.cpp b/task_01/src/get_two_nums.cpp new file mode 100644 index 00000000..ce5cb802 --- /dev/null +++ b/task_01/src/get_two_nums.cpp @@ -0,0 +1,20 @@ +#include "get_two_nums.hpp" + +std::pair GetTwoNums(long long number, + std::vector nums) { + if (nums.size() <= 1) { + throw std::length_error("The array size must be greater than 1."); + } + size_t left = 0; + size_t right = nums.size() - 1; + while (left != right) { + if (nums[left] + nums[right] == number) + return {nums[left], nums[right]}; + else if (nums[left] + nums[right] < number) + left++; + else if (nums[left] + nums[right] > number) + right--; + } + throw std::logic_error( + "There are no two elements, which add up to a given number."); +} diff --git a/task_01/src/get_two_nums.hpp b/task_01/src/get_two_nums.hpp new file mode 100644 index 00000000..5c1e6383 --- /dev/null +++ b/task_01/src/get_two_nums.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include +#include + +std::pair GetTwoNums(long long number, + std::vector nums); diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index 0e4393ba..9effade2 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -1,3 +1,44 @@ #include +#include +#include -int main() { return 0; } +#include "get_two_nums.hpp" + +size_t GetSize() { + size_t length; + std::cout << "Enter a length of array: "; + std::cin >> length; + if (length <= 1) { + std::cout << "You need to enter a number greater than 1\n"; + GetSize(); + } + return length; +}; + +long long GetNumber() { + long long number; + std::cout << "Enter a number: "; + std::cin >> number; + return number; +}; + +std::vector GetArray(size_t length) { + std::vector nums; + std::cout << "Enter the array: "; + for (int i = 0; i < length; i++) { + int number; + std::cin >> number; + nums.push_back(number); + } + return nums; +} + +int main() { + long long number = GetNumber(); + size_t length = GetSize(); + std::vector nums = GetArray(length); + std::pair res = GetTwoNums(number, nums); + std::cout << "Two numbers, which add up to a given number: " << res.first + << ", " << res.second; + return 0; +} diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index ef5a86ae..98fc92aa 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -1,8 +1,82 @@ - #include -#include "topology_sort.hpp" +#include +#include +#include + +#include "get_two_nums.hpp" + +TEST(GetTwoNums, Test_1) { + ASSERT_EQ(GetTwoNums(15, std::vector{5, 10, 15, 20, 25}), + (std::pair{5, 10})); +} + +TEST(GetTwoNums, Test_2) { + ASSERT_EQ( + GetTwoNums(18, std::vector{1, 2, 3, 5, 7, 8, 10, 14, 19, 25}), + (std::pair{8, 10})); +} + +TEST(GetTwoNums, Test_3) { + ASSERT_EQ(GetTwoNums(-20, std::vector{-100, -98, -72, -54, -11, 0, + 10, 20, 34, 60}), + (std::pair{-54, 34})); +} + +TEST(GetTwoNums, Test_4) { + ASSERT_EQ( + GetTwoNums(-6, std::vector{-120, -100, -84, -20, -11, -5, -1}), + (std::pair{-5, -1})); +} + +TEST(GetTwoNums, Test_5) { + ASSERT_EQ( + GetTwoNums(21000000000, + std::vector{1000000000, 2000000000, 4000000000, + 8000000000, 11000000000, 13000000000}), + (std::pair{8000000000, 13000000000})); +} + +TEST(GetTwoNums, Test_6) { + ASSERT_EQ( + GetTwoNums( + 11, std::vector{0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, + 6, 7, 8, 9, 9, 9, 12, 13, 15, 15, 16, 17}), + (std::pair{2, 9})); +} + +TEST(GetTwoNums, Test_7) { + ASSERT_EQ(GetTwoNums(100000000000000, + std::vector{ + 10000000000000, 20000000000000, 30000000000000, + 30000000000000, 50000000000000, 50000000000000, + 60000000000000, 110000000000000, 110000000000000, + 110000000000000}), + (std::pair{50000000000000, 50000000000000})); +} + +TEST(GetTwoNums, Test_8) { + ASSERT_EQ(GetTwoNums(84, std::vector{-12, -6, -4, 1, 23, 25, 26, + 33, 38, 46, 52, 58, 64, 69, + 76, 82, 97, 101}), + (std::pair{26, 58})); +} + +TEST(GetTwoNums, Test_9) { + EXPECT_THROW(GetTwoNums(2, std::vector{2}), std::length_error); +} + +TEST(GetTwoNums, Test_10) { + EXPECT_THROW(GetTwoNums(100, std::vector{}), std::length_error); +} + +TEST(GetTwoNums, Test_11) { + EXPECT_THROW(GetTwoNums(5, std::vector{1, 2, 5, 7, 9, 11, 23, 55}), + std::logic_error); +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(GetTwoNums, Test_12) { + EXPECT_THROW(GetTwoNums(-10, std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14}), + std::logic_error); } 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..28f23bb9 100644 --- a/task_02/src/main.cpp +++ b/task_02/src/main.cpp @@ -1,3 +1,8 @@ #include -int main() { return 0; } +#include "stack.hpp" + +int main() { + MinStack stack; + stack.Push(1); +} 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..5c7ea37f 100644 --- a/task_02/src/stack.hpp +++ b/task_02/src/stack.hpp @@ -1,23 +1,81 @@ #pragma once -#include -#include +#include +#include +template +struct StackElem { + explicit StackElem(T value, const std::shared_ptr& prev) + : value_{value}, prev_{prev} {} + + T value_; + std::shared_ptr prev_; +}; + +template class Stack { public: - void Push(int value); - int Pop(); + explicit Stack() : top_{nullptr} {} + + void Push(T value); + T Pop(); + + T Top() const { + if (IsEmpty()) throw std::out_of_range("Stack is empty!"); + return top_->value_; + } + size_t Size() const { return size_; } + bool IsEmpty() const { return size_ == 0; } private: - std::stack data_; + std::shared_ptr> top_; + size_t size_ = 0; }; +template class MinStack { public: - void Push(int value); - int Pop(); - int GetMin(); + explicit MinStack() : data_(), mins_data_() {} + + void Push(T value); + T Pop(); + + T Top() const { return data_.Top(); } + T GetMin() const { return mins_data_.Top(); } + size_t Size() const { return data_.Size(); } + bool IsEmpty() const { return data_.IsEmpty(); } private: - std::vector data_; + Stack data_; + Stack mins_data_; }; + +template +void Stack::Push(T value) { + top_ = std::make_shared>(value, top_); + size_++; +} + +template +T Stack::Pop() { + if (IsEmpty()) throw std::out_of_range("Stack is empty!"); + T res = top_->value_; + top_ = std::move(top_->prev_); + size_--; + return res; +} + +template +void MinStack::Push(T value) { + data_.Push(value); + if (mins_data_.Size() > 0 && mins_data_.Top() < value) + mins_data_.Push(mins_data_.Top()); + else + mins_data_.Push(value); +} + +template +T MinStack::Pop() { + mins_data_.Pop(); + return data_.Pop(); +} \ No newline at end of file diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 54e7ce90..6fdce571 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -6,7 +6,7 @@ #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 +22,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 +39,19 @@ TEST(MinStackTest, Simple) { 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(StackTest, Empty) { + Stack stack; + EXPECT_THROW(stack.Pop(), std::out_of_range); +} + +TEST(MinStackTest, Empty) { + MinStack stack; + EXPECT_THROW(stack.Pop(), std::out_of_range); +} + +TEST(MinStackTest, Empty_2) { + MinStack stack; + EXPECT_THROW(stack.GetMin(), std::out_of_range); +} diff --git a/task_03/src/temperature.cpp b/task_03/src/temperature.cpp new file mode 100644 index 00000000..29ce0136 --- /dev/null +++ b/task_03/src/temperature.cpp @@ -0,0 +1,25 @@ +#include "temperature.hpp" + +vector DaysBeforeWarming(vector temperatures) { + vector days(temperatures.size()); + + if (temperatures.empty()) return days; + + for (size_t i = 0; i < temperatures.size() - 1; i++) { + // Если у предыдущего дня температура больше и кол-во дней до потепления + // больше 1, то для текущего дня можно не считать кол-во дней + if (i > 0 && temperatures[i - 1] > temperatures[i] && days[i - 1] > 1) + days[i] = temperatures[i - 1] - 1; + // Иначе считаем кол-во дней по-честному + else { + for (size_t j = i; j < temperatures.size(); j++) { + if (temperatures[j] > temperatures[i]) break; + days[i]++; + } + // Если мы вышли из цикла без break, значит потепления не было на + // протяжении всех дней + if (days[i] == temperatures.size() - i) days[i] = 0; + } + } + return days; +} \ 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..36c8677f --- /dev/null +++ b/task_03/src/temperature.hpp @@ -0,0 +1,5 @@ +#pragma once +#include +using namespace std; + +vector DaysBeforeWarming(vector temperatures); \ No newline at end of file diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86ae..0ccb600a 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,8 +1,44 @@ #include -#include "topology_sort.hpp" +#include "temperature.hpp" -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(DaysBeforeWarming, Test_1) { + ASSERT_EQ(DaysBeforeWarming(vector{}), vector{}); } + +TEST(DaysBeforeWarming, Test_2) { + ASSERT_EQ(DaysBeforeWarming(vector{1}), vector{0}); +} + +TEST(DaysBeforeWarming, Test_3) { + ASSERT_EQ(DaysBeforeWarming(vector{1, 2}), (vector{1, 0})); +} + +TEST(DaysBeforeWarming, Test_4) { + ASSERT_EQ(DaysBeforeWarming(vector{1, 2, 3, 4, 5, 6}), + (vector{1, 1, 1, 1, 1, 0})); +} + +TEST(DaysBeforeWarming, Test_5) { + ASSERT_EQ(DaysBeforeWarming(vector{6, 5, 4, 3, 2, 1}), + (vector{0, 0, 0, 0, 0, 0})); +} + +TEST(DaysBeforeWarming, Test_6) { + ASSERT_EQ(DaysBeforeWarming(vector{-6, -5, -4, -3, -2, -1}), + (vector{1, 1, 1, 1, 1, 0})); +} + +TEST(DaysBeforeWarming, Test_7) { + ASSERT_EQ(DaysBeforeWarming(vector{-1, 0, 2, -1, -5, 3, 6, 1}), + (vector{1, 1, 3, 1, 1, 1, 0, 0})); +} + +TEST(DaysBeforeWarming, Test_8) { + ASSERT_EQ(DaysBeforeWarming(vector{ + -10, 5, -3, 8, -20, 12, 17, -15, 6, -7, 25, -30, 19, + 4, -2, 11, -18, 14, -5, 9, -13, 22, -35, 16, -40}), + (vector{1, 2, 4, 2, 7, 1, 4, 16, 2, 5, 0, 1, 9, + 18, 3, 2, 10, 4, 13, 2, 8, 0, 1, 0, 0})); +} \ 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/main.cpp b/task_04/src/main.cpp deleted file mode 100644 index 0e4393ba..00000000 --- a/task_04/src/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int main() { return 0; } diff --git a/task_04/src/max_heap.hpp b/task_04/src/max_heap.hpp new file mode 100644 index 00000000..b77fa512 --- /dev/null +++ b/task_04/src/max_heap.hpp @@ -0,0 +1,65 @@ +#include +#include +#include + +template +class MaxHeap { + public: + MaxHeap() = default; + + MaxHeap(const std::vector& data) { + for (auto& elem : data) Add(elem); + } + + MaxHeap(const std::initializer_list& data) { + for (const auto& elem : data) Add(elem); + } + + T ExtractMax() { + if (Empty()) throw std::out_of_range("Empty heap!"); + + T max = data_[0]; + std::swap(data_[0], data_[Size() - 1]); + data_.pop_back(); + SiftDown(0); + return max; + } + + void Add(T elem) { + data_.push_back(elem); + SiftUp(); + } + + size_t Size() const { return data_.size(); } + + bool Empty() const { 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 max = IndexLeftChild(index); + if (IndexRightChild(index) < Size() && + data_[IndexRightChild(index)] > data_[max]) + max = IndexRightChild(index); + if (data_[index] > data_[max]) break; + std::swap(data_[index], data_[max]); + index = max; + } + } + + 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); + } + } +}; diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 5e11617e..8ecbb041 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,67 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include + +#include "max_heap.hpp" + +using namespace std; + +TEST(MaxHeap_Test, Test_1) { + MaxHeap heap; + EXPECT_THROW(heap.ExtractMax(), out_of_range); + ASSERT_EQ(heap.Size(), 0); + EXPECT_TRUE(heap.Empty()); +} + +TEST(MaxHeap_Test, Test_2) { + MaxHeap heap{1, 6, 3, 8, 2}; + ASSERT_EQ(heap.ExtractMax(), 8); + ASSERT_EQ(heap.ExtractMax(), 6); + ASSERT_EQ(heap.ExtractMax(), 3); + ASSERT_EQ(heap.ExtractMax(), 2); + ASSERT_EQ(heap.ExtractMax(), 1); + EXPECT_THROW(heap.ExtractMax(), out_of_range); +} + +TEST(MaxHeap_Test, Test_3) { + vector data{1, 4, 3, 5, 0, 6}; + MaxHeap heap(data); + ASSERT_EQ(heap.ExtractMax(), 6); + ASSERT_EQ(heap.ExtractMax(), 5); + ASSERT_EQ(heap.ExtractMax(), 4); + ASSERT_EQ(heap.ExtractMax(), 3); + ASSERT_EQ(heap.ExtractMax(), 1); + ASSERT_EQ(heap.ExtractMax(), 0); + heap.Add(5); + heap.Add(7); + ASSERT_EQ(heap.ExtractMax(), 7); + ASSERT_EQ(heap.ExtractMax(), 5); +} + +TEST(MaxHeap_Test, Test_4) { + MaxHeap heap; + heap.Add(1); + heap.Add(2); + heap.Add(3); + heap.Add(4); + heap.Add(5); + ASSERT_EQ(heap.ExtractMax(), 5); + ASSERT_EQ(heap.ExtractMax(), 4); + ASSERT_EQ(heap.ExtractMax(), 3); + ASSERT_EQ(heap.ExtractMax(), 2); + ASSERT_EQ(heap.ExtractMax(), 1); +} + +TEST(MaxHeap_Test, Test_5) { + MaxHeap heap; + EXPECT_TRUE(heap.Empty()); + heap.Add(6); + ASSERT_EQ(heap.Size(), 1); + heap.Add(6); + heap.Add(6); + ASSERT_EQ(heap.Size(), 3); + ASSERT_EQ(heap.ExtractMax(), 6); + ASSERT_EQ(heap.ExtractMax(), 6); + ASSERT_EQ(heap.ExtractMax(), 6); } diff --git a/task_05/src/main.cpp b/task_05/src/main.cpp deleted file mode 100644 index 0e4393ba..00000000 --- a/task_05/src/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int main() { return 0; } diff --git a/task_05/src/merge_sort.hpp b/task_05/src/merge_sort.hpp new file mode 100644 index 00000000..7389f850 --- /dev/null +++ b/task_05/src/merge_sort.hpp @@ -0,0 +1,48 @@ +#include +#include +using namespace std; + +template +void Merge(T* begin, T* middle, T* end) { + std::vector sorted_array; + + T* begin_copy = begin; + T* middle_copy = middle; + + while ((begin < middle_copy) || (middle < end)) { + if ((begin < middle_copy) && (middle < end)) { + if (*begin <= *middle) { + sorted_array.push_back(*begin); + ++begin; + } else { + sorted_array.push_back(*middle); + ++middle; + } + } else { + if (begin < middle_copy) { + sorted_array.push_back(*begin); + ++begin; + } else { + sorted_array.push_back(*middle); + ++middle; + } + } + } + size_t index = 0; + for (T* i = begin_copy; i < end; i++) { + *i = sorted_array[index]; + index++; + } +} + +template +void MergeSort(T* begin, T* end) { + if ((begin == end) || (end - begin < 2)) return; + + T* middle = begin + (end - begin) / 2; + + MergeSort(begin, middle); + MergeSort(middle, end); + + Merge(begin, middle, end); +} diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp deleted file mode 100644 index 5e11617e..00000000 --- a/task_05/src/test.cpp +++ /dev/null @@ -1,6 +0,0 @@ - -#include - -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} diff --git a/task_05/src/test_merge_sort.cpp b/task_05/src/test_merge_sort.cpp new file mode 100644 index 00000000..ec26303e --- /dev/null +++ b/task_05/src/test_merge_sort.cpp @@ -0,0 +1,126 @@ +#include + +#include +#include +#include +#include + +#include "merge_sort.hpp" + +TEST(MergeSort, Test_1) { + vector data{2, 1, 3, 7, 5, 6, 4}; + int* begin = &(data[0]); + int* end = &(data[data.size()]); + MergeSort(begin, end); + ASSERT_EQ(data, (vector{1, 2, 3, 4, 5, 6, 7})); +} + +TEST(MergeSort, Test_2) { + vector data{}; + int* begin = &(data[0]); + int* end = &(data[data.size()]); + MergeSort(begin, end); + ASSERT_EQ(data, (vector{})); +} + +TEST(MergeSort, Test_3) { + vector data{1}; + int* begin = &(data[0]); + int* end = &(data[data.size()]); + MergeSort(begin, end); + ASSERT_EQ(data, (vector{1})); +} + +TEST(MergeSort, Test_4) { + vector data{2, 1}; + int* begin = &(data[0]); + int* end = &(data[data.size()]); + MergeSort(begin, end); + ASSERT_EQ(data, (vector{1, 2})); +} + +TEST(MergeSort, Test_5) { + vector data{20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + int* begin = &(data[0]); + int* end = &(data[data.size()]); + MergeSort(begin, end); + ASSERT_EQ(data, (vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20})); +} + +TEST(MergeSort, Test_6) { + vector data{3.456, 7.890, 8.976, 4.567, 6.543, 5.432, 2.109, 9.012, + 1.234, 6.789, 0.987, 1.234, 5.678, 4.321, 9.876, 8.765, + 2.345, 7.654, 0.123, 3.210, 4.321, 1.234, 5.432, 9.876, + 6.543, 8.765, 3.456, 7.890, 2.109, 0.987, 6.789, 4.567, + 8.976, 2.345, 9.012, 7.654, 5.678, 3.210, 0.123}; + + vector sorted_data = data; + std::sort(sorted_data.begin(), sorted_data.end()); + + double* begin = &(data[0]); + double* end = &(data[data.size()]); + MergeSort(begin, end); + + ASSERT_EQ(data, sorted_data); +} + +TEST(MergeSort, Test_7) { + vector data{3, 5, 3, 2, 4, 5, 7, 3, 3, 2, 1, 4, 9, 7, 5}; + + vector sorted_data = data; + std::sort(sorted_data.begin(), sorted_data.end()); + + int* begin = &(data[0]); + int* end = &(data[data.size()]); + MergeSort(begin, end); + + ASSERT_EQ(data, sorted_data); +} + +TEST(MergeSort, Test_8) { + vector data{3, 5, 3, 2, 4, 5, 7, 3, 3, 2, 1, 4, 9, 7, 5}; + + vector sorted_data = data; + std::sort(sorted_data.begin(), sorted_data.end()); + + int* begin = &(data[0]); + int* end = &(data[data.size()]); + MergeSort(begin, end); + + ASSERT_EQ(data, sorted_data); +} + +TEST(MergeSort, Test_9) { + vector data{18, 5, 26, 21, 7, 25, 19, 16, 9, 3, 8, 13, 27, + 14, 2, 1, 23, 6, 29, 17, 4, 15, 11, 28, 12}; + + vector sorted_data = data; + std::sort(sorted_data.begin(), sorted_data.begin() + 12); + + int* begin = &(data[0]); + int* end = &(data[12]); + MergeSort(begin, end); + + ASSERT_EQ(data, sorted_data); +} + +TEST(MergeSort, Test_10) { + vector data{1, 2, 3, 4, 5, 1, 6, 7, 8, 9, 2, 10, 11, + 12, 13, 14, 3, 15, 16, 17, 4, 18, 19, 20, 5, 21, + 22, 23, 24, 1, 25, 26, 27, 28, 29, 2, 30, 31, 32, + 33, 34, 35, 3, 36, 37, 38, 39, 40, 4, 41, 42, 43, + 44, 45, 5, 46, 47, 48, 49, 50, 1, 51, 52, 53, 54, + 55, 2, 56, 57, 58, 59, 60, 3, 61, 62, 63, 64, 65, + 4, 66, 67, 68, 69, 70, 5, 71, 72, 73, 74, 75, 1}; + + vector sorted_data = data; + std::sort(sorted_data.begin(), sorted_data.end()); + + int* begin = &(data[0]); + int* end = &(data[data.size()]); + MergeSort(begin, end); + + ASSERT_EQ(data, sorted_data); +} \ No newline at end of file diff --git a/task_06/src/find_ordinal_statistic.hpp b/task_06/src/find_ordinal_statistic.hpp new file mode 100644 index 00000000..00804b6a --- /dev/null +++ b/task_06/src/find_ordinal_statistic.hpp @@ -0,0 +1,34 @@ +#include +#include +using namespace std; + +template +T FindOrdinalStatistic(vector data, size_t n) { + if (data.empty()) throw logic_error("An array is empty!"); + if (n > data.size() || n <= 0) + throw logic_error("Incorrect ordinal statistic!"); + + if (data.size() == 1) return data[0]; + + size_t p = rand() % data.size(); + T pivot = data[p]; + data.erase(data.begin() + p); + // Левая часть содержит элементы, которые меньше pivot'а, а правая - + // которые больше + vector left_part{pivot}, right_part; + + for (auto elem : data) { + if (elem < pivot) + left_part.push_back(elem); + else if (elem > pivot) + right_part.push_back(elem); + // Мы не добавляем дубликаты, а просто уменьшаем порядковую статистику + else if (n != 1) + n--; + } + + if (n <= left_part.size()) + return FindOrdinalStatistic(left_part, n); + else + return FindOrdinalStatistic(right_part, n - left_part.size()); +} \ No newline at end of file diff --git a/task_06/src/main.cpp b/task_06/src/main.cpp deleted file mode 100644 index 0e4393ba..00000000 --- a/task_06/src/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int main() { return 0; } diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617e..987a9de4 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,65 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "find_ordinal_statistic.hpp" + +TEST(FindOrdinalStatistic, Test_1) { + vector v{1, 2, 3, 4, 5, 6}; + ASSERT_EQ(FindOrdinalStatistic(v, 5), 5); +} + +TEST(FindOrdinalStatistic, Test_2) { + vector v{1}; + ASSERT_EQ(FindOrdinalStatistic(v, 1), 1); +} + +TEST(FindOrdinalStatistic, Test_3) { + vector v{3, 1, 2}; + ASSERT_EQ(FindOrdinalStatistic(v, 2), 2); +} + +TEST(FindOrdinalStatistic, Test_4) { + vector v{}; + EXPECT_THROW(FindOrdinalStatistic(v, 0), std::logic_error); +} + +TEST(FindOrdinalStatistic, Test_5) { + vector v{8, 4}; + EXPECT_THROW(FindOrdinalStatistic(v, 3), std::logic_error); } + +TEST(FindOrdinalStatistic, Test_6) { + vector v{8, 4}; + ASSERT_EQ(FindOrdinalStatistic(v, 1), 4); +} + +TEST(FindOrdinalStatistic, Test_7) { + vector v{2, 4, 6, 2, 2}; + ASSERT_EQ(FindOrdinalStatistic(v, 4), 4); +} + +TEST(FindOrdinalStatistic, Test_8) { + vector v{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + ASSERT_EQ(FindOrdinalStatistic(v, 7), 1); +} + +TEST(FindOrdinalStatistic, Test_9) { + vector v{46, 58, 77, 16, 26, 36, 95, 80, 74, 39, 68, 72, 60, 61, 23, + 30, 52, 9, 78, 31, 5, 55, 27, 62, 73, 57, 79, 18, 11, 54, + 51, 90, 38, 6, 21, 29, 93, 94, 81, 22, 17, 71, 7, 76, 44, + 99, 84, 82, 85, 19, 91, 63, 87, 37, 25, 14, 47, 100, 86, 66, + 88, 13, 35, 2, 4, 10, 34, 20, 69, 59, 33, 45, 32, 98, 49, + 56, 83, 12, 40, 65, 1, 53, 41, 50, 96, 89, 8, 3, 75, 42, + 28, 67, 70, 48, 92, 43, 97, 24, 15, 64}; + ASSERT_EQ(FindOrdinalStatistic(v, 100), 100); +} + +TEST(FindOrdinalStatistic, Test_10) { + vector v{46, 58, 77, 16, 26, 36, 95, 80, 74, 39, 68, 72, 60, 61, 23, + 30, 52, 9, 78, 31, 5, 55, 27, 62, 73, 57, 79, 18, 11, 54, + 51, 90, 38, 6, 21, 29, 93, 94, 81, 22, 17, 71, 7, 76, 44, + 99, 84, 82, 85, 19, 91, 63, 87, 37, 25, 14, 47, 100, 86, 66, + 88, 13, 35, 2, 4, 10, 34, 20, 69, 59, 33, 45, 32, 98, 49, + 56, 83, 12, 40, 65, 1, 53, 41, 50, 96, 89, 8, 3, 75, 42, + 28, 67, 70, 48, 92, 43, 97, 24, 15, 64}; + ASSERT_EQ(FindOrdinalStatistic(v, 24), 24); +} \ 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..004e0c93 --- /dev/null +++ b/task_07/src/avl_tree.hpp @@ -0,0 +1,166 @@ +#include +#include +#include + +template +struct Node { + explicit Node(T k) : key{k}, left{nullptr}, right{nullptr}, height{1} {} + T key; + size_t height; + Node* left; + Node* right; +}; + +template +class AVLTree { + public: + AVLTree() : root_{nullptr} {} + + void Insert(T value); + + void Remove(T value); + + bool Contains(T value) const; + + private: + Node* root_; + + Node* Insert(Node* node, T value); + + Node* Remove(Node* node, T value); + + bool Contains(const Node* node, T value) const; + + Node* Balance(Node* node); + + Node* FindMin(Node* node) const; + + Node* RemoveMin(Node* node); + + Node* LeftRotate(Node* node); + + Node* RightRotate(Node* node); + + size_t Height(Node* node) const; + + void UpdateHeight(Node* node); + + int Difference(Node* node) const; +}; + +template +void AVLTree::Insert(T value) { + root_ = Insert(root_, value); +} + +template +void AVLTree::Remove(T value) { + root_ = Remove(root_, value); +} + +template +bool AVLTree::Contains(T value) const { + return Contains(root_, value); +} + +template +Node* AVLTree::Insert(Node* node, T value) { + if (!node) return new Node(value); + if (value < node->key) + node->left = Insert(node->left, value); + else if (value > node->key) + node->right = Insert(node->right, value); + return Balance(node); +} + +template +Node* AVLTree::Remove(Node* node, T value) { + if (!node) return nullptr; + if (value < node->key) + node->left = Remove(node->left, value); + else if (value > node->key) + node->right = Remove(node->right, value); + else if (value == node->key) { + Node* new_node_1 = node->left; + Node* new_node_2 = node->right; + delete node; + 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); + } + return Balance(node); +} + +template +bool AVLTree::Contains(const Node* node, T 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; +} + +template +Node* AVLTree::Balance(Node* node) { + UpdateHeight(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; +} + +template +Node* AVLTree::FindMin(Node* node) const { + if (!node->left) return node; + return FindMin(node->left); +} + +template +Node* AVLTree::RemoveMin(Node* node) { + if (!node->left) return node->right; + node->left = RemoveMin(node->left); + return Balance(node); +} + +template +Node* AVLTree::LeftRotate(Node* node) { + Node* new_node = node->right; + node->right = new_node->left; + new_node->left = node; + UpdateHeight(node); + UpdateHeight(new_node); + return new_node; +} + +template +Node* AVLTree::RightRotate(Node* node) { + Node* new_node = node->left; + node->left = new_node->right; + new_node->right = node; + UpdateHeight(node); + UpdateHeight(new_node); + return new_node; +} + +template +size_t AVLTree::Height(Node* node) const { + return node ? node->height : 0; +} + +template +void AVLTree::UpdateHeight(Node* node) { + size_t left_height = Height(node->left); + size_t right_height = Height(node->right); + node->height = std::max(left_height, right_height) + 1; +} + +template +int AVLTree::Difference(Node* node) const { + return Height(node->right) - Height(node->left); +} diff --git a/task_07/src/main.cpp b/task_07/src/main.cpp deleted file mode 100644 index 0e4393ba..00000000 --- a/task_07/src/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int main() { return 0; } diff --git a/task_07/src/test.cpp b/task_07/src/test.cpp index 5e11617e..95f7fdc4 100644 --- a/task_07/src/test.cpp +++ b/task_07/src/test.cpp @@ -1,6 +1,62 @@ - +#include #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "avl_tree.hpp" + +TEST(AVLTree_Test, Test_1) { + AVLTree tree; + + tree.Insert(1); + ASSERT_TRUE(tree.Contains(1)); + tree.Insert(3); + ASSERT_TRUE(tree.Contains(3)); + ASSERT_FALSE(tree.Contains(5)); +} + +TEST(AVLTree_Test, Test_2) { + AVLTree tree; + + tree.Insert(20); + ASSERT_TRUE(tree.Contains(20)); + tree.Remove(20); + ASSERT_FALSE(tree.Contains(20)); +} + +TEST(AVLTree_Test, Test_3) { + AVLTree tree; + + tree.Insert(10); + tree.Remove(30); + ASSERT_TRUE(tree.Contains(10)); + ASSERT_FALSE(tree.Contains(30)); + tree.Remove(10); + ASSERT_FALSE(tree.Contains(10)); +} + +TEST(AVLTree_Test, Test_4) { + AVLTree tree; + + tree.Insert(60000000); + tree.Insert(40000000); + tree.Insert(20000000); + ASSERT_TRUE(tree.Contains(20000000)); + ASSERT_TRUE(tree.Contains(40000000)); + ASSERT_TRUE(tree.Contains(60000000)); + ASSERT_FALSE(tree.Contains(10000000)); + ASSERT_FALSE(tree.Contains(30000000)); + ASSERT_FALSE(tree.Contains(50000000)); +} + +TEST(AVLTree_Test, Test_5) { + AVLTree tree; + + tree.Insert(10000000); + tree.Insert(30000000); + tree.Insert(50000000); + ASSERT_TRUE(tree.Contains(10000000)); + ASSERT_TRUE(tree.Contains(30000000)); + ASSERT_TRUE(tree.Contains(50000000)); + ASSERT_FALSE(tree.Contains(20000000)); + ASSERT_FALSE(tree.Contains(40000000)); + ASSERT_FALSE(tree.Contains(60000000)); } diff --git a/task_08/src/hash_table.hpp b/task_08/src/hash_table.hpp new file mode 100644 index 00000000..68f1bc33 --- /dev/null +++ b/task_08/src/hash_table.hpp @@ -0,0 +1,145 @@ +#pragma once +#include + +#include +#include +#include + +using namespace std; + +template +class HashTable { + public: + HashTable() : size_{0}, states_size_{0}, buffer_size_{8} { + data_ = vector(buffer_size_); + states_ = vector(buffer_size_, State::Free); + } + + HashTable(const std::initializer_list &data) + : size_{data.size()}, states_size_{data.size()}, buffer_size_{8} { + data_ = data; + states_ = vector(buffer_size_, State::Occupied); + } + + void Insert(T value); + + void Remove(T value); + + bool Contains(T value); + + void Clear(); + + size_t Size() const { return size_; } + + bool Empty() const { return size_ == 0; } + + private: + constexpr static const double hash_coef = 0.74920592; + constexpr static const double rehash_coef = 0.6; + + enum class State { Deleted, Occupied, Free }; + + size_t buffer_size_; + size_t size_; + size_t states_size_; + + vector data_; + vector states_; + + size_t FirstHashFunction(T key); + size_t SecondHashFunction(T key); + + void Resize(); + + void Rehash(); +}; + +template +void HashTable::Insert(T value) { + size_t hash = FirstHashFunction(value) % buffer_size_; + size_t counter = 0; + + while (states_[hash] == State::Occupied) { + if (data_[hash] == value) return; + counter++; + hash = (FirstHashFunction(value) + counter * SecondHashFunction(value)) % + buffer_size_; + } + + data_[hash] = value; + states_[hash] = State::Occupied; + states_size_++; + size_++; + + double states_coefficient = double(states_size_) / double(buffer_size_); + if (states_coefficient >= rehash_coef) Rehash(); +} + +template +void HashTable::Remove(T value) { + size_t hash = FirstHashFunction(value) % buffer_size_; + size_t counter = 0; + + while (states_[hash] != State::Free) { + if (data_[hash] == value && states_[hash] == State::Occupied) { + states_[hash] = State::Deleted; + size_--; + break; + } + if (data_[hash] == value && states_[hash] == State::Deleted) break; + + counter++; + hash = (FirstHashFunction(value) + SecondHashFunction(value) * counter) % + buffer_size_; + } +} + +template +bool HashTable::Contains(T value) { + size_t hash = FirstHashFunction(value) % buffer_size_; + size_t counter = 0; + + while (states_[hash] != State::Free) { + if (data_[hash] == value && states_[hash] == State::Occupied) return true; + counter++; + hash = (FirstHashFunction(value) + counter * SecondHashFunction(value)) % + buffer_size_; + } + return false; +} + +template +void HashTable::Clear() { + states_size_ = 0; + size_ = 0; + for (auto &cell : states_) cell = State::Free; +} + +template +size_t HashTable::FirstHashFunction(T key) { + return floor(buffer_size_ * + ((double(key) * hash_coef) - floor(double(key) * hash_coef))); +} + +template +size_t HashTable::SecondHashFunction(T key) { + return int(key * buffer_size_ - 1) % (buffer_size_); +} + +template +void HashTable::Resize() { + buffer_size_ *= 2; + data_.resize(buffer_size_); + states_.resize(buffer_size_); +} + +template +void HashTable::Rehash() { + vector sub_data; + for (size_t i = 0; i < buffer_size_; i++) + if (states_[i] == State::Occupied) sub_data.push_back(data_[i]); + + Resize(); + Clear(); + for (auto &elem : sub_data) Insert(elem); +} diff --git a/task_08/src/main.cpp b/task_08/src/main.cpp deleted file mode 100644 index 0e4393ba..00000000 --- a/task_08/src/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int main() { return 0; } diff --git a/task_08/src/test.cpp b/task_08/src/test.cpp index 5e11617e..26261751 100644 --- a/task_08/src/test.cpp +++ b/task_08/src/test.cpp @@ -1,6 +1,37 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include + +TEST(HashTable_Test, Test_1) { + HashTable table; + table.Insert(1); + ASSERT_TRUE(table.Contains(1)); + ASSERT_FALSE(table.Contains(2)); + table.Remove(1); + ASSERT_FALSE(table.Contains(1)); +} + +TEST(HashTable_Test, Test_2) { + HashTable table; + table.Insert(2); + table.Insert(5); + table.Insert(7); + ASSERT_TRUE(table.Contains(2)); + ASSERT_TRUE(table.Contains(5)); + ASSERT_TRUE(table.Contains(7)); + ASSERT_EQ(table.Size(), 3); + table.Clear(); + ASSERT_TRUE(table.Empty()); +} + +TEST(HashTable_Test, Test_3) { + HashTable table; + table.Insert(10); + table.Insert(20); + table.Insert(30); + ASSERT_TRUE(table.Contains(10)); + ASSERT_FALSE(table.Contains(40)); + table.Clear(); + ASSERT_EQ(table.Size(), 0); } diff --git a/task_09/src/main.cpp b/task_09/src/main.cpp deleted file mode 100644 index 0e4393ba..00000000 --- a/task_09/src/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int main() { return 0; } diff --git a/task_09/src/min_amount_of_coins.cpp b/task_09/src/min_amount_of_coins.cpp new file mode 100644 index 00000000..a20f94a7 --- /dev/null +++ b/task_09/src/min_amount_of_coins.cpp @@ -0,0 +1,14 @@ +#include "min_amount_of_coins.hpp" +#include + +unsigned MinAmountOfCoins(std::vector& coins, unsigned amount) { + std::vector amounts(amount + 1, amount + 1); + amounts[0] = 0; + + for (size_t i = 1; i <= amount; ++i) + for (auto& coin : coins) + if (coin <= i) amounts[i] = std::min(amounts[i], amounts[i - coin] + 1); + + if (amounts[amount] > amount) throw std::logic_error("Impossible to collect amount from this set of coins!"); + return amounts[amount]; +} \ No newline at end of file diff --git a/task_09/src/min_amount_of_coins.hpp b/task_09/src/min_amount_of_coins.hpp new file mode 100644 index 00000000..a90fe831 --- /dev/null +++ b/task_09/src/min_amount_of_coins.hpp @@ -0,0 +1,6 @@ +#pragma once +#include +#include +#include + +unsigned MinAmountOfCoins(std::vector& coins, unsigned amount); \ No newline at end of file diff --git a/task_09/src/test.cpp b/task_09/src/test.cpp index 869094dd..350a1818 100644 --- a/task_09/src/test.cpp +++ b/task_09/src/test.cpp @@ -1,4 +1,39 @@ #include -TEST(TopologySort, Simple) { ASSERT_EQ(1, 1); } +#include +#include + +#include "min_amount_of_coins.hpp" + +using namespace std; + +TEST(MinAmountOfCoins, Test_1) { + vector coins{1, 2, 5, 10}; + ASSERT_EQ(MinAmountOfCoins(coins, 20), 2); +} + +TEST(MinAmountOfCoins, Test_2) { + vector coins{1, 2, 5, 10}; + ASSERT_EQ(MinAmountOfCoins(coins, 21), 3); +} + +TEST(MinAmountOfCoins, Test_3) { + vector coins{1, 3, 5, 7}; + ASSERT_EQ(MinAmountOfCoins(coins, 18), 4); +} + +TEST(MinAmountOfCoins, Test_4) { + vector coins{3, 5, 7}; + EXPECT_THROW(MinAmountOfCoins(coins, 2), std::logic_error); +} + +TEST(MinAmountOfCoins, Test_5) { + vector coins{1, 2, 4, 5}; + ASSERT_EQ(MinAmountOfCoins(coins, 8), 2); +} + +TEST(MinAmountOfCoins, Test_6) { + vector coins{1, 2, 5, 10}; + ASSERT_EQ(MinAmountOfCoins(coins, 28), 5); +} \ No newline at end of file