diff --git a/ex02/Main.cpp b/ex02/Main.cpp index e8c1d34..744aba2 100644 --- a/ex02/Main.cpp +++ b/ex02/Main.cpp @@ -4,9 +4,7 @@ int main(int ac, char **av) { PmergeMe pm; try { - pm.parseInput(ac, av); - pm.printVector(); - pm.printDeque(); + pm.run(ac, av); } catch (const std::exception &e) { std::cerr << e.what() << std::endl; return 1; diff --git a/ex02/PmergeMe b/ex02/PmergeMe new file mode 100755 index 0000000..d155d19 Binary files /dev/null and b/ex02/PmergeMe differ diff --git a/ex02/PmergeMe.cpp b/ex02/PmergeMe.cpp index e1963c0..ed48f8e 100644 --- a/ex02/PmergeMe.cpp +++ b/ex02/PmergeMe.cpp @@ -42,7 +42,8 @@ void PmergeMe::parseInput(int ac, char **av) for (int i = 1; i < ac; i++) { std::istringstream ss(av[i]); - while (ss >> token) { + while (ss >> token) + { std::istringstream iss(token); if (!(iss >> n) || !iss.eof() || n < 0) throw std::runtime_error("Error"); @@ -55,3 +56,239 @@ void PmergeMe::parseInput(int ac, char **av) if (_vec.empty()) throw std::runtime_error("Error"); } + +void PmergeMe::run(int ac, char **av) +{ + std::cout << std::fixed << std::setprecision(5); + parseInput(ac, av); + std::cout << "Before: "; + printVector(); + sortVector(); + sortDeque(); + std::cout << "After: "; + printVector(); + std::cout << "Time to process a range of " << _vec.size() << " elements with std::vector : " << _vecTime << " us" << std::endl; + std::cout << "Time to process a range of " << _deq.size() << " elements with std::deque : " << _deqTime << " us" << std::endl; +} + +void PmergeMe::sortVector() +{ + clock_t start = clock(); + _vec = fordJohnsonVec(_vec); + clock_t end = clock(); + _vecTime = (double)(end - start) * 1e6 / CLOCKS_PER_SEC; +} + +std::vector > makePairs(std::vector v) +{ + std::vector > pairs; + for (size_t i = 0; i + 1 < v.size(); i += 2) + { + int a = v[i]; + int b = v[i + 1]; + if (a >= b) + pairs.push_back(std::make_pair(a, b)); + else + pairs.push_back(std::make_pair(b, a)); + } + return pairs; +} + +std::vector > reorderPairs(std::vector > pairs, std::vector winners) +{ + std::vector > reordered; + for (size_t i = 0; i < winners.size(); i++) + { + for (size_t j = 0; j < pairs.size(); j++) + { + if (pairs[j].first == winners[i]) + { + reordered.push_back(pairs[j]); + break; + } + } + } + return reordered; +} + +std::vector generateInsertionOrder(std::vector pend) +{ + std::vector order; + std::vector jacob; + jacob.push_back(0); + jacob.push_back(1); + while (jacob.back() <= pend.size()) + jacob.push_back(jacob.back() + 2 * jacob[jacob.size() - 2]); + for (size_t k = 3; k < jacob.size(); k++) + { + size_t high = jacob[k] - 2; + if (high >= pend.size()) + high = pend.size() - 1; + size_t low = jacob[k - 1] - 1; + for (size_t idx = high + 1; idx > low; idx--) + order.push_back(idx - 1); + } + return order; +} + +std::vector PmergeMe::fordJohnsonVec(std::vector v) +{ + if (v.size() <= 1) + return v; + + std::vector > pairs = makePairs(v); + int straggler = 0; + bool hasStraggler = false; + if (v.size() % 2 != 0) + { + straggler = v.back(); + hasStraggler = true; + } + + std::vector winners; + for (size_t i = 0; i < pairs.size(); i++) + winners.push_back(pairs[i].first); + winners = fordJohnsonVec(winners); + pairs = reorderPairs(pairs, winners); + + std::vector mainChain; + mainChain.push_back(pairs[0].second); + for (size_t i = 0; i < pairs.size(); i++) + { + mainChain.push_back(pairs[i].first); + } + + std::vector pend; + for (size_t i = 1; i < pairs.size(); i++) + { + pend.push_back(pairs[i].second); + } + + std::vector order = generateInsertionOrder(pend); + for (size_t i = 0; i < order.size(); i++) + { + int value = pend[order[i]]; + int aiValue = pairs[order[i] + 1].first; + std::vector::iterator aiPos = std::find(mainChain.begin(), mainChain.end(), aiValue); + std::vector::iterator insertPos = std::upper_bound(mainChain.begin(), aiPos, value); + mainChain.insert(insertPos, value); + } + + if (hasStraggler) + { + std::vector::iterator insertPos = std::upper_bound(mainChain.begin(), mainChain.end(), straggler); + mainChain.insert(insertPos, straggler); + } + return mainChain; +} + +void PmergeMe::sortDeque() +{ + clock_t start = clock(); + _deq = fordJohnsonDeque(_deq); + clock_t end = clock(); + _deqTime = (double)(end - start) * 1e6 / CLOCKS_PER_SEC; +} + +std::deque > makePairs(std::deque d) +{ + std::deque > pairs; + for (size_t i = 0; i + 1 < d.size(); i += 2) + { + int a = d[i]; + int b = d[i + 1]; + if (a >= b) + pairs.push_back(std::make_pair(a, b)); + else + pairs.push_back(std::make_pair(b, a)); + } + return pairs; +} + +std::deque > reorderPairs(std::deque > pairs, std::deque winners) +{ + std::deque > reordered; + for (size_t i = 0; i < winners.size(); i++) + { + for (size_t j = 0; j < pairs.size(); j++) + { + if (pairs[j].first == winners[i]) + { + reordered.push_back(pairs[j]); + break; + } + } + } + return reordered; +} + +std::deque generateInsertionOrder(std::deque pend) +{ + std::deque order; + std::deque jacob; + jacob.push_back(0); + jacob.push_back(1); + while (jacob.back() <= pend.size()) + jacob.push_back(jacob.back() + 2 * jacob[jacob.size() - 2]); + for (size_t k = 3; k < jacob.size(); k++) + { + size_t high = jacob[k] - 2; + if (high >= pend.size()) + high = pend.size() - 1; + size_t low = jacob[k - 1] - 1; + for (size_t idx = high + 1; idx > low; idx--) + order.push_back(idx - 1); + } + return order; +} + +std::deque PmergeMe::fordJohnsonDeque(std::deque d) +{ + if (d.size() <= 1) + return d; + + std::deque > pairs = makePairs(d); + int straggler = 0; + bool hasStraggler = false; + if (d.size() % 2 != 0) + { + straggler = d.back(); + hasStraggler = true; + } + + std::deque winners; + for (size_t i = 0; i < pairs.size(); i++) + winners.push_back(pairs[i].first); + winners = fordJohnsonDeque(winners); + pairs = reorderPairs(pairs, winners); + + std::deque mainChain; + mainChain.push_back(pairs[0].second); + for (size_t i = 0; i < pairs.size(); i++) + { + mainChain.push_back(pairs[i].first); + } + + std::deque pend; + for (size_t i = 1; i < pairs.size(); i++) + { + pend.push_back(pairs[i].second); + } + + std::deque order = generateInsertionOrder(pend); + for (size_t i = 0; i < order.size(); i++) + { + int value = pend[order[i]]; + int aiValue = pairs[order[i] + 1].first; + std::deque::iterator aiPos = std::find(mainChain.begin(), mainChain.end(), aiValue); + std::deque::iterator insertPos = std::upper_bound(mainChain.begin(), aiPos, value); + mainChain.insert(insertPos, value); + } + + if (hasStraggler) + { + std::deque::iterator insertPos = std::upper_bound(mainChain.begin(), mainChain.end(), straggler); + mainChain.insert(insertPos, straggler); + } + return mainChain; +} \ No newline at end of file diff --git a/ex02/PmergeMe.hpp b/ex02/PmergeMe.hpp index 432a686..803eaf9 100644 --- a/ex02/PmergeMe.hpp +++ b/ex02/PmergeMe.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include class PmergeMe @@ -23,6 +24,8 @@ class PmergeMe private: std::vector _vec; std::deque _deq; + double _vecTime; + double _deqTime; void printDeque() const; void printVector() const; @@ -32,6 +35,8 @@ class PmergeMe void sortVector(); void sortDeque(); + std::vector fordJohnsonVec(std::vector v); + std::deque fordJohnsonDeque(std::deque v); }; diff --git a/ex02/obj/Main.o b/ex02/obj/Main.o new file mode 100644 index 0000000..09500d7 Binary files /dev/null and b/ex02/obj/Main.o differ diff --git a/ex02/obj/PmergeMe.o b/ex02/obj/PmergeMe.o new file mode 100644 index 0000000..2c6c1b0 Binary files /dev/null and b/ex02/obj/PmergeMe.o differ