#include "PmergeMe.hpp" #include #include #include #include #include #include #include #include #include std::ostream &operator<<(std::ostream &os, const std::vector &obj) { for (std::vector::const_iterator it = obj.begin(); it != obj.end(); ++it) { if (it != obj.begin()) os << " "; os << *it; } return os; } PmergeMe::PmergeMe(const int argc, const char **argv) { for (int i = 1; argv[i] != nullptr; ++i) { size_t pos; int value = std::stoi(argv[i], &pos); if (value < 0) throw std::invalid_argument("All inputs must be non-negative integers"); if (pos != std::strlen(argv[i])) throw std::invalid_argument("Invalid input: not a valid integer"); _data_vector.push_back(value); _data_deque.push_back(value); } if (!areAllUnique()) throw std::invalid_argument("All inputs must be unique integers"); if (_data_vector.size() != static_cast(argc) - 1 || _data_deque.size() != static_cast(argc) - 1) throw std::invalid_argument("Invalid input detected"); _jacobstahl_numbers = Jacobstahl().getUpTo(_data_vector.size()); } PmergeMe::PmergeMe(const PmergeMe &other) : _data_vector(other._data_vector), _data_deque(other._data_deque), _jacobstahl_numbers(other._jacobstahl_numbers) { } PmergeMe::~PmergeMe() { } PmergeMe &PmergeMe::operator=(const PmergeMe &other) { if (this != &other) { _data_vector = other._data_vector; _data_deque = other._data_deque; _jacobstahl_numbers = other._jacobstahl_numbers; } return *this; } std::ostream &PmergeMe::operator<<(std::ostream &os) const { os << "Vector: "; for (std::vector::const_iterator it = _data_vector.begin(); it != _data_vector.end(); ++it) { if (it != _data_vector.begin()) os << " "; os << *it; } os << "\nDeque: "; for (std::deque::const_iterator it = _data_deque.begin(); it != _data_deque.end(); ++it) { if (it != _data_deque.begin()) os << " "; os << *it; } return os; } void PmergeMe::sort() { sortVector(0); std::sort(_data_deque.begin(), _data_deque.end()); } void PmergeMe::sortVector(int level = 0) { // #1 Create pairs and sort them if (_data_vector.size() <= 1) return; size_t group_size = std::pow(2, level + 1); int odd = _data_vector.size() % group_size; std::vector left = std::vector(_data_vector.end() - odd, _data_vector.end()); _data_vector.erase(_data_vector.end() - odd, _data_vector.end()); for (size_t i = 0; i < _data_vector.size(); i += group_size) { if (_data_vector[i + group_size / 2 - 1] > _data_vector[i + group_size - 1]) std::swap_ranges(_data_vector.begin() + i, _data_vector.begin() + i + group_size / 2, _data_vector.begin() + i + group_size / 2); } if (group_size < _data_vector.size()) sortVector(level + 1); std::vector main; std::vector pend; // #3 Separate main and pend group_size /= 2; main.insert(main.end(), _data_vector.begin(), _data_vector.begin() + group_size); auto it = _data_vector.begin() + group_size; while (it != _data_vector.end()) { if (it + group_size > _data_vector.end()) group_size = _data_vector.end() - it; main.insert(main.end(), it, it + group_size); it += group_size; if (it == _data_vector.end()) break; if (it + group_size > _data_vector.end()) group_size = _data_vector.end() - it; pend.insert(pend.end(), it, it + group_size); it += group_size; } pend.insert(pend.end(), left.begin(), left.end()); int i = 0; int sorted_in_main = 3; // TODO ?? while (!pend.empty()) { int jacob_index = Jacobstahl().get(i + 3) - Jacobstahl().get(i + 2); int start_index = std::min(jacob_index, static_cast(pend.size() / group_size) - 1); for (int j = start_index; j >= 0; --j) { insertVector(main, pend, j, sorted_in_main, group_size); std::cout << "insertVector(main, pend, " << j << ", " << sorted_in_main << ", " << group_size << ")" << std::endl; } sorted_in_main += start_index + 1; // TODO ?? i++; } _data_vector = main; } std::string PmergeMe::getPrintableVector() const { std::string result; for (std::vector::const_iterator it = _data_vector.begin(); it != _data_vector.end(); ++it) { if (it != _data_vector.begin()) result += ", "; result += std::to_string(*it); } return result; } std::string PmergeMe::getPrintableDeque() const { std::string result; for (std::deque::const_iterator it = _data_deque.begin(); it != _data_deque.end(); ++it) { if (it != _data_deque.begin()) result += ", "; result += std::to_string(*it); } return result; } bool PmergeMe::areAllUnique() const { std::vector temp = _data_vector; // Create a copy std::sort(temp.begin(), temp.end()); auto it = std::unique(temp.begin(), temp.end()); return it == temp.end(); } void PmergeMe::insertVector(std::vector &main, std::vector &pend, int start_index, int right, int group_size) { if (pend.empty() || start_index < 0 || start_index >= static_cast(pend.size())) return; std::cout << main << " | " << pend << " | start_index: " << start_index << " | right: " << right << " | group_size: " << group_size << std::endl; // Use the last element in the group for binary search int value_to_insert = pend[(start_index + 1) * group_size - 1]; std::cout << "Value to insert: " << value_to_insert << std::endl; auto insert_pos = main.begin() + right * group_size; int left = 0; while (left <= right) { int mid = left + (right - left) / 2; int last_idx = std::min((mid + 1) * group_size, static_cast(main.size())) - 1; if (main[last_idx] < value_to_insert) { left = mid + 1; } else { right = mid - 1; insert_pos = main.begin() + (mid * group_size); // Insert before the start of the found group //TODO ?? } } main.insert(insert_pos, pend.begin() + start_index * group_size, pend.begin() + (start_index + 1) * group_size); std::cout << "After insertion: " << main << std::endl; pend.erase(pend.begin() + start_index * group_size, pend.begin() + (start_index + 1) * group_size); } std::ostream &operator<<(std::ostream &os, const PmergeMe &obj) { os << "Vector: " << obj.getPrintableVector() << "\n"; os << "Deque: " << obj.getPrintableDeque(); return os; }