diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e14407e..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "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", - "ctime": "cpp", - "iomanip": "cpp", - "sstream": "cpp", - "*.tpp": "cpp", - "chrono": "cpp", - "list": "cpp", - "ratio": "cpp" - } -} \ No newline at end of file diff --git a/common.mk b/common.mk index b8b74af..732934a 100644 --- a/common.mk +++ b/common.mk @@ -21,9 +21,6 @@ all: $(NAME) -include $(OBJ:.o=.d) -run: all - ./$(NAME) - $(NAME): $(OBJ) $(CC) $(CFLAGS) $(OBJ) -o $(NAME) diff --git a/ex00/Makefile b/ex00/Makefile index a2d4582..7a9b379 100644 --- a/ex00/Makefile +++ b/ex00/Makefile @@ -1,2 +1,5 @@ NAME := btc -include ../common.mk \ No newline at end of file +include ../common.mk + +run: all + ./$(NAME) input.txt diff --git a/ex00/dat2a.csv b/ex00/data.csv similarity index 100% rename from ex00/dat2a.csv rename to ex00/data.csv diff --git a/ex00/inc/BitcoinExchange.hpp b/ex00/inc/BitcoinExchange.hpp index 9387e5f..ceb6080 100644 --- a/ex00/inc/BitcoinExchange.hpp +++ b/ex00/inc/BitcoinExchange.hpp @@ -2,24 +2,26 @@ #include #include -#include -#include -#include -#include -#include -#include #include class BitcoinExchange { public: + // Constructors BitcoinExchange() = delete; BitcoinExchange(const std::string &data_file); + + // Copy constructor and copy assignment operator BitcoinExchange(const BitcoinExchange &other); - ~BitcoinExchange(); BitcoinExchange &operator=(const BitcoinExchange &other); - void printData() const; + // Move constructor and move assignment operator + BitcoinExchange(BitcoinExchange &&other) noexcept; + BitcoinExchange &operator=(BitcoinExchange &&other) noexcept; + + // Destructor + ~BitcoinExchange(); + void loadInputFile(const std::string &filename); class FileNotFoundException : public std::exception @@ -59,4 +61,4 @@ private: void loadDataFile(const std::string &filename); float getRate(long timestamp) const; float getValue(long timestamp, float amount) const; -}; \ No newline at end of file +}; diff --git a/ex00/src/BitcoinExchange.cpp b/ex00/src/BitcoinExchange.cpp index 88f6434..7c52dc8 100644 --- a/ex00/src/BitcoinExchange.cpp +++ b/ex00/src/BitcoinExchange.cpp @@ -2,7 +2,10 @@ #include #include #include -#include +#include +#include +#include +#include BitcoinExchange::BitcoinExchange(const std::string &data_file) { @@ -13,6 +16,10 @@ BitcoinExchange::BitcoinExchange(const BitcoinExchange &other) : _data(other._da { } +BitcoinExchange::BitcoinExchange(BitcoinExchange &&other) noexcept : _data(std::move(other._data)) +{ +} + BitcoinExchange::~BitcoinExchange() { } @@ -26,21 +33,26 @@ BitcoinExchange &BitcoinExchange::operator=(const BitcoinExchange &other) return *this; } -void BitcoinExchange::printData() const +BitcoinExchange &BitcoinExchange::operator=(BitcoinExchange &&other) noexcept { - for (std::map::const_iterator it = _data.begin(); it != _data.end(); ++it) + if (this != &other) { - std::cout << it->first << " => " << it->second << std::endl; + _data = std::move(other._data); } + return *this; } void trimInPlace(std::string &str) { - // Trim from right - str.erase(str.find_last_not_of(" \t\n\r") + 1); - - // Trim from left - str.erase(0, str.find_first_not_of(" \t\n\r")); + const std::string whitespace = " \t\n\r"; + size_t first = str.find_first_not_of(whitespace); + if (first == std::string::npos) + { + str.clear(); + return; + } + size_t last = str.find_last_not_of(whitespace); + str = str.substr(first, last - first + 1); } std::pair split(const std::string &str, char delimiter) @@ -61,14 +73,38 @@ std::pair split(const std::string &str, char delimiter { throw BitcoinExchange::LineFormatException(); } - if (second.find_first_not_of("-0123456789.") != std::string::npos) - { - throw BitcoinExchange::LineFormatException(); - } return {first, second}; } +static bool isValidDateFormat(const std::string &date) +{ + if (date.size() != 10) + return false; + for (size_t i = 0; i < date.size(); ++i) + { + if (i == 4 || i == 7) + { + if (date[i] != '-') + return false; + } + else if (!std::isdigit(static_cast(date[i]))) + { + return false; + } + } + return true; +} + +static float parseValue(const std::string &value) +{ + char *end = NULL; + float parsed = std::strtof(value.c_str(), &end); + if (end == value.c_str() || *end != '\0') + throw BitcoinExchange::LineFormatException(); + return parsed; +} + void BitcoinExchange::loadDataFile(const std::string &filename) { std::ifstream rate_file(filename); @@ -83,12 +119,12 @@ void BitcoinExchange::loadDataFile(const std::string &filename) { std::pair parts = split(line, ','); long timestamp = getTimestamp(parts.first); - float value = std::stof(parts.second); + float value = parseValue(parts.second); _data[timestamp] = value; } catch (std::exception &e) { - std::cerr << e.what() << std::endl; + (void)e; } } } @@ -108,26 +144,50 @@ void BitcoinExchange::loadInputFile(const std::string &filename) try { std::pair parts = split(line, '|'); - long timestamp = getTimestamp(parts.first); - float value = std::stof(parts.second); + long timestamp; + try + { + timestamp = getTimestamp(parts.first); + } + catch (const DateInvalidException &e) + { + (void)e; + std::cerr << "Error: bad input => " << parts.first << std::endl; + continue; + } + float value = parseValue(parts.second); if (value < 0) throw ValueNegativeException(); if (value > 1000) throw ValueTooLargeException(); - std::cout << parts.first << " => " << getValue(timestamp, value) << std::endl; + float converted = getValue(timestamp, value); + std::cout << parts.first << " => " << parts.second << " = " << converted << std::endl; + } + catch (const ValueNegativeException &e) + { + std::cerr << e.what() << std::endl; + } + catch (const ValueTooLargeException &e) + { + std::cerr << e.what() << std::endl; } catch (std::exception &e) { - std::cerr << e.what() << std::endl; + (void)e; + std::cerr << "Error: bad input => " << line << std::endl; } } } float BitcoinExchange::getRate(long timestamp) const { - auto it = _data.upper_bound(timestamp); - if (it != _data.begin()) - --it; + if (_data.empty()) + throw LineFormatException(); + + std::map::const_iterator it = _data.upper_bound(timestamp); + if (it == _data.begin()) + throw DateInvalidException(); + --it; return it->second; } @@ -138,34 +198,45 @@ float BitcoinExchange::getValue(long timestamp, float amount) const long BitcoinExchange::getTimestamp(const std::string &date) const { - std::stringstream ss(date); - std::tm tm = {}; - ss >> std::get_time(&tm, "%Y-%m-%d"); - if (ss.fail()) - throw std::invalid_argument("Error: Invalid date format: " + std::string(date)); - return static_cast(std::mktime(&tm)); + if (!isValidDateFormat(date)) + throw DateInvalidException(); + + int year = std::atoi(date.substr(0, 4).c_str()); + int month = std::atoi(date.substr(5, 2).c_str()); + int day = std::atoi(date.substr(8, 2).c_str()); + + const std::chrono::year_month_day ymd( + std::chrono::year(year), + std::chrono::month(static_cast(month)), + std::chrono::day(static_cast(day)) + ); + + if (!ymd.ok()) + throw DateInvalidException(); + + return static_cast(year * 10000 + month * 100 + day); } const char *BitcoinExchange::FileNotFoundException::what() const noexcept { - return "Error: File not found"; + return "Error: could not open file."; } const char *BitcoinExchange::LineFormatException::what() const noexcept { - return "Error: Line format is incorrect"; + return "Error: bad input"; } const char *BitcoinExchange::ValueNegativeException::what() const noexcept { - return "Error: Value is negative"; + return "Error: not a positive number."; } const char *BitcoinExchange::ValueTooLargeException::what() const noexcept { - return "Error: Value is too large"; + return "Error: too large a number."; } const char *BitcoinExchange::DateInvalidException::what() const noexcept { - return "Error: Date is invalid"; + return "Error: bad input"; } diff --git a/ex00/src/main.cpp b/ex00/src/main.cpp index 9f964cd..87c3806 100644 --- a/ex00/src/main.cpp +++ b/ex00/src/main.cpp @@ -1,13 +1,11 @@ #include "BitcoinExchange.hpp" -#include #include -#include int main (int argc, char **argv) { if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; + std::cerr << "Error: could not open file." << std::endl; return 1; } @@ -28,4 +26,4 @@ int main (int argc, char **argv) } return 0; -} \ No newline at end of file +} diff --git a/ex01/Makefile b/ex01/Makefile index 57c02d6..80d865b 100644 --- a/ex01/Makefile +++ b/ex01/Makefile @@ -1,2 +1,5 @@ NAME := RPN -include ../common.mk \ No newline at end of file +include ../common.mk + +run: all + ./$(NAME) "8 9 * 9 - 9 - 9 - 4 - 1 +" diff --git a/ex01/inc/RPN.hpp b/ex01/inc/RPN.hpp index fc7c347..c60500d 100644 --- a/ex01/inc/RPN.hpp +++ b/ex01/inc/RPN.hpp @@ -6,11 +6,21 @@ class RPN { public: + // Constructors RPN(); RPN(std::string expression); + + // Copy constructor and copy assignment operator RPN(const RPN &other); - ~RPN(); RPN &operator=(const RPN &other); + + // Move constructor and move assignment operator + RPN(RPN &&other) noexcept; + RPN &operator=(RPN &&other) noexcept; + + // Destructor + ~RPN(); + void setExpression(std::string expression); int evaluate(); @@ -44,5 +54,4 @@ private: bool isWellformed() const; bool isOperator(char c) const; int applyOperator(int a, int b, char op) const; - void printStack(std::stack stack) const; }; diff --git a/ex01/src/RPN.cpp b/ex01/src/RPN.cpp index e04c684..9b3982d 100644 --- a/ex01/src/RPN.cpp +++ b/ex01/src/RPN.cpp @@ -1,9 +1,9 @@ #include "RPN.hpp" -#include #include #include -#include +#include +#include RPN::RPN() : _expression("") { @@ -17,6 +17,10 @@ RPN::RPN(const RPN &other) : _expression(other._expression) { } +RPN::RPN(RPN &&other) noexcept : _expression(std::move(other._expression)) +{ +} + RPN::~RPN() { } @@ -30,6 +34,15 @@ RPN &RPN::operator=(const RPN &other) return *this; } +RPN &RPN::operator=(RPN &&other) noexcept +{ + if (this != &other) + { + _expression = std::move(other._expression); + } + return *this; +} + void RPN::setExpression(std::string expression) { _expression = expression; @@ -64,8 +77,6 @@ int RPN::evaluate() { throw RPN::InvalidCharacterException(); } - // std::cout << "Stack after processing '" << c << "': "; - // printStack(stack); } if (stack.size() != 1) throw RPN::InvalidExpressionException(); @@ -124,33 +135,6 @@ int RPN::applyOperator(int a, int b, char op) const return 0; } } - -void RPN::printStack(std::stack stack) const -{ - if (stack.empty()) - { - std::cout << "[]\n"; - return; - } - - std::stack temp; - while (!stack.empty()) - { - temp.push(stack.top()); - stack.pop(); - } - - std::cout << "["; - while (!temp.empty()) - { - std::cout << temp.top(); - temp.pop(); - if (!temp.empty()) - std::cout << ", "; - } - std::cout << "]\n"; -} - const char *RPN::NoExpressionException::NoExpressionException::what() const noexcept { return "No expression provided."; @@ -169,4 +153,4 @@ const char *RPN::DivisionByZeroException::DivisionByZeroException::what() const const char *RPN::InvalidCharacterException::InvalidCharacterException::what() const noexcept { return "Invalid character in expression."; -} \ No newline at end of file +} diff --git a/ex02/Makefile b/ex02/Makefile index 274982f..9fc3694 100644 --- a/ex02/Makefile +++ b/ex02/Makefile @@ -1,2 +1,5 @@ NAME = PmergeMe -include ../common.mk \ No newline at end of file +include ../common.mk + +run: all + ./$(NAME) $$(shuf -i 1-100000 -n 30 | tr '\n' ' ') diff --git a/ex02/inc/Jacobstahl.hpp b/ex02/inc/Jacobstahl.hpp index 65ad3f3..f309b7b 100644 --- a/ex02/inc/Jacobstahl.hpp +++ b/ex02/inc/Jacobstahl.hpp @@ -7,12 +7,12 @@ class Jacobstahl public: Jacobstahl(); Jacobstahl(const Jacobstahl &other); + Jacobstahl(Jacobstahl &&other) noexcept; Jacobstahl &operator=(const Jacobstahl &other); + Jacobstahl &operator=(Jacobstahl &&other) noexcept; ~Jacobstahl(); int get(int n); - std::vector getUpTo(int n); - int getAfter(int n); private: int getRecursive(int n); diff --git a/ex02/inc/PmergeMe.hpp b/ex02/inc/PmergeMe.hpp index f02c998..c480dcd 100644 --- a/ex02/inc/PmergeMe.hpp +++ b/ex02/inc/PmergeMe.hpp @@ -1,9 +1,7 @@ #pragma once #include "Jacobstahl.hpp" #include -#include #include -#include template class PmergeMe @@ -12,18 +10,21 @@ public: PmergeMe() = delete; PmergeMe(const int argc, const char **argv); PmergeMe(const PmergeMe &other); + PmergeMe(PmergeMe &&other) noexcept; ~PmergeMe(); PmergeMe &operator=(const PmergeMe &other); + PmergeMe &operator=(PmergeMe &&other) noexcept; void sort(); std::string getString() const; int getComparisons() const; + long long getTimeUs() const; private: Container _data; - std::vector _jacobstahl_numbers; int _comparisons; + long long _time_us; bool less(int a, int b); bool areAllUnique() const; @@ -34,4 +35,4 @@ private: template std::ostream &operator<<(std::ostream &os, const PmergeMe &obj); -#include "PmergeMe.tpp" \ No newline at end of file +#include "PmergeMe.tpp" diff --git a/ex02/inc/PmergeMe.tpp b/ex02/inc/PmergeMe.tpp index 0c53db4..df570ea 100644 --- a/ex02/inc/PmergeMe.tpp +++ b/ex02/inc/PmergeMe.tpp @@ -3,15 +3,12 @@ #include "PmergeMe.hpp" #include -#include #include #include -#include -#include #include #include -#include #include +#include template std::string getTypeName() @@ -24,7 +21,7 @@ std::string getTypeName() } template -PmergeMe::PmergeMe(const int argc, const char **argv) : _comparisons(0) +PmergeMe::PmergeMe(const int argc, const char **argv) : _comparisons(0), _time_us(0) { for (int i = 1; argv[i] != nullptr; ++i) { @@ -54,13 +51,17 @@ PmergeMe::PmergeMe(const int argc, const char **argv) : _comparisons( if (_data.size() != static_cast(argc) - 1 || _data.empty()) throw std::invalid_argument("Invalid input detected"); - - _jacobstahl_numbers = Jacobstahl().getUpTo(_data.size()); } template PmergeMe::PmergeMe(const PmergeMe &other) - : _data(other._data), _jacobstahl_numbers(other._jacobstahl_numbers) + : _data(other._data), _comparisons(other._comparisons), _time_us(other._time_us) +{ +} + +template +PmergeMe::PmergeMe(PmergeMe &&other) noexcept + : _data(std::move(other._data)), _comparisons(other._comparisons), _time_us(other._time_us) { } @@ -73,7 +74,20 @@ PmergeMe &PmergeMe::operator=(const PmergeMe &o if (this != &other) { _data = other._data; - _jacobstahl_numbers = other._jacobstahl_numbers; + _comparisons = other._comparisons; + _time_us = other._time_us; + } + return *this; +} + +template +PmergeMe &PmergeMe::operator=(PmergeMe &&other) noexcept +{ + if (this != &other) + { + _data = std::move(other._data); + _comparisons = other._comparisons; + _time_us = other._time_us; } return *this; } @@ -89,8 +103,7 @@ void PmergeMe::sort() // std::cout << "Total comparisons: " << _comparisons << std::endl; // std::cout << (std::is_sorted(_data_vector.begin(), _data_vector.end()) ? "Sorted!!!" : "ERROR!!") << std::endl; auto time_end = std::chrono::high_resolution_clock::now(); - auto time_diff = std::chrono::duration_cast(time_end - time_start).count(); - std::cout << "Time to process a range of " << _data.size() << " elements with " << getTypeName() << ": " << time_diff << " us" << std::endl; + _time_us = std::chrono::duration_cast(time_end - time_start).count(); } template @@ -100,7 +113,7 @@ std::string PmergeMe::getString() const for (auto it = _data.begin(); it != _data.end(); ++it) { if (it != _data.begin()) - result += ", "; + result += " "; result += std::to_string(*it); } return result; @@ -112,6 +125,12 @@ int PmergeMe::getComparisons() const return _comparisons; } +template +long long PmergeMe::getTimeUs() const +{ + return _time_us; +} + template bool PmergeMe::less(int a, int b) { diff --git a/ex02/src/Jacobstahl.cpp b/ex02/src/Jacobstahl.cpp index 48f57f6..5dba560 100644 --- a/ex02/src/Jacobstahl.cpp +++ b/ex02/src/Jacobstahl.cpp @@ -1,6 +1,7 @@ #include "Jacobstahl.hpp" #include +#include Jacobstahl::Jacobstahl() : _jacobstahl_numbers() { @@ -20,6 +21,17 @@ Jacobstahl &Jacobstahl::operator=(const Jacobstahl &other) return *this; } +Jacobstahl::Jacobstahl(Jacobstahl &&other) noexcept : _jacobstahl_numbers(std::move(other._jacobstahl_numbers)) {} + +Jacobstahl &Jacobstahl::operator=(Jacobstahl &&other) noexcept +{ + if (this != &other) + { + _jacobstahl_numbers = std::move(other._jacobstahl_numbers); + } + return *this; +} + Jacobstahl::~Jacobstahl() {} int Jacobstahl::get(int n) @@ -46,34 +58,3 @@ int Jacobstahl::getRecursive(int n) _jacobstahl_numbers[n] = getRecursive(n - 1) + 2 * getRecursive(n - 2); return _jacobstahl_numbers[n]; } - -std::vector Jacobstahl::getUpTo(int n) -{ - if (n < 0) - throw std::invalid_argument("n must be non-negative"); - - std::vector result; - while (true) - { - int number = get(result.size()); - if (number > n) - break; - result.push_back(number); - } - return result; -} - -int Jacobstahl::getAfter(int n) -{ - if (n < 0) - throw std::invalid_argument("n must be non-negative"); - - int index = 0; - while (true) - { - int number = get(index); - if (number > n) - return number; - index++; - } -} \ No newline at end of file diff --git a/ex02/src/PmergeMe.cpp b/ex02/src/PmergeMe.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/ex02/src/main.cpp b/ex02/src/main.cpp index ca15918..3010f10 100644 --- a/ex02/src/main.cpp +++ b/ex02/src/main.cpp @@ -1,4 +1,3 @@ -#include "Jacobstahl.hpp" #include "PmergeMe.hpp" #include #include @@ -8,18 +7,25 @@ int main(const int argc, const char **argv) { - try - { - PmergeMe > sorter_vector(argc, argv); - std::cout << "Before: " << sorter_vector << std::endl; - sorter_vector.sort(); - PmergeMe > sorter_deque(argc, argv); - sorter_deque.sort(); - std::cout << "After: " << sorter_deque << std::endl; - std::cout << "Total comparisons (vector): " << sorter_vector.getComparisons() << std::endl; - std::cout << "Total comparisons (deque): " << sorter_deque.getComparisons() << std::endl; + try + { + PmergeMe > sorter_vector(argc, argv); + PmergeMe > sorter_deque(argc, argv); - } + std::cout << "Before: " << sorter_vector << std::endl; + + sorter_vector.sort(); + sorter_deque.sort(); + + std::cout << "After: " << sorter_deque << std::endl; + std::cout << "Time to process a range of " << argc - 1 << " elements with std::vector : " + << sorter_vector.getTimeUs() << " us" << std::endl; + std::cout << "Time to process a range of " << argc - 1 << " elements with std::deque : " + << sorter_deque.getTimeUs() << " us" << std::endl; + // std::cout << "Total comparisons (vector): " << sorter_vector.getComparisons() << std::endl; + // std::cout << "Total comparisons (deque): " << sorter_deque.getComparisons() << std::endl; + + } catch (const std::invalid_argument &e) { std::cerr << "Error: " << e.what() << std::endl;