diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3a7b272 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,52 @@ +{ + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "ranges": "cpp", + "span": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp" + } +} \ No newline at end of file diff --git a/common.mk b/common.mk index e1f8179..32014a0 100644 --- a/common.mk +++ b/common.mk @@ -6,7 +6,7 @@ # By: whaffman +#+ # # +#+ # # Created: 2025/03/21 15:00:16 by whaffman #+# #+# # -# Updated: 2025/03/21 15:04:44 by whaffman ######## odam.nl # +# Updated: 2025/09/02 11:40:20 by whaffman ######## odam.nl # # # # **************************************************************************** # @@ -15,7 +15,7 @@ VPATH = src SRC = $(notdir $(wildcard src/*.cpp)) OBJ = $(SRC:.cpp=.o) CC = c++ -CFLAGS = -Wall -Wextra -Werror -std=c++23 -MMD +CFLAGS = -Wall -Wextra -Werror -std=c++20 -MMD all: $(NAME) diff --git a/ex02/inc/PmergeMe.hpp b/ex02/inc/PmergeMe.hpp index 7b51bbc..0ca70d1 100644 --- a/ex02/inc/PmergeMe.hpp +++ b/ex02/inc/PmergeMe.hpp @@ -1,29 +1,33 @@ #pragma once - +#include "Jacobstahl.hpp" #include #include +#include +#include -template class PmergeMe { public: PmergeMe() = delete; - PmergeMe(const Container &container); + PmergeMe(const int argc, const char **argv); PmergeMe(const PmergeMe &other); ~PmergeMe(); PmergeMe &operator=(const PmergeMe &other); + std::ostream &operator<<(std::ostream &os) const; - void sort(); + void sort(); + void sortVector(int level); + std::string getPrintableVector() const; + std::string getPrintableDeque() const; private: - std::vector _data_vector; - std::deque _data_deque; - std::vector _jacobstahl_numbers; - - int getJacobstahlNumber(int n); - int getJacobstahlNumberRecursive(int n); - - + std::vector _data_vector; + std::deque _data_deque; + std::vector _jacobstahl_numbers; + bool areAllUnique() const; + void insertVector(std::vector &main, std::vector &pend, int start_index, int right, int group_size); }; + +std::ostream &operator<<(std::ostream &os, const PmergeMe &obj); \ No newline at end of file diff --git a/ex02/src/PmergeMe.cpp b/ex02/src/PmergeMe.cpp index e69de29..99d3318 100644 --- a/ex02/src/PmergeMe.cpp +++ b/ex02/src/PmergeMe.cpp @@ -0,0 +1,236 @@ +#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() +{ + // Implement the sorting algorithm using _data_vector and _data_deque + // This is a placeholder for the actual sorting logic + 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 = 2; + 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; + 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; + // // Find the group in pend starting at start_index + // if (start_index + group_size > static_cast(pend.size())) + // group_size = pend.size() - start_index; + // if (group_size <= 0) + // 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]; + + // Binary search in main for insertion position + // Binary search comparing only the last values of each group in main + auto insert_pos = main.begin() + right; + int left = 0; + // right = (main.size() + group_size - 1) / group_size - 1; // number of groups - 1 + + 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() + last_idx; + } + } + + // Insert the whole group before insert_pos + main.insert(insert_pos, pend.begin() + start_index * group_size, pend.begin() + (start_index + 1) * group_size); + std::cout << "After insertion: " << main << std::endl; + // Erase the group from pend + 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; +} diff --git a/ex02/src/main.cpp b/ex02/src/main.cpp index 9359fde..b276b28 100644 --- a/ex02/src/main.cpp +++ b/ex02/src/main.cpp @@ -1,27 +1,22 @@ #include "Jacobstahl.hpp" +#include "PmergeMe.hpp" #include -int main() +int main(const int argc, const char **argv) { - Jacobstahl jacobstahl; - std::cout << "First 10 Jacobstahl numbers:" << std::endl; - - for (int i = 0; i < 10; ++i) + try { - std::cout << "Jacobstahl(" << i << ") = " << jacobstahl.get(i) << std::endl; + PmergeMe sorter(argc, argv); + std::cout << "Before sorting:\n" << sorter << std::endl; + sorter.sort(); + std::cout << "After sorting:\n" << sorter << std::endl; } - - - std::vector jacobstahl_numbers = jacobstahl.getUpTo(100); - std::cout << "Jacobstahl numbers up to 100:" << std::endl; - for (int num : jacobstahl_numbers) + catch (const std::invalid_argument &e) { - std::cout << num << " "; + std::cerr << "Error: " << e.what() << std::endl; + return 1; } - std::cout << std::endl; - - std::cout << "Jacobstahl number after 100: " << jacobstahl.getAfter(100) << std::endl; return 0; }