diff --git a/ex02/src/PmergeMe.cpp b/ex02/src/PmergeMe.cpp index 3da7370..bff03c1 100644 --- a/ex02/src/PmergeMe.cpp +++ b/ex02/src/PmergeMe.cpp @@ -1,242 +1,237 @@ #include "PmergeMe.hpp" #include -#include +#include +#include #include -#include +#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; - } + for (std::vector::const_iterator it = obj.begin(); it != obj.end(); ++it) + { + if (it != obj.begin()) + os << " "; + os << *it; + } - return os; + return os; } PmergeMe::PmergeMe(const int argc, const char **argv) : _comparisons(0) { - 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"); + 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); - } + _data_vector.push_back(value); + _data_deque.push_back(value); + } - if (!areAllUnique()) - throw std::invalid_argument("All inputs must be unique integers"); + 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"); + 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()); + _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) -{ -} + : _data_vector(other._data_vector), _data_deque(other._data_deque), _jacobstahl_numbers(other._jacobstahl_numbers) +{} -PmergeMe::~PmergeMe() -{ -} +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; + 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; + 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() { - _comparisons = 0; - sortVector(0); - std::cout << "Total comparisons: " << _comparisons << std::endl; - std::cout << (std::is_sorted(_data_vector.begin(), _data_vector.end()) ? "Sorted!!!" : "ERROR!!") << std::endl; - std::sort(_data_deque.begin(), _data_deque.end()); + _comparisons = 0; + sortVector(0); + std::cout << "Total comparisons: " << _comparisons << std::endl; + std::cout << (std::is_sorted(_data_vector.begin(), _data_vector.end()) ? "Sorted!!!" : "ERROR!!") << std::endl; + 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; + // #1 Create pairs and sort them + if (_data_vector.size() <= 1) + return; - size_t group_size = std::pow(2, level + 1); + size_t group_size = std::pow(2, level + 1); - int odd = _data_vector.size() % group_size; + int odd = _data_vector.size() % group_size; - std::vector left = std::vector(_data_vector.end() - odd, _data_vector.end()); + std::vector left = std::vector(_data_vector.end() - odd, _data_vector.end()); - _data_vector.erase(_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 (!less(_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); - } + for (size_t i = 0; i < _data_vector.size(); i += group_size) + { + if (!less(_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); + if (group_size < _data_vector.size()) + sortVector(level + 1); - std::vector main; - std::vector pend; + 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); // inserting b1 - auto it = _data_vector.begin() + group_size; // this is a1 - 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()); + // #3 Separate main and pend + group_size /= 2; + main.insert(main.end(), _data_vector.begin(), _data_vector.begin() + group_size); // inserting b1 + auto it = _data_vector.begin() + group_size; // this is a1 + while (it != _data_vector.end()) + { + main.insert(main.end(), it, it + group_size); + it += group_size; + if (it == _data_vector.end()) + break; + pend.insert(pend.end(), it, it + group_size); + it += group_size; + } + pend.insert(pend.end(), left.begin(), left.end()); - int i = 0; - while (!pend.empty()) - { - int sorted_in_main = std::pow(2, i + 2) -1 ; // TODO ?? - sorted_in_main = sorted_in_main > static_cast(main.size() / group_size) ? static_cast(main.size() / group_size) : sorted_in_main; + int i = 0; + while (!pend.empty()) + { + int sorted_in_main = std::pow(2, i + 2) - 1; // TODO ?? + sorted_in_main = sorted_in_main > static_cast(main.size() / group_size) + ? static_cast(main.size() / group_size) + : sorted_in_main; - int jacob_index = Jacobstahl().get(i + 3) - Jacobstahl().get(i + 2) - 1; - int start_index = std::min(jacob_index, static_cast(pend.size() / group_size) - 1); + int jacob_index = Jacobstahl().get(i + 3) - Jacobstahl().get(i + 2) - 1; + int start_index = std::min(jacob_index, static_cast(pend.size() / group_size) - 1); - for (int j = start_index; j >= 0; --j) - { + for (int j = start_index; j >= 0; --j) + { + insertVector(main, pend, j, sorted_in_main, group_size); + } - 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--; - } - - i++; - } - _data_vector = main; + 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 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; + 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::less(int a, int b) { - _comparisons++; - return a < b; + _comparisons++; + return a < b; } 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(); + 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; + if (pend.empty() || start_index < 0 || start_index >= static_cast(pend.size())) + return; - // 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; - // std::cout << main << " | " << std::setw(3) << value_to_insert << " | " << pend - // << " | start_index: " << start_index << " | right: " << right - // << " | group_size: " << group_size << (!std::is_sorted(main.begin(), main.end()) && group_size == 1 ? "<<<" : "") - // << std::endl; + // Use the last element in the group for binary search + int value_to_insert = pend[(start_index + 1) * group_size - 1]; - auto insert_pos = main.begin() + right * group_size; - int left = 0; + std::cout + // << main << " | " << std::setw(3) << value_to_insert << " | " << pend << " | pend_index: " << start_index + << " | main: " << main.size() / group_size << " | end: " << right << " | group_size: " << group_size + << (!std::is_sorted(main.begin(), main.end()) && group_size == 1 ? "<<<" : "") << std::endl; - while (left <= right) - { - int mid = left + (right - left) / 2; - int last_idx = std::min((mid + 1) * group_size, static_cast(main.size())) - 1; - if (less(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 ?? - } - } + auto insert_pos = main.begin() + right * group_size; + int left = 0; - main.insert(insert_pos, pend.begin() + start_index * group_size, pend.begin() + (start_index + 1) * group_size); - // std::cout << "After insertion: " << main << std::endl; + while (left < right) + { + int mid = left + (right - left) / 2; + int last_idx = std::min((mid + 1) * group_size, static_cast(main.size())) - 1; + if (less(main[last_idx], value_to_insert)) + { + left = mid + 1; + } + else + { + right = mid; + } + } + insert_pos = main.begin() + (left * group_size); - pend.erase(pend.begin() + start_index * group_size, pend.begin() + (start_index + 1) * group_size); + main.insert(insert_pos, pend.begin() + start_index * group_size, pend.begin() + (start_index + 1) * group_size); + + 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; + os << "Vector: " << obj.getPrintableVector() << "\n"; + os << "Deque: " << obj.getPrintableDeque(); + return os; }