diff --git a/tasks/krasnopevtseva_v_hoare_batcher_sort/common/include/common.hpp b/tasks/krasnopevtseva_v_hoare_batcher_sort/common/include/common.hpp new file mode 100644 index 00000000..e6ce6b86 --- /dev/null +++ b/tasks/krasnopevtseva_v_hoare_batcher_sort/common/include/common.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include + +#include "task/include/task.hpp" + +namespace krasnopevtseva_v_hoare_batcher_sort { + +using InType = std::vector; +using OutType = std::vector; +using TestType = std::tuple, std::string>; +using BaseTask = ppc::task::Task; + +} // namespace krasnopevtseva_v_hoare_batcher_sort diff --git a/tasks/krasnopevtseva_v_hoare_batcher_sort/data/pic.ppm b/tasks/krasnopevtseva_v_hoare_batcher_sort/data/pic.ppm new file mode 100644 index 00000000..63762423 Binary files /dev/null and b/tasks/krasnopevtseva_v_hoare_batcher_sort/data/pic.ppm differ diff --git a/tasks/krasnopevtseva_v_hoare_batcher_sort/info.json b/tasks/krasnopevtseva_v_hoare_batcher_sort/info.json new file mode 100644 index 00000000..704b14a6 --- /dev/null +++ b/tasks/krasnopevtseva_v_hoare_batcher_sort/info.json @@ -0,0 +1,9 @@ +{ + "student": { + "first_name": "Вероника", + "group_number": "3823Б1ПМоп3", + "last_name": "Краснопевцева", + "middle_name": "Дмитриевна", + "task_number": "14" + } +} diff --git a/tasks/krasnopevtseva_v_hoare_batcher_sort/seq/include/ops_seq.hpp b/tasks/krasnopevtseva_v_hoare_batcher_sort/seq/include/ops_seq.hpp new file mode 100644 index 00000000..fbc53f2e --- /dev/null +++ b/tasks/krasnopevtseva_v_hoare_batcher_sort/seq/include/ops_seq.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "krasnopevtseva_v_hoare_batcher_sort/common/include/common.hpp" +#include "task/include/task.hpp" + +namespace krasnopevtseva_v_hoare_batcher_sort { + +class KrasnopevtsevaVHoareBatcherSortSEQ : public BaseTask { + public: + static constexpr ppc::task::TypeOfTask GetStaticTypeOfTask() { + return ppc::task::TypeOfTask::kSEQ; + } + explicit KrasnopevtsevaVHoareBatcherSortSEQ(const InType &in); + + private: + bool ValidationImpl() override; + bool PreProcessingImpl() override; + bool RunImpl() override; + static void CompareAndSwap(int &a, int &b); + static void BatcherMerge(std::vector &arr, int left, int right); + static void QuickBatcherSort(std::vector &arr, int left, int right); + static void InsertionSort(std::vector &arr, int left, int right); + static int Partition(std::vector &arr, int left, int right); + bool PostProcessingImpl() override; +}; + +} // namespace krasnopevtseva_v_hoare_batcher_sort diff --git a/tasks/krasnopevtseva_v_hoare_batcher_sort/seq/src/ops_seq.cpp b/tasks/krasnopevtseva_v_hoare_batcher_sort/seq/src/ops_seq.cpp new file mode 100644 index 00000000..f7682438 --- /dev/null +++ b/tasks/krasnopevtseva_v_hoare_batcher_sort/seq/src/ops_seq.cpp @@ -0,0 +1,160 @@ +#include "krasnopevtseva_v_hoare_batcher_sort/seq/include/ops_seq.hpp" + +#include +#include +#include +#include +#include + +#include "krasnopevtseva_v_hoare_batcher_sort/common/include/common.hpp" + +namespace krasnopevtseva_v_hoare_batcher_sort { + +KrasnopevtsevaVHoareBatcherSortSEQ::KrasnopevtsevaVHoareBatcherSortSEQ(const InType &in) { + SetTypeOfTask(GetStaticTypeOfTask()); + GetInput() = in; + GetOutput() = std::vector(); +} + +bool KrasnopevtsevaVHoareBatcherSortSEQ::ValidationImpl() { + const auto &input = GetInput(); + return (!input.empty()); +} + +bool KrasnopevtsevaVHoareBatcherSortSEQ::PreProcessingImpl() { + GetOutput() = std::vector(); + return true; +} + +bool KrasnopevtsevaVHoareBatcherSortSEQ::RunImpl() { + const auto &input = GetInput(); + size_t size = input.size(); + std::vector sort_v = input; + + if (size > 1) { + QuickBatcherSort(sort_v, 0, static_cast(size - 1)); + } + GetOutput() = sort_v; + return true; +} + +void KrasnopevtsevaVHoareBatcherSortSEQ::CompareAndSwap(int &a, int &b) { + if (a > b) { + std::swap(a, b); + } +} + +void KrasnopevtsevaVHoareBatcherSortSEQ::BatcherMerge(std::vector &arr, int left, int right) { + int n = right - left + 1; + if (n <= 1) { + return; + } + + std::vector temp(arr.begin() + left, arr.begin() + right + 1); + + std::function odd_even_merge = [&](int l, int r) { + if (l == r) { + return; + } + + int m = l + ((r - l) / 2); + odd_even_merge(l, m); + odd_even_merge(m + 1, r); + + for (int i = l + 1; i + (m - l + 1) <= r; i += 2) { + CompareAndSwap(temp[i], temp[i + (m - l + 1)]); + } + }; + + odd_even_merge(0, n - 1); + + for (int i = 1; i + 1 < n; i += 2) { + CompareAndSwap(temp[i], temp[i + 1]); + } + for (int i = 0; i < n; i++) { + arr[left + i] = temp[i]; + } +} + +void KrasnopevtsevaVHoareBatcherSortSEQ::QuickBatcherSort(std::vector &arr, int left, int right) { + std::stack> stack; + stack.emplace(left, right); + + while (!stack.empty()) { + auto [l, r] = stack.top(); + stack.pop(); + + if (l >= r) { + continue; + } + + if (r - l < 16) { + InsertionSort(arr, l, r); + continue; + } + + int pivot_index = Partition(arr, l, r); + + if (pivot_index - l < r - pivot_index) { + stack.emplace(pivot_index + 1, r); + stack.emplace(l, pivot_index - 1); + } else { + stack.emplace(l, pivot_index - 1); + stack.emplace(pivot_index + 1, r); + } + } + + if (right - left > 32) { + BatcherMerge(arr, left, right); + } +} + +void KrasnopevtsevaVHoareBatcherSortSEQ::InsertionSort(std::vector &arr, int left, int right) { + for (int i = left + 1; i <= right; ++i) { + int key = arr[i]; + int j = i - 1; + while (j >= left && arr[j] > key) { + arr[j + 1] = arr[j]; + --j; + } + arr[j + 1] = key; + } +} + +int KrasnopevtsevaVHoareBatcherSortSEQ::Partition(std::vector &arr, int left, int right) { + int mid = left + ((right - left) / 2); + if (arr[left] > arr[mid]) { + std::swap(arr[left], arr[mid]); + } + if (arr[left] > arr[right]) { + std::swap(arr[left], arr[right]); + } + if (arr[mid] > arr[right]) { + std::swap(arr[mid], arr[right]); + } + + std::swap(arr[mid], arr[right - 1]); + int pivot = arr[right - 1]; + + int i = left; + int j = right - 1; + + while (true) { + while (arr[++i] < pivot) { + } + while (arr[--j] > pivot) { + } + if (i >= j) { + break; + } + std::swap(arr[i], arr[j]); + } + + std::swap(arr[i], arr[right - 1]); + return i; +} + +bool KrasnopevtsevaVHoareBatcherSortSEQ::PostProcessingImpl() { + return true; +} +} // namespace krasnopevtseva_v_hoare_batcher_sort diff --git a/tasks/krasnopevtseva_v_hoare_batcher_sort/settings.json b/tasks/krasnopevtseva_v_hoare_batcher_sort/settings.json new file mode 100644 index 00000000..0be0208f --- /dev/null +++ b/tasks/krasnopevtseva_v_hoare_batcher_sort/settings.json @@ -0,0 +1,10 @@ +{ + "tasks": { + "all": "enabled", + "omp": "enabled", + "seq": "enabled", + "stl": "enabled", + "tbb": "enabled" + }, + "tasks_type": "threads" +} diff --git a/tasks/krasnopevtseva_v_hoare_batcher_sort/tests/functional/main.cpp b/tasks/krasnopevtseva_v_hoare_batcher_sort/tests/functional/main.cpp new file mode 100644 index 00000000..6fb34c9c --- /dev/null +++ b/tasks/krasnopevtseva_v_hoare_batcher_sort/tests/functional/main.cpp @@ -0,0 +1,90 @@ +#include + +#include +#include +#include +#include +#include +#include + +#include "krasnopevtseva_v_hoare_batcher_sort/common/include/common.hpp" +#include "krasnopevtseva_v_hoare_batcher_sort/seq/include/ops_seq.hpp" +#include "util/include/func_test_util.hpp" +#include "util/include/util.hpp" + +namespace krasnopevtseva_v_hoare_batcher_sort { + +class KrasnopevtsevaVRunFuncTestsThreads : public ppc::util::BaseRunFuncTests { + public: + static std::string PrintTestParam(const TestType &test_param) { + const auto &input = std::get<0>(test_param); + size_t size = input.size(); + std::string s; + for (size_t i = 0; i < size; i++) { + s += std::to_string(input[i]); + if (i < size - 1) { + s += "_"; + } + } + std::string result = "array_" + s + "_size" + std::to_string(size) + "_" + std::get<1>(test_param); + return result; + } + + protected: + void SetUp() override { + auto test_param = std::get(ppc::util::GTestParamIndex::kTestParams)>(GetParam()); + input_data_ = std::get<0>(test_param); + } + + bool CheckTestOutputData(OutType &output_data) final { + size_t size = output_data.size(); + bool result = true; + for (size_t i = 0; i < size - 1; i++) { + if (output_data[i] > output_data[i + 1]) { + result = false; + } + } + return result; + } + + InType GetTestInputData() final { + return input_data_; + } + + private: + InType input_data_; +}; + +namespace { + +TEST_P(KrasnopevtsevaVRunFuncTestsThreads, HoareBatcherSort) { + ExecuteTest(GetParam()); +} + +const std::array kTestParam = { + std::make_tuple(std::vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, "sorted_array"), + std::make_tuple(std::vector{5, 1, 3, 4, 2, 34, 24, 16, 31, 666, 22, 14, 52, 67, 13, 99, 9, 6, 28, 35}, + "default_array"), + std::make_tuple(std::vector{10, 1, 30, 2}, "short_array"), + std::make_tuple(std::vector{1000, 3246, 10, 31, 120, 4, 2, 1000, 23, 34, 30, 42, 1, + 45, 24, 15, 32, 111, 35, 25, 252, 222, 66234, 2325, 23423, 2355, + 745, 579, 875, 33, 66, 345, 4666, 2490, 100, 10, 3415, 234, 22, + 526, 372, 8432, 21, 58, 225, 865, 23, 13333, 35, 2523, 33}, + "long_array"), + std::make_tuple(std::vector{10, 20, 20, 10, 20, 10, 20, 10, 20}, "two_number_array"), + std::make_tuple(std::vector{10000, 9999, 9998, 4356, 3662, 3000, 2500, 2300, 2200, 2000, 1999, 1900, + 1843, 1000, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, + "end_to_begin_array")}; + +const auto kTestTasksList = ppc::util::AddFuncTask( + kTestParam, PPC_SETTINGS_krasnopevtseva_v_hoare_batcher_sort); + +const auto kGtestValues = ppc::util::ExpandToValues(kTestTasksList); + +const auto kPerfTestName = KrasnopevtsevaVRunFuncTestsThreads::PrintFuncTestName; + +INSTANTIATE_TEST_SUITE_P(HoareBatcherSort, KrasnopevtsevaVRunFuncTestsThreads, kGtestValues, kPerfTestName); + +} // namespace + +} // namespace krasnopevtseva_v_hoare_batcher_sort diff --git a/tasks/krasnopevtseva_v_hoare_batcher_sort/tests/performance/main.cpp b/tasks/krasnopevtseva_v_hoare_batcher_sort/tests/performance/main.cpp new file mode 100644 index 00000000..67480722 --- /dev/null +++ b/tasks/krasnopevtseva_v_hoare_batcher_sort/tests/performance/main.cpp @@ -0,0 +1,62 @@ +#include + +#include +#include +#include +#include + +#include "krasnopevtseva_v_hoare_batcher_sort/common/include/common.hpp" +#include "krasnopevtseva_v_hoare_batcher_sort/seq/include/ops_seq.hpp" +#include "util/include/perf_test_util.hpp" + +namespace krasnopevtseva_v_hoare_batcher_sort { + +class KrasnopevtsevaVRunPerfTestsThreads : public ppc::util::BaseRunPerfTests { + InType input_data_; + bool res_{}; + + void SetUp() override { + std::vector vec(100000); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(0, 100000000); + + for (size_t i = 0; i < 100000; ++i) { + vec[i] = dist(gen); + } + input_data_ = vec; + } + + bool CheckTestOutputData(OutType &output_data) final { + size_t size = output_data.size(); + res_ = true; + for (size_t i = 0; i < size - 1; i++) { + if (output_data[i] > output_data[i + 1]) { + res_ = false; + } + } + return res_; + } + InType GetTestInputData() final { + return input_data_; + } +}; + +TEST_P(KrasnopevtsevaVRunPerfTestsThreads, RunPerfModes) { + ExecuteTest(GetParam()); +} + +namespace { + +const auto kAllPerfTasks = ppc::util::MakeAllPerfTasks( + PPC_SETTINGS_krasnopevtseva_v_hoare_batcher_sort); + +const auto kGtestValues = ppc::util::TupleToGTestValues(kAllPerfTasks); + +const auto kPerfTestName = KrasnopevtsevaVRunPerfTestsThreads::CustomPerfTestName; + +INSTANTIATE_TEST_SUITE_P(RunModeTests, KrasnopevtsevaVRunPerfTestsThreads, kGtestValues, kPerfTestName); + +} // namespace + +} // namespace krasnopevtseva_v_hoare_batcher_sort