diff --git a/task_01/CMakeLists.txt b/task_01/CMakeLists.txt deleted file mode 100644 index 0e239848..00000000 --- a/task_01/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) -string(REPLACE " " "_" PROJECT_NAME ${PROJECT_NAME}) -project(${PROJECT_NAME} C CXX) - -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -file(GLOB_RECURSE source_list "src/*.cpp" "src/*.hpp") -file(GLOB_RECURSE lib_source_list "../lib/src/*.cpp" "../lib/src/*.hpp") -file(GLOB_RECURSE main_source_list "src/main.cpp") -file(GLOB_RECURSE test_source_list "src/*.cpp") -file(GLOB_RECURSE test_list "src/*test.cpp") - -list(REMOVE_ITEM test_source_list ${main_source_list}) -list(REMOVE_ITEM source_list ${test_list}) - -include_directories(${PROJECT_NAME} PUBLIC src) -include_directories(${PROJECT_NAME} PUBLIC ../lib/src) - -add_executable(${PROJECT_NAME} ${source_list}) -target_link_libraries(${PROJECT_NAME} PUBLIC Utils) - -# Locate GTest -enable_testing() -find_package(GTest REQUIRED) -include_directories(${GTEST_INCLUDE_DIRS}) - -# Link runTests with what we want to test and the GTest and pthread library -add_executable(${PROJECT_NAME}_tests ${test_source_list}) -target_link_libraries( - ${PROJECT_NAME}_tests - GTest::gtest_main - Utils -) - -include(GoogleTest) -gtest_discover_tests(${PROJECT_NAME}_tests) diff --git a/task_01/README.md b/task_01/README.md deleted file mode 100644 index 8ceb5d4e..00000000 --- a/task_01/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Задача 1 - -Дано целое число и отсортированый массив целых чисел, нужно найти 2 числа из массива которые в сумме дадут заданное число diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp deleted file mode 100644 index 0e4393ba..00000000 --- a/task_01/src/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include - -int main() { return 0; } diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp deleted file mode 100644 index ef5a86ae..00000000 --- a/task_01/src/test.cpp +++ /dev/null @@ -1,8 +0,0 @@ - -#include - -#include "topology_sort.hpp" - -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] -} 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/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..b9851975 100644 --- a/task_02/src/stack.hpp +++ b/task_02/src/stack.hpp @@ -1,23 +1,95 @@ #pragma once -#include -#include +#include +#include +template class Stack { public: - void Push(int value); - int Pop(); + explicit Stack() : top_(nullptr) {} + void Push(T data); + T Pop(); + T Top() const; + size_t Size() const; private: - std::stack data_; + struct StackNode { + T data_; + std::shared_ptr next_; + explicit StackNode(T data, const std::shared_ptr& next) + : data_(data), next_(next) {} + }; + size_t size_ = 0; + std::shared_ptr top_; }; +template class MinStack { public: - void Push(int value); - int Pop(); - int GetMin(); + explicit MinStack() : data_stack_(), minimums_stack_() {} + + void Push(T data); + T Pop(); + T Top() const; + T GetMin() const; + size_t Size() const; private: - std::vector data_; + Stack data_stack_; + Stack minimums_stack_; }; +template +void Stack::Push(T data) { + top_ = std::make_shared(data, top_); + size_++; +} + +template +T Stack::Pop() { + if (size_ == 0) throw std::out_of_range("Stack is empty"); + T removed_value = top_->data_; + top_ = std::move(top_->next_); + size_--; + return removed_value; +} + +template +T Stack::Top() const { + if (size_ == 0) throw std::out_of_range("Stack is empty"); + return top_->data_; +} + +template +size_t Stack::Size() const { + return size_; +} + +template +void MinStack::Push(T data) { + data_stack_.Push(data); + if (minimums_stack_.Size() > 0 && data > minimums_stack_.Top()) + minimums_stack_.Push(minimums_stack_.Top()); + else + minimums_stack_.Push(data); +} + +template +T MinStack::Pop() { + minimums_stack_.Pop(); + return data_stack_.Pop(); +} + +template +T MinStack::GetMin() const { + return minimums_stack_.Top(); +} + +template +size_t MinStack::Size() const { + return data_stack_.Size(); +} + +template +T MinStack::Top() const { + return data_stack_.Top(); +} \ No newline at end of file diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 54e7ce90..ddf10c13 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -1,42 +1,73 @@ - #include #include +#include #include "stack.hpp" -TEST(StackTest, Simple) { - Stack stack; - stack.Push(1); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] - stack.Push(1); // Stack [1] - stack.Push(2); // Stack [1, 2] - ASSERT_EQ(stack.Pop(), 2); // Stack [1] - stack.Push(3); // Stack [1, 3] - ASSERT_EQ(stack.Pop(), 3); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] +TEST(StackTest, PushAndPop) { + Stack stack; + stack.Push(1); + stack.Push(2); + stack.Push(3); + + ASSERT_EQ(stack.Size(), 3); + ASSERT_EQ(stack.Top(), 3); + ASSERT_EQ(stack.Pop(), 3); + ASSERT_EQ(stack.Size(), 2); + ASSERT_EQ(stack.Top(), 2); + ASSERT_EQ(stack.Pop(), 2); + ASSERT_EQ(stack.Size(), 1); + ASSERT_EQ(stack.Top(), 1); + ASSERT_EQ(stack.Pop(), 1); + ASSERT_EQ(stack.Size(), 0); } -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] +TEST(StackTest, PopFromEmptyStack) { + Stack stack; + ASSERT_THROW(stack.Pop(), std::out_of_range); + stack.Push(10); + stack.Pop(); + ASSERT_THROW(stack.Pop(), std::out_of_range); +} + +TEST(StackTest, TopFromEmptyStack) { + Stack stack; + ASSERT_THROW(stack.Top(), std::out_of_range); +} + +TEST(MinStackTest, PushAndPop) { + MinStack stack; + stack.Push(3); + stack.Push(2); + stack.Push(1); + stack.Push(0); + + ASSERT_EQ(stack.Size(), 4); + ASSERT_EQ(stack.Top(), 0); + ASSERT_EQ(stack.GetMin(), 0); + ASSERT_EQ(stack.Pop(), 0); + ASSERT_EQ(stack.Size(), 3); + ASSERT_EQ(stack.Top(), 1); ASSERT_EQ(stack.GetMin(), 1); - ASSERT_EQ(stack.Pop(), 3); // Stack [1] - ASSERT_EQ(stack.Pop(), 1); // Stack [] -} \ No newline at end of file + ASSERT_EQ(stack.Pop(), 1); + ASSERT_EQ(stack.Size(), 2); + ASSERT_EQ(stack.Top(), 2); + ASSERT_EQ(stack.GetMin(), 2); + ASSERT_EQ(stack.Pop(), 2); + ASSERT_EQ(stack.Size(), 1); + ASSERT_EQ(stack.Top(), 3); + ASSERT_EQ(stack.GetMin(), 3); + ASSERT_EQ(stack.Pop(), 3); + ASSERT_EQ(stack.Size(), 0); +} + +TEST(MinStackTest, TopFromEmptyStack) { + MinStack stack; + ASSERT_THROW(stack.Top(), std::out_of_range); +} + +TEST(MinStackTest, GetMinFromEmptyStack) { + MinStack stack; + ASSERT_THROW(stack.GetMin(), std::out_of_range); +} diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index ef5a86ae..5b474fe9 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,8 +1,33 @@ #include -#include "topology_sort.hpp" +#include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "warming_prediction.hpp" +TEST(warming_prediction, Simple) { + ASSERT_EQ(DoWarmingPrediction(std::vector{23, 29, 12, 16, 45, 10, -8, + -39, 35, 6, 4, -11}), + (std::vector{1, 3, 1, 1, 0, 3, 2, 1, 0, 0, 0, 0})); + + ASSERT_EQ(DoWarmingPrediction(std::vector{-32, -5, 34, -37, -48, -17, 33, + 27, 18, -36, 22, 32}), + (std::vector{1, 1, 0, 2, 1, 1, 0, 4, 2, 1, 1, 0})); + + ASSERT_EQ(DoWarmingPrediction(std::vector{34, -49, 7, -44, 25, -45, -29, + -14, 2, -30, 34, -36}), + (std::vector{0, 1, 2, 1, 6, 1, 1, 1, 2, 1, 0, 0})); + + ASSERT_EQ(DoWarmingPrediction(std::vector{}), + (std::vector{})); + + ASSERT_EQ( + DoWarmingPrediction(std::vector{32, 11, 11, 10, 9, 7, 5, 3, 1}), + (std::vector{0, 0, 0, 0, 0, 0, 0, 0, 0})); + + ASSERT_EQ(DoWarmingPrediction( + std::vector{4, 12, 8, 7, 9, 1, 11, 9, 9, 10, 11, 12}), + (std::vector{1, 0, 2, 1, 2, 1, 5, 2, 1, 1, 1, 0})); + + EXPECT_THROW(DoWarmingPrediction(std::vector{"1"}), + std::logic_error); } 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_03/src/warming_prediction.hpp b/task_03/src/warming_prediction.hpp new file mode 100644 index 00000000..cdb5bfd0 --- /dev/null +++ b/task_03/src/warming_prediction.hpp @@ -0,0 +1,26 @@ +#pragma once +#include +#include +#include + +template +std::vector DoWarmingPrediction( + const std::vector& temperature_data) { + if (!std::is_arithmetic::value) + throw std::logic_error("Invalid data type"); + std::stack unpredictable_days; + std::vector days_of_waiting(temperature_data.size()); + for (unsigned int current_day = 0; current_day != temperature_data.size(); + current_day++) { + while (!unpredictable_days.empty() && + temperature_data[current_day] > + temperature_data[unpredictable_days.top()]) { + unsigned int last_unpredictable_day = unpredictable_days.top(); + days_of_waiting[last_unpredictable_day] = + current_day - last_unpredictable_day; + unpredictable_days.pop(); + } + unpredictable_days.push(current_day); + } + return days_of_waiting; +} \ No newline at end of file diff --git a/task_04/src/heap.hpp b/task_04/src/heap.hpp new file mode 100644 index 00000000..c26d13af --- /dev/null +++ b/task_04/src/heap.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include +#include +#include + +template +class Heap { + public: + Heap() : heap_array_(std::vector{}){}; + explicit Heap(std::vector&& array) { + heap_array_ = std::move(array); + for (size_t node = heap_array_.size(); node > 0; --node) SiftDown(node); + } + + T Pop(); + + T Top() const; + + void Push(T value); + + bool Empty() const; + + size_t Size() const; + + private: + std::vector heap_array_; + + void SiftUp(size_t node_index); + + void SiftDown(size_t node_index); +}; + +template +bool Heap::Empty() const { + return (heap_array_.size() == 0); +} + +template +size_t Heap::Size() const { + return heap_array_.size(); +} + +template +void Heap::SiftUp(size_t node_index) { + if (node_index <= 0) return; + size_t parent_index = (node_index - 1) / 2; + if (heap_array_[node_index] < heap_array_[parent_index]) { + std::swap(heap_array_[node_index], heap_array_[parent_index]); + SiftUp(parent_index); + } +} + +template +void Heap::SiftDown(size_t node_index) { + size_t size = heap_array_.size(); + size_t left_child_index = 2 * node_index + 1; + size_t right_child_index = 2 * node_index + 2; + size_t smallest_child_index = node_index; + if (left_child_index < size && + heap_array_[left_child_index] < heap_array_[smallest_child_index]) + smallest_child_index = left_child_index; + if (right_child_index < size && + heap_array_[right_child_index] < heap_array_[smallest_child_index]) + smallest_child_index = right_child_index; + if (smallest_child_index != node_index) { + std::swap(heap_array_[smallest_child_index], heap_array_[node_index]); + SiftDown(smallest_child_index); + } +} + +template +void Heap::Push(T value) { + heap_array_.emplace_back(value); + SiftUp(heap_array_.size() - 1); +} + +template +T Heap::Top() const { + if (Empty()) throw std::runtime_error("Heap is empty"); + return heap_array_[0]; +} + +template +T Heap::Pop() { + T top = Top(); + std::swap(heap_array_[0], heap_array_.back()); + heap_array_.pop_back(); + SiftDown(0); + return top; +} \ No newline at end of file diff --git a/task_04/src/main.cpp b/task_04/src/main.cpp index 0e4393ba..9ec81e03 100644 --- a/task_04/src/main.cpp +++ b/task_04/src/main.cpp @@ -1,3 +1,3 @@ #include -int main() { return 0; } +int main() { return 0; } \ No newline at end of file diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 5e11617e..ae977f01 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,53 @@ #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include + +#include "heap.hpp" + +TEST(Heap, EmptyHeap) { + Heap empty_heap; + EXPECT_THROW(empty_heap.Top(), std::runtime_error); + EXPECT_THROW(empty_heap.Pop(), std::runtime_error); + ASSERT_EQ(empty_heap.Empty(), true); + ASSERT_EQ(empty_heap.Size(), 0); +} + +TEST(Heap, Simple) { + Heap heap; + heap.Push(10); + heap.Push(5); + heap.Push(15); + heap.Push(3); + + ASSERT_EQ(heap.Size(), 4); + ASSERT_EQ(heap.Top(), 3); + + ASSERT_EQ(heap.Pop(), 3); + ASSERT_EQ(heap.Pop(), 5); + + heap.Push(7); + ASSERT_EQ(heap.Pop(), 7); + ASSERT_EQ(heap.Pop(), 10); + ASSERT_EQ(heap.Pop(), 15); + + EXPECT_THROW(heap.Pop(), std::runtime_error); +} + +TEST(Heap, DuplicateData) { + Heap heap; + heap.Push(5); + heap.Push(10); + heap.Push(5); + + ASSERT_EQ(heap.Size(), 3); + + ASSERT_EQ(heap.Top(), 5); + ASSERT_EQ(heap.Pop(), 5); + + ASSERT_EQ(heap.Top(), 5); + ASSERT_EQ(heap.Pop(), 5); + + ASSERT_EQ(heap.Top(), 10); } diff --git a/task_05/src/quick_sort.hpp b/task_05/src/quick_sort.hpp new file mode 100644 index 00000000..354096b9 --- /dev/null +++ b/task_05/src/quick_sort.hpp @@ -0,0 +1,54 @@ +#include +#include + +// Function to perform Insertion Sort on a subarray from index 'begin' to 'end' +template +void InsertionSort(std::vector &array, int begin, int end) { + for (int i = begin + 1; i <= end; i++) { + for (int j = i; j > 0; --j) { + if (array[j - 1] > array[j]) + std::swap(array[j], array[j - 1]); + else + break; + } + } +} + +// Function to partition the array and return the pivot index +template +int Partition(std::vector &array, int begin, int end) { + int pivot_index = (rand() % (end - begin + 1)) + begin; + std::swap(array[pivot_index], array[end]); + T pivot = array[end]; + while (true) { + while (array[begin] < pivot) begin++; + while (array[end] > pivot) end--; + if (begin >= end) { + return end; + } + std::swap(array[begin++], array[end--]); + } +} + +// Function to perform Quick Sort on a subarray from index 'begin' to 'end' +template +void QuickSort(std::vector &array, int begin, int end) { + const int InsertionSortThreshold = 25; + while (begin < end) { + if (end - begin <= InsertionSortThreshold) { + InsertionSort(array, begin, + end); // Perform Insertion Sort if subarray size is small + return; + } + int pivot_index = Partition(array, begin, end); + if (pivot_index - begin < end - pivot_index) { + QuickSort(array, begin, + pivot_index); // Recursively sort the left subarray + begin = pivot_index + 1; + } else { + QuickSort(array, pivot_index + 1, + end); // Recursively sort the right subarray + end = pivot_index; + } + } +} diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617e..51960028 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,63 @@ #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include + +#include "quick_sort.hpp" + +TEST(quick_sort, EmptyArray) { + std::vector array = {}; + std::vector sorted_array = {}; + QuickSort(array, 0, int(array.size() - 1)); + ASSERT_EQ(array, sorted_array); } + +TEST(quick_sort, AlreadySortedArray) { + std::vector array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::vector sorted_array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + QuickSort(array, 0, int(array.size() - 1)); + ASSERT_EQ(array, sorted_array); +} + +TEST(quick_sort, ReverseSortedArray) { + std::vector array = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + std::vector sorted_array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + QuickSort(array, 0, int(array.size() - 1)); + ASSERT_EQ(array, sorted_array); +} + +TEST(quick_sort, SmallRandomArray) { + std::vector array = {-61, 20, -64, -39, 24, -91, 28, -69, -78, + 7, 16, -97, -12, 29, 8, -27, 50, -98, + -37, 42, -72, -19, -25, 23, 96}; + std::vector sorted_array = {-98, -97, -91, -78, -72, -69, -64, -61, -39, + -37, -27, -25, -19, -12, 7, 8, 16, 20, + 23, 24, 28, 29, 42, 50, 96}; + QuickSort(array, 0, int(array.size() - 1)); + ASSERT_EQ(array, sorted_array); +} + +TEST(quick_sort, LargeRandomArray) { + std::vector array = { + -141, -98, 477, -592, 76, -815, -826, 97, -178, -723, 814, -266, + 374, 602, 40, -191, -578, 858, 919, 785, -54, -706, 294, -187, + -239, -946, -8, -310, 305, -353, 405, 699, -767, 798, -727, -452, + 400, 67, -318, -814, 676, -515, 693, -848, -470, 334, -858, -576, + 953, 695, 442, 854, 103, 818, 274, 611, 129, 412, 517, 480, + -246, 769, 57, -431, -326, 492, 732, -40, -261, -463, -316, 915, + -30, 836, 276, 309, -225, -193, -623, -1000, -113, 614, -869, 694, + -480, -287, -343, 71, -458, -775, -947, 335, 637, -627, 43, -874, + 109, -805, 567, 927}; + std::vector sorted_array = { + -1000, -947, -946, -874, -869, -858, -848, -826, -815, -814, -805, -775, + -767, -727, -723, -706, -627, -623, -592, -578, -576, -515, -480, -470, + -463, -458, -452, -431, -353, -343, -326, -318, -316, -310, -287, -266, + -261, -246, -239, -225, -193, -191, -187, -178, -141, -113, -98, -54, + -40, -30, -8, 40, 43, 57, 67, 71, 76, 97, 103, 109, + 129, 274, 276, 294, 305, 309, 334, 335, 374, 400, 405, 412, + 442, 477, 480, 492, 517, 567, 602, 611, 614, 637, 676, 693, + 694, 695, 699, 732, 769, 785, 798, 814, 818, 836, 854, 858, + 915, 919, 927, 953}; + QuickSort(array, 0, int(array.size() - 1)); + ASSERT_EQ(array, sorted_array); +} \ No newline at end of file diff --git a/task_06/src/k_sorted_sequence.hpp b/task_06/src/k_sorted_sequence.hpp new file mode 100644 index 00000000..f0b5009d --- /dev/null +++ b/task_06/src/k_sorted_sequence.hpp @@ -0,0 +1,41 @@ +#include +#include +#include + +// Function to find the k-th smallest element in a sorted sequence using +// Quickselect algorithm +template +T FindSortedSequence(std::vector array, int k) { + int begin = 0, end = array.size() - 1; + + // Check if k is within the bounds of the array + if (k > end) + throw std::out_of_range("k should be less than the size of the array"); + + // Loop until the k-th element is found + while (true) { + int first = begin; + int pivot = + (rand() % (end - begin + 1)) + begin; // Randomly select a pivot + std::swap(array[pivot], array[end]); // Move pivot element to the end + + // Partition the array based on the pivot element + while (array[begin] <= array[end] && begin < end) ++begin; + + for (int start = begin + 1; start < end; ++start) + if (array[start] <= array[end]) std::swap(array[start], array[begin++]); + std::swap(array[begin], array[end]); + + // Check if the k-th element is found at the current partition + if (k == begin) + return array[begin]; + else if (k < begin) { + end = begin - 1; + if (end == first) return array[begin - 1]; + begin = 0; + } else if (k > begin) { + ++begin; + if (begin == end) return array[begin]; + } + } +} diff --git a/task_06/src/main.cpp b/task_06/src/main.cpp index 0e4393ba..d1f324d8 100644 --- a/task_06/src/main.cpp +++ b/task_06/src/main.cpp @@ -1,3 +1,5 @@ #include +#include "k_sorted_sequence.hpp" + int main() { return 0; } diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617e..6c6bb769 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,40 @@ #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include + +#include "k_sorted_sequence.hpp" + +TEST(k_sorted_sequence, EmptyArray) { + std::vector array = {}; + EXPECT_THROW(FindSortedSequence(array, 1), std::out_of_range); +} + +TEST(k_sorted_sequence, SingleElementArray) { + std::vector array = {42}; + ASSERT_EQ(FindSortedSequence(array, 0), 42); +} + +TEST(k_sorted_sequence, NegativeNumbers) { + std::vector array = {-5, -3, -8, -1, -10, -2, -6, -4, -7, -9}; + ASSERT_EQ(FindSortedSequence(array, 4), -6); +} + +TEST(k_sorted_sequence, SmallRandomArray) { + std::vector array = {-61, 20, -64, -39, 24, -91, 28, -69, -78, + 7, 16, -97, -12, 29, 8, -27, 50, -98, + -37, 42, -72, -19, -25, 23, 96}; + ASSERT_EQ(FindSortedSequence(array, 7), -61); +} + +TEST(k_sorted_sequence, LargeRandomArray) { + std::vector array = { + 75, 93, 82, 35, 79, 59, 1, 54, 84, 40, 94, 83, 81, 61, 2, 88, 92, + 70, 52, 14, 36, 33, 100, 97, 58, 17, 50, 96, 7, 53, 77, 74, 85, 38, + 34, 26, 90, 8, 55, 76, 6, 51, 63, 42, 21, 99, 67, 9, 41, 56, 64, + 25, 12, 49, 98, 44, 87, 68, 78, 28, 72, 37, 5, 31, 71, 29, 22, 91, + 13, 24, 89, 65, 80, 20, 11, 43, 19, 69, 10, 45, 16, 66, 57, 27, 32, + 86, 15, 47, 18, 30, 60, 23, 3, 46, 48, 73, 4, 95, 62, 39}; + ASSERT_EQ(FindSortedSequence(array, 87), 88); } diff --git a/task_07/src/avl_tree.hpp b/task_07/src/avl_tree.hpp new file mode 100644 index 00000000..a133ced5 --- /dev/null +++ b/task_07/src/avl_tree.hpp @@ -0,0 +1,168 @@ +#pragma once +#include +#include + +template +class AVLTree { + public: + AVLTree() : root(nullptr) {} + + void Insert(T value); + + bool Contains(T value) const; + + void Remove(T value); + + private: + struct AVLNode { + T value; + size_t height; + std::unique_ptr left; + std::unique_ptr right; + + explicit AVLNode(T value) + : value(value), left(nullptr), right(nullptr), height(1) {} + }; + + std::unique_ptr root; + + size_t Height(const std::unique_ptr &node) const; + + int BalanceFactor(const std::unique_ptr &node) const; + + void UpdateHeight(std::unique_ptr &node); + + std::unique_ptr RotateRight(std::unique_ptr &original_node); + + std::unique_ptr RotateLeft(std::unique_ptr &original_node); + + std::unique_ptr ReBalance(std::unique_ptr &node); + + std::unique_ptr SearchMin(std::unique_ptr &node); + + std::unique_ptr Insert(T value, std::unique_ptr &node); + + std::unique_ptr Remove(T value, std::unique_ptr &node); + + bool Contains(T value, const std::unique_ptr &node) const; +}; + +template +size_t AVLTree::Height(const std::unique_ptr &node) const { + return node ? node->height : 0; +} + +template +int AVLTree::BalanceFactor(const std::unique_ptr &node) const { + return Height(node->left) - Height(node->right); +} + +template +void AVLTree::UpdateHeight(std::unique_ptr &node) { + if (node) + node->height = std::max(Height(node->left), Height(node->right)) + 1; +} + +template +std::unique_ptr::AVLNode> AVLTree::RotateRight( + std::unique_ptr &original_node) { + std::unique_ptr new_node = std::move(original_node->left); + original_node->left = std::move(new_node->right); + new_node->right = std::move(original_node); + + UpdateHeight(original_node); + UpdateHeight(new_node); + + return new_node; +} + +template +std::unique_ptr::AVLNode> AVLTree::RotateLeft( + std::unique_ptr &original_node) { + std::unique_ptr new_node = std::move(original_node->right); + original_node->right = std::move(new_node->left); + new_node->left = std::move(original_node); + + UpdateHeight(original_node); + UpdateHeight(new_node); + + return new_node; +} + +template +std::unique_ptr::AVLNode> AVLTree::ReBalance( + std::unique_ptr &node) { + int balance = BalanceFactor(node); + if (balance > 1) { + if (BalanceFactor(node->left) < 0) node->left = RotateLeft(node); + return RotateRight(node); + } + if (balance < -1) { + if (BalanceFactor(node->right) > 0) node->right = RotateRight(node); + return RotateLeft(node); + } + return std::move(node); +} + +template +std::unique_ptr::AVLNode> AVLTree::SearchMin( + std::unique_ptr &node) { + if (!node->left) return std::move(node); + return SearchMin(node->left); +} + +template +std::unique_ptr::AVLNode> AVLTree::Insert( + T value, std::unique_ptr &node) { + if (!node) return std::make_unique(value); + if (value < node->value) + node->left = Insert(value, node->left); + else if (value > node->value) + node->right = Insert(value, node->right); + else + return std::move(node); + UpdateHeight(node); + return ReBalance(node); +} + +template +bool AVLTree::Contains(T value, const std::unique_ptr &node) const { + if (!node) return false; + if (value < node->value) return Contains(value, node->left); + if (value > node->value) return Contains(value, node->right); + return true; +} + +template +std::unique_ptr::AVLNode> AVLTree::Remove( + T value, std::unique_ptr &node) { + if (!node) return nullptr; + if (value < node->value) + node->left = Remove(value, node->left); + else if (value > node->value) + node->right = Remove(value, node->right); + else { + if (!node->left) return std::move(node->right); + if (!node->right) return std::move(node->left); + std::unique_ptr min_node = SearchMin(node->right); + node->value = min_node->value; + node->right = Remove(min_node->value, node->right); + } + UpdateHeight(node); + return ReBalance(node); +} + +template +void AVLTree::Insert(T value) { + root = Insert(value, root); +} + +template +void AVLTree::Remove(T value) { + root = Remove(value, root); +} + +template +bool AVLTree::Contains(const T value) const { + return Contains(value, root); +} \ No newline at end of file diff --git a/task_07/src/bs_tree.hpp b/task_07/src/bs_tree.hpp new file mode 100644 index 00000000..01447262 --- /dev/null +++ b/task_07/src/bs_tree.hpp @@ -0,0 +1,121 @@ +#pragma once +#include + +template +class BSTree { + public: + // Constructor to initialize the tree with a nullptr root + BSTree() : root(nullptr) {} + + // Public methods for insertion, checking containment, and removal + void Insert(T value); + bool Contains(T value) const; + bool Remove(T value); + + private: + // Node structure for the binary search tree + struct BSTNode { + T value; + std::unique_ptr left; + std::unique_ptr right; + + // Node constructor to set the value, left, and right pointers to nullptr + explicit BSTNode(T value) : value(value), left(nullptr), right(nullptr) {} + }; + + std::unique_ptr root; // Root of the binary search tree + + // Private method to find the minimum node in a subtree starting from the + // given node + std::unique_ptr &SearchMin(std::unique_ptr &node) const; + + // Private method to check containment recursively in a subtree starting from + // the given node + bool Contains(T value, const std::unique_ptr &node) const; + + // Private method to insert a value recursively in the binary search tree + // starting from the given node + void Insert(T value, std::unique_ptr &node); + + // Private method to remove a value recursively from the binary search tree + // starting from the given node + bool Remove(T value, std::unique_ptr &node); +}; + +// Public method to insert a value into the binary search tree +template +void BSTree::Insert(T value) { + Insert(value, root); +} + +// Private method to insert a value recursively into the binary search tree +template +void BSTree::Insert(T value, std::unique_ptr &node) { + if (!node) { + node = std::make_unique(value); + return; + } + if (value <= node->value) Insert(value, node->left); + if (value > node->value) Insert(value, node->right); +} + +// Public method to check if a value is contained in the binary search tree +template +bool BSTree::Contains(T value) const { + return Contains(value, root); +} + +// Private method to check if a value is contained in a subtree starting from +// the given node +template +bool BSTree::Contains(T value, const std::unique_ptr &node) const { + if (!node) return false; + if (value < node->value) return Contains(value, node->left); + if (value > node->value) return Contains(value, node->right); + return true; +} + +// Public method to remove a value from the binary search tree +template +bool BSTree::Remove(T value) { + return Remove(value, root); +} + +// Private method to remove a value recursively from the binary search tree +// starting from the given node +template +bool BSTree::Remove(T value, std::unique_ptr &node) { + if (!node) return false; + if (value == node->value) { + if (!node->left && !node->right) { + node = nullptr; + return true; + } + if (node->left && !node->right) { + node = std::move(node->left); + return true; + } + if (!node->left && node->right) { + node = std::move(node->right); + return true; + } + std::unique_ptr &minNode = SearchMin(node->right); + node->value = minNode->value; + return Remove(minNode->value, minNode); + } + if (value < node->value) { + return Remove(value, node->left); + } + if (value > node->value) { + return Remove(value, node->right); + } +} + +// Private method to find the minimum node in a subtree starting from the given +// node +template +std::unique_ptr::BSTNode> &BSTree::SearchMin( + std::unique_ptr &node) const { + if (!node->left) return node; + return SearchMin(node->left); +} \ No newline at end of file diff --git a/task_07/src/test.cpp b/task_07/src/test.cpp index 5e11617e..fd9fcb1f 100644 --- a/task_07/src/test.cpp +++ b/task_07/src/test.cpp @@ -1,6 +1,162 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "avl_tree.hpp" +#include "bs_tree.hpp" + +TEST(BSTreeTest, Simple) { + BSTree tree; + tree.Insert(10); + tree.Insert(5); + tree.Insert(15); + tree.Insert(3); + tree.Insert(7); + tree.Insert(12); + tree.Insert(17); + + ASSERT_EQ(tree.Contains(10), true); + ASSERT_EQ(tree.Contains(5), true); + ASSERT_EQ(tree.Contains(15), true); + ASSERT_EQ(tree.Contains(3), true); + ASSERT_EQ(tree.Contains(7), true); + ASSERT_EQ(tree.Contains(12), true); + ASSERT_EQ(tree.Contains(17), true); + ASSERT_EQ(tree.Contains(8), false); + ASSERT_EQ(tree.Contains(20), false); + + tree.Remove(3); + ASSERT_EQ(tree.Contains(3), false); + + tree.Remove(15); + ASSERT_EQ(tree.Contains(15), false); + + tree.Insert(20); + tree.Insert(8); + ASSERT_EQ(tree.Contains(20), true); + ASSERT_EQ(tree.Contains(8), true); + + tree.Remove(5); + ASSERT_EQ(tree.Contains(5), false); + + tree.Insert(1); + tree.Insert(25); + ASSERT_EQ(tree.Contains(1), true); + ASSERT_EQ(tree.Contains(25), true); +} + +TEST(BSTreeTest, DuplicateData) { + BSTree Tree; + + ASSERT_EQ(Tree.Contains(10), false); + + Tree.Insert(5); + Tree.Remove(5); + ASSERT_EQ(Tree.Contains(5), false); + + Tree.Insert(1); + Tree.Insert(2); + Tree.Insert(3); + Tree.Remove(1); + Tree.Remove(2); + Tree.Remove(3); + ASSERT_EQ(Tree.Contains(1), false); + ASSERT_EQ(Tree.Contains(2), false); + ASSERT_EQ(Tree.Contains(3), false); +} + +TEST(BSTreeTest, RemoveChecking) { + BSTree Tree; + Tree.Insert(10); + Tree.Insert(5); + Tree.Insert(15); + Tree.Insert(7); + Tree.Insert(12); + Tree.Insert(20); + + ASSERT_EQ(Tree.Remove(10), true); + ASSERT_EQ(Tree.Contains(10), false); + + ASSERT_EQ(Tree.Remove(7), true); + ASSERT_EQ(Tree.Contains(7), false); + + ASSERT_EQ(Tree.Contains(5), true); + ASSERT_EQ(Tree.Remove(5), true); + + ASSERT_EQ(Tree.Remove(19), false); + ASSERT_EQ(Tree.Remove(119), false); + ASSERT_EQ(Tree.Remove(12), true); + ASSERT_EQ(Tree.Remove(12), false); +} + +TEST(AVLTreeTest, InsertAndFind) { + AVLTree tree; + + tree.Insert(10); + ASSERT_TRUE(tree.Contains(10)); + ASSERT_FALSE(tree.Contains(20)); + + tree.Insert(20); + ASSERT_TRUE(tree.Contains(10)); + ASSERT_TRUE(tree.Contains(20)); + + tree.Insert(30); + ASSERT_TRUE(tree.Contains(10)); + ASSERT_TRUE(tree.Contains(20)); + ASSERT_TRUE(tree.Contains(30)); + + tree.Insert(5); + ASSERT_TRUE(tree.Contains(5)); + ASSERT_TRUE(tree.Contains(10)); + ASSERT_TRUE(tree.Contains(20)); + ASSERT_TRUE(tree.Contains(30)); + + tree.Insert(15); + ASSERT_TRUE(tree.Contains(5)); + ASSERT_TRUE(tree.Contains(10)); + ASSERT_TRUE(tree.Contains(15)); + ASSERT_TRUE(tree.Contains(20)); + ASSERT_TRUE(tree.Contains(30)); +} + +TEST(AVLTreeTest, Remove) { + AVLTree tree; + + tree.Insert(10); + tree.Insert(20); + tree.Insert(30); + + tree.Remove(20); + ASSERT_TRUE(tree.Contains(10)); + ASSERT_FALSE(tree.Contains(20)); + ASSERT_TRUE(tree.Contains(30)); + + tree.Remove(10); + ASSERT_FALSE(tree.Contains(10)); + ASSERT_TRUE(tree.Contains(30)); + + tree.Remove(30); + ASSERT_FALSE(tree.Contains(10)); + ASSERT_FALSE(tree.Contains(20)); + ASSERT_FALSE(tree.Contains(30)); + + tree.Insert(10); + tree.Insert(20); + tree.Insert(30); + tree.Insert(5); + tree.Insert(15); + + tree.Remove(20); + ASSERT_TRUE(tree.Contains(10)); + ASSERT_TRUE(tree.Contains(15)); + ASSERT_TRUE(tree.Contains(30)); + ASSERT_TRUE(tree.Contains(5)); + + tree.Remove(10); + ASSERT_TRUE(tree.Contains(15)); + ASSERT_TRUE(tree.Contains(30)); + ASSERT_TRUE(tree.Contains(5)); +} + +TEST(AVLTreeTest, ContainsEmptyTree) { + AVLTree tree; + ASSERT_FALSE(tree.Contains(10)); } diff --git a/task_08/src/hash_table.hpp b/task_08/src/hash_table.hpp new file mode 100644 index 00000000..6a9c0325 --- /dev/null +++ b/task_08/src/hash_table.hpp @@ -0,0 +1,209 @@ +#pragma once + +#include + +#include +#include +#include + +template +class HashTable { + public: + explicit HashTable(std::function hash_func) + : used_cell_count_(0), + size_(0), + buffer_size_(DefaultBufferSize), + table_container_(std::vector(buffer_size_)), + cell_conditions_( + std::vector(buffer_size_, Condition::Empty)), + is_custom_hash_func_(true), + CustomHashFunction(hash_func) {} + + HashTable() + : used_cell_count_(0), + size_(0), + buffer_size_(DefaultBufferSize), + table_container_(std::vector(buffer_size_)), + cell_conditions_( + std::vector(buffer_size_, Condition::Empty)), + is_custom_hash_func_(false) {} + + bool Contains(T value) const; + + void Insert(T value); + + void Remove(T value); + + void Clear(); + + size_t Size() const; + + private: + enum class Condition { Fill, Deleted, Empty }; + constexpr static const double RehashCoefficient = 0.7; + constexpr static const double HashCoefficient = 0.618033989; + constexpr static const double DefaultBufferSize = 16; + bool is_custom_hash_func_; + + size_t buffer_size_; + size_t size_; + unsigned used_cell_count_; + + std::vector table_container_; + std::vector cell_conditions_; + + size_t SecondHashFunction(T key) const; + + size_t FirstHashFunction(T key) const; + + void Rehash(); + + void ReSize(); + + std::function CustomHashFunction; +}; + +template +size_t HashTable::Size() const { + return size_; +} + +template +size_t HashTable::SecondHashFunction(T key) const { + if constexpr (std::is_arithmetic::value) + return (key * buffer_size_ - 1) % buffer_size_; + throw std::invalid_argument( + "HashHashTable does not support this data type, use custom hash " + "functions"); +} + +template +size_t HashTable::FirstHashFunction(T key) const { + if constexpr (std::is_arithmetic::value) + return floor(buffer_size_ * + ((key * HashCoefficient) - floor(key * HashCoefficient))); + throw std::invalid_argument( + "HashHashTable does not support this data type, use custom hash " + "functions"); +} + +template +void HashTable::Clear() { + size_ = 0; + used_cell_count_ = 0; + std::fill(cell_conditions_.begin(), cell_conditions_.end(), Condition::Empty); +} + +template +void HashTable::Insert(T value) { + size_t hash; + if (is_custom_hash_func_) { + hash = CustomHashFunction(value) % buffer_size_; + while (cell_conditions_[hash] == Condition::Fill) { + if (table_container_[hash] == value) return; + hash++; + } + } else { + hash = FirstHashFunction(value) % buffer_size_; + int attempt_count = 0; + while (cell_conditions_[hash] == Condition::Fill) { + if (table_container_[hash] == value) return; + attempt_count++; + hash = (FirstHashFunction(value) + + attempt_count * SecondHashFunction(value)) % + buffer_size_; + } + } + + table_container_[hash] = value; + cell_conditions_[hash] = Condition::Fill; + used_cell_count_++; + size_++; + + auto fill_coefficient = double(used_cell_count_) / buffer_size_; + if (fill_coefficient >= RehashCoefficient) Rehash(); +} + +template +bool HashTable::Contains(T value) const { + size_t hash; + if (is_custom_hash_func_) { + hash = CustomHashFunction(value) % buffer_size_; + while (cell_conditions_[hash] != Condition::Empty) { + if (table_container_[hash] == value && + cell_conditions_[hash] == Condition::Fill) + return true; + hash++; + } + } else { + hash = FirstHashFunction(value) % buffer_size_; + int attempt_count = 0; + while (cell_conditions_[hash] != Condition::Empty) { + if (table_container_[hash] == value && + cell_conditions_[hash] == Condition::Fill) + return true; + attempt_count++; + hash = (FirstHashFunction(value) + + attempt_count * SecondHashFunction(value)) % + buffer_size_; + } + } + return false; +} + +template +void HashTable::Remove(T value) { + size_t hash; + if (is_custom_hash_func_) { + hash = CustomHashFunction(value); + while (cell_conditions_[hash] != Condition::Empty) { + if (table_container_[hash] == value && + cell_conditions_[hash] == Condition::Fill) { + cell_conditions_[hash] = Condition::Deleted; + size_--; + break; + } + if (table_container_[hash] == value && + cell_conditions_[hash] == Condition::Deleted) + break; + hash++; + } + } else { + hash = FirstHashFunction(value) % buffer_size_; + int attempt_count = 0; + while (cell_conditions_[hash] != Condition::Empty) { + if (table_container_[hash] == value && + cell_conditions_[hash] == Condition::Fill) { + cell_conditions_[hash] = Condition::Deleted; + size_--; + break; + } + if (table_container_[hash] == value && + cell_conditions_[hash] == Condition::Deleted) + break; + attempt_count++; + hash = (FirstHashFunction(value) + + attempt_count * SecondHashFunction(value)) % + buffer_size_; + } + } +} + +template +void HashTable::ReSize() { + buffer_size_ *= 2; + table_container_.resize(buffer_size_); + cell_conditions_.resize(buffer_size_); +} + +template +void HashTable::Rehash() { + std::vector outdated_container; + for (int i = 0; i < buffer_size_; ++i) + if (cell_conditions_[i] == Condition::Fill) + outdated_container.push_back(table_container_[i]); + + ReSize(); + Clear(); + for (auto &elem : outdated_container) Insert(elem); +} diff --git a/task_08/src/test.cpp b/task_08/src/test.cpp index 5e11617e..ee449f5f 100644 --- a/task_08/src/test.cpp +++ b/task_08/src/test.cpp @@ -1,6 +1,93 @@ #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include +#include + +#include "hash_table.hpp" + +size_t CustomHashFunction(int key) { return key % 10; } +size_t CustomStringHashFunction(std::string key) { return key.size() % 17; } + +TEST(HashTableTest, SimpleTest) { + HashTable table; + ASSERT_EQ(table.Size(), 0); + + table.Insert(14); + table.Insert(124); + table.Insert(1); + table.Insert(-23); + table.Insert(54); + table.Insert(44); + table.Insert(0); + table.Insert(674); + + ASSERT_EQ(table.Contains(124), true); + ASSERT_EQ(table.Contains(44), true); + ASSERT_EQ(table.Contains(54), true); + ASSERT_EQ(table.Contains(0), true); + ASSERT_EQ(table.Contains(-23), true); + ASSERT_EQ(table.Contains(1), true); + + ASSERT_EQ(table.Size(), 8); + + table.Remove(14); + ASSERT_EQ(table.Contains(14), false); + + table.Clear(); + ASSERT_EQ(table.Size(), 0); + + for (int i = 0; i < 100000; ++i) { + table.Insert(i); + } + + ASSERT_EQ(table.Contains(18353), true); + table.Remove(18353); + ASSERT_EQ(table.Contains(18353), false); + + table.Insert(-99999); + ASSERT_EQ(table.Contains(-99999), true); +} + +TEST(HashTableTest, CustomHashFunctionTest) { + HashTable table(CustomHashFunction); + + table.Insert(10); + table.Insert(26); + + ASSERT_EQ(table.Contains(10), true); + ASSERT_EQ(table.Contains(26), true); + + table.Remove(10); + table.Remove(26); + + ASSERT_EQ(table.Contains(10), false); + ASSERT_EQ(table.Contains(26), false); +} + +TEST(HashTableTest, CollisionTest) { + HashTable table(CustomHashFunction); + + table.Insert(10); + table.Insert(20); + table.Insert(30); + + ASSERT_EQ(table.Contains(10), true); + ASSERT_EQ(table.Contains(20), true); + ASSERT_EQ(table.Contains(30), true); +} + +TEST(HashTableTest, AnotherTypeTest) { + HashTable table(CustomStringHashFunction); + + table.Insert("Dog"); + table.Insert("Cat"); + table.Insert("Very long string"); + ASSERT_EQ(table.Contains("Dog"), true); + ASSERT_EQ(table.Contains("Dog"), true); + ASSERT_EQ(table.Contains("Short string"), false); + + table.Remove("Dog"); + ASSERT_EQ(table.Contains("Dog"), false); + ASSERT_EQ(table.Size(), 2); } diff --git a/task_09/src/coin_exchange.cpp b/task_09/src/coin_exchange.cpp new file mode 100644 index 00000000..a95cf6ae --- /dev/null +++ b/task_09/src/coin_exchange.cpp @@ -0,0 +1,18 @@ +#include "coin_exchange.hpp" + +int ChangeCoins(int money_amount, const std::vector& coin_denominations) { + std::vector minimal_exchanges(money_amount + 1, INT_MAX); + minimal_exchanges[0] = 0; + for (int cur_money_amount = 1; cur_money_amount <= money_amount; + ++cur_money_amount) { + for (auto coin : coin_denominations) + if (cur_money_amount >= coin && + minimal_exchanges[cur_money_amount - coin] != INT_MAX) + minimal_exchanges[cur_money_amount] = + std::min(minimal_exchanges[cur_money_amount], + minimal_exchanges[cur_money_amount - coin] + 1); + } + return minimal_exchanges[money_amount] == INT_MAX + ? -1 + : minimal_exchanges[money_amount]; +} \ No newline at end of file diff --git a/task_09/src/coin_exchange.hpp b/task_09/src/coin_exchange.hpp new file mode 100644 index 00000000..42b5453c --- /dev/null +++ b/task_09/src/coin_exchange.hpp @@ -0,0 +1,5 @@ +#pragma once +#include +#include + +int ChangeCoins(int money_amount, const std::vector& coin_denominations); \ No newline at end of file diff --git a/task_09/src/test.cpp b/task_09/src/test.cpp index 869094dd..1da8a5b5 100644 --- a/task_09/src/test.cpp +++ b/task_09/src/test.cpp @@ -1,4 +1,45 @@ #include -TEST(TopologySort, Simple) { ASSERT_EQ(1, 1); } +#include + +#include "coin_exchange.hpp" + +TEST(ChangeCoinsTest, Simple) { + std::vector coins = {1, 2, 5}; + EXPECT_EQ(ChangeCoins(11, coins), 3); +} +TEST(ChangeCoinsTest, Normal) { + std::vector coins = {1, 2, 5, 7, 10}; + EXPECT_EQ(ChangeCoins(14, coins), 2); +} + +TEST(ChangeCoinsTest, Impossible) { + std::vector coins = {2, 3}; + EXPECT_EQ(ChangeCoins(1, coins), -1); +} + +TEST(ChangeCoinsTest, Zero) { + std::vector coins = {1, 2, 5}; + EXPECT_EQ(ChangeCoins(0, coins), 0); +} + +TEST(ChangeCoinsTest, LargeSum) { + std::vector coins = {1, 2, 5, 10, 20, 50, 100}; + EXPECT_EQ(ChangeCoins(12321377, coins), 123217); +} + +TEST(ChangeCoinsTest, SingleCoin) { + std::vector coins = {1}; + EXPECT_EQ(ChangeCoins(5, coins), 5); +} + +TEST(ChangeCoinsTest, NoCoins) { + std::vector coins = {}; + EXPECT_EQ(ChangeCoins(10, coins), -1); +} + +TEST(ChangeCoinsTest, LargeCoins) { + std::vector coins = {1, 2, 5, 10, 20, 50, 100, 200, 500, 1000}; + EXPECT_EQ(ChangeCoins(1279, coins), 7); +} \ No newline at end of file