Compare commits
No commits in common. "main" and "Template-insert" have entirely different histories.
main
...
Template-i
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,5 +2,3 @@
|
|||||||
*.d
|
*.d
|
||||||
*.o
|
*.o
|
||||||
PmergeMe
|
PmergeMe
|
||||||
RPN
|
|
||||||
ex00/btc
|
|
||||||
|
|||||||
57
.vscode/settings.json
vendored
Normal file
57
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,13 +6,13 @@
|
|||||||
# By: whaffman <whaffman@student.codam.nl> +#+ #
|
# By: whaffman <whaffman@student.codam.nl> +#+ #
|
||||||
# +#+ #
|
# +#+ #
|
||||||
# Created: 2025/03/21 15:00:16 by whaffman #+# #+# #
|
# Created: 2025/03/21 15:00:16 by whaffman #+# #+# #
|
||||||
# Updated: 2025/09/08 16:11:34 by whaffman ######## odam.nl #
|
# Updated: 2025/09/02 11:40:20 by whaffman ######## odam.nl #
|
||||||
# #
|
# #
|
||||||
# **************************************************************************** #
|
# **************************************************************************** #
|
||||||
|
|
||||||
INC = -I./inc
|
INC = -I./inc
|
||||||
VPATH = src
|
VPATH = src
|
||||||
|
SRC = $(notdir $(wildcard src/*.cpp))
|
||||||
OBJ = $(SRC:.cpp=.o)
|
OBJ = $(SRC:.cpp=.o)
|
||||||
CC = c++
|
CC = c++
|
||||||
CFLAGS = -Wall -Wextra -Werror -std=c++20 -MMD
|
CFLAGS = -Wall -Wextra -Werror -std=c++20 -MMD
|
||||||
@ -21,6 +21,9 @@ all: $(NAME)
|
|||||||
|
|
||||||
-include $(OBJ:.o=.d)
|
-include $(OBJ:.o=.d)
|
||||||
|
|
||||||
|
run: all
|
||||||
|
./$(NAME)
|
||||||
|
|
||||||
$(NAME): $(OBJ)
|
$(NAME): $(OBJ)
|
||||||
$(CC) $(CFLAGS) $(OBJ) -o $(NAME)
|
$(CC) $(CFLAGS) $(OBJ) -o $(NAME)
|
||||||
|
|
||||||
@ -29,7 +32,6 @@ $(NAME): $(OBJ)
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJ)
|
rm -f $(OBJ)
|
||||||
rm -f $(OBJ:.o=.d)
|
|
||||||
|
|
||||||
fclean: clean
|
fclean: clean
|
||||||
rm -f $(NAME)
|
rm -f $(NAME)
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
NAME := btc
|
|
||||||
SRC := main.cpp BitcoinExchange.cpp
|
|
||||||
include ../common.mk
|
|
||||||
|
|
||||||
run: all
|
|
||||||
./$(NAME) input.txt
|
|
||||||
1613
ex00/data.csv
1613
ex00/data.csv
File diff suppressed because it is too large
Load Diff
@ -1,64 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
class BitcoinExchange
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructors
|
|
||||||
BitcoinExchange() = delete;
|
|
||||||
BitcoinExchange(const std::string &data_file);
|
|
||||||
|
|
||||||
// Copy constructor and copy assignment operator
|
|
||||||
BitcoinExchange(const BitcoinExchange &other);
|
|
||||||
BitcoinExchange &operator=(const BitcoinExchange &other);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual const char *what() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LineFormatException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual const char *what() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ValueNegativeException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual const char *what() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ValueTooLargeException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual const char *what() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DateInvalidException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual const char *what() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::map<long, float>
|
|
||||||
_data;
|
|
||||||
long getTimestamp(const std::string &date) const;
|
|
||||||
void loadDataFile(const std::string &filename);
|
|
||||||
float getRate(long timestamp) const;
|
|
||||||
float getValue(long timestamp, float amount) const;
|
|
||||||
};
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
date | value
|
|
||||||
2011-01-03 | 3
|
|
||||||
2011-01-03 | 2
|
|
||||||
2011-01-03 | 1
|
|
||||||
2011-01-03 | 1.2
|
|
||||||
2011-01-09 | 1
|
|
||||||
2016-04-12 | 3
|
|
||||||
|
|
||||||
2025-12-12 |2
|
|
||||||
2012-01-11 | -1
|
|
||||||
2001-42-42 | 2
|
|
||||||
2000-01-11 | 1
|
|
||||||
2012-01-11 | 2147483648
|
|
||||||
2012-01-11 | 1
|
|
||||||
2001-123-1 | 3
|
|
||||||
|
|
||||||
@ -1,242 +0,0 @@
|
|||||||
#include "BitcoinExchange.hpp"
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cctype>
|
|
||||||
#include <chrono>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
BitcoinExchange::BitcoinExchange(const std::string &data_file)
|
|
||||||
{
|
|
||||||
loadDataFile(data_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
BitcoinExchange::BitcoinExchange(const BitcoinExchange &other) : _data(other._data)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BitcoinExchange::BitcoinExchange(BitcoinExchange &&other) noexcept : _data(std::move(other._data))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BitcoinExchange::~BitcoinExchange()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BitcoinExchange &BitcoinExchange::operator=(const BitcoinExchange &other)
|
|
||||||
{
|
|
||||||
if (this != &other)
|
|
||||||
{
|
|
||||||
_data = other._data;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
BitcoinExchange &BitcoinExchange::operator=(BitcoinExchange &&other) noexcept
|
|
||||||
{
|
|
||||||
if (this != &other)
|
|
||||||
{
|
|
||||||
_data = std::move(other._data);
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void trimInPlace(std::string &str)
|
|
||||||
{
|
|
||||||
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<std::string, std::string> split(const std::string &str, char delimiter)
|
|
||||||
{
|
|
||||||
size_t pos = str.find(delimiter);
|
|
||||||
if (pos == std::string::npos)
|
|
||||||
{
|
|
||||||
throw BitcoinExchange::LineFormatException();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string first = str.substr(0, pos);
|
|
||||||
std::string second = str.substr(pos + 1);
|
|
||||||
|
|
||||||
trimInPlace(first);
|
|
||||||
trimInPlace(second);
|
|
||||||
|
|
||||||
if (first.empty() || second.empty())
|
|
||||||
{
|
|
||||||
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<unsigned char>(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);
|
|
||||||
if (!rate_file)
|
|
||||||
throw FileNotFoundException();
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
std::getline(rate_file, line);
|
|
||||||
while (std::getline(rate_file, line))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::pair<std::string, std::string> parts = split(line, ',');
|
|
||||||
long timestamp = getTimestamp(parts.first);
|
|
||||||
float value = parseValue(parts.second);
|
|
||||||
_data[timestamp] = value;
|
|
||||||
}
|
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
|
||||||
(void)e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BitcoinExchange::loadInputFile(const std::string &filename)
|
|
||||||
{
|
|
||||||
std::ifstream input_file(filename);
|
|
||||||
if (!input_file)
|
|
||||||
throw FileNotFoundException();
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
std::getline(input_file, line);
|
|
||||||
while (std::getline(input_file, line))
|
|
||||||
{
|
|
||||||
if (line.empty())
|
|
||||||
continue;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::pair<std::string, std::string> parts = split(line, '|');
|
|
||||||
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();
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
(void)e;
|
|
||||||
std::cerr << "Error: bad input => " << line << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float BitcoinExchange::getRate(long timestamp) const
|
|
||||||
{
|
|
||||||
if (_data.empty())
|
|
||||||
throw LineFormatException();
|
|
||||||
|
|
||||||
std::map<long, float>::const_iterator it = _data.upper_bound(timestamp);
|
|
||||||
if (it == _data.begin())
|
|
||||||
throw DateInvalidException();
|
|
||||||
--it;
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
float BitcoinExchange::getValue(long timestamp, float amount) const
|
|
||||||
{
|
|
||||||
return getRate(timestamp) * amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
long BitcoinExchange::getTimestamp(const std::string &date) const
|
|
||||||
{
|
|
||||||
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<unsigned>(month)),
|
|
||||||
std::chrono::day(static_cast<unsigned>(day))
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!ymd.ok())
|
|
||||||
throw DateInvalidException();
|
|
||||||
|
|
||||||
return static_cast<long>(year * 10000 + month * 100 + day);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *BitcoinExchange::FileNotFoundException::what() const noexcept
|
|
||||||
{
|
|
||||||
return "Error: could not open file.";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *BitcoinExchange::LineFormatException::what() const noexcept
|
|
||||||
{
|
|
||||||
return "Error: bad input";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *BitcoinExchange::ValueNegativeException::what() const noexcept
|
|
||||||
{
|
|
||||||
return "Error: not a positive number.";
|
|
||||||
}
|
|
||||||
const char *BitcoinExchange::ValueTooLargeException::what() const noexcept
|
|
||||||
{
|
|
||||||
return "Error: too large a number.";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *BitcoinExchange::DateInvalidException::what() const noexcept
|
|
||||||
{
|
|
||||||
return "Error: bad input";
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
#include "BitcoinExchange.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc != 2)
|
|
||||||
{
|
|
||||||
std::cerr << "Error: could not open file." << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
BitcoinExchange btcExchange("data.csv");
|
|
||||||
btcExchange.loadInputFile(argv[1]);
|
|
||||||
}
|
|
||||||
catch (const BitcoinExchange::FileNotFoundException &e)
|
|
||||||
{
|
|
||||||
std::cerr << e.what() << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << "An error occurred: " << e.what() << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
NAME := RPN
|
|
||||||
SRC := main.cpp RPN.cpp
|
|
||||||
include ../common.mk
|
|
||||||
|
|
||||||
run: all
|
|
||||||
./$(NAME) "8 9 * 9 - 9 - 9 - 4 - 1 +"
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
class RPN
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// Constructors
|
|
||||||
RPN();
|
|
||||||
RPN(std::string expression);
|
|
||||||
|
|
||||||
// Copy constructor and copy assignment operator
|
|
||||||
RPN(const RPN &other);
|
|
||||||
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();
|
|
||||||
|
|
||||||
class NoExpressionException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const char *what() const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class InvalidExpressionException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const char *what() const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DivisionByZeroException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const char *what() const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class InvalidCharacterException : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const char *what() const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string _expression;
|
|
||||||
|
|
||||||
bool isWellformed() const;
|
|
||||||
bool isOperator(char c) const;
|
|
||||||
int applyOperator(int a, int b, char op) const;
|
|
||||||
};
|
|
||||||
156
ex01/src/RPN.cpp
156
ex01/src/RPN.cpp
@ -1,156 +0,0 @@
|
|||||||
#include "RPN.hpp"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <stack>
|
|
||||||
#include <cctype>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
RPN::RPN() : _expression("")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RPN::RPN(std::string expression) : _expression(expression)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RPN::RPN(const RPN &other) : _expression(other._expression)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RPN::RPN(RPN &&other) noexcept : _expression(std::move(other._expression))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RPN::~RPN()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
RPN &RPN::operator=(const RPN &other)
|
|
||||||
{
|
|
||||||
if (this != &other)
|
|
||||||
{
|
|
||||||
_expression = other._expression;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RPN::evaluate()
|
|
||||||
{
|
|
||||||
if (_expression.empty())
|
|
||||||
throw RPN::NoExpressionException();
|
|
||||||
if (!isWellformed())
|
|
||||||
throw RPN::InvalidExpressionException();
|
|
||||||
std::stack<int> stack;
|
|
||||||
for (char c : _expression)
|
|
||||||
{
|
|
||||||
if (std::isspace(c))
|
|
||||||
continue;
|
|
||||||
if (std::isdigit(c))
|
|
||||||
stack.push(c - '0');
|
|
||||||
else if (isOperator(c))
|
|
||||||
{
|
|
||||||
if (stack.size() < 2)
|
|
||||||
throw RPN::InvalidExpressionException();
|
|
||||||
|
|
||||||
int b = stack.top();
|
|
||||||
stack.pop();
|
|
||||||
int a = stack.top();
|
|
||||||
stack.pop();
|
|
||||||
int result = applyOperator(a, b, c);
|
|
||||||
stack.push(result);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw RPN::InvalidCharacterException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (stack.size() != 1)
|
|
||||||
throw RPN::InvalidExpressionException();
|
|
||||||
return stack.top();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RPN::isWellformed() const
|
|
||||||
{
|
|
||||||
bool needs_space = false;
|
|
||||||
for (char c : _expression)
|
|
||||||
{
|
|
||||||
if (std::isspace(c))
|
|
||||||
{
|
|
||||||
if (needs_space)
|
|
||||||
needs_space = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (std::isdigit(c) || isOperator(c))
|
|
||||||
{
|
|
||||||
if (needs_space)
|
|
||||||
return false;
|
|
||||||
needs_space = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RPN::isOperator(char c) const
|
|
||||||
{
|
|
||||||
if (std::string("+-*/").find(c) != std::string::npos)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RPN::applyOperator(int a, int b, char op) const
|
|
||||||
{
|
|
||||||
switch (op)
|
|
||||||
{
|
|
||||||
case '+':
|
|
||||||
return a + b;
|
|
||||||
case '-':
|
|
||||||
return a - b;
|
|
||||||
case '*':
|
|
||||||
return a * b;
|
|
||||||
case '/':
|
|
||||||
if (b == 0)
|
|
||||||
throw RPN::DivisionByZeroException();
|
|
||||||
return a / b;
|
|
||||||
default:
|
|
||||||
throw RPN::InvalidExpressionException();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const char *RPN::NoExpressionException::NoExpressionException::what() const noexcept
|
|
||||||
{
|
|
||||||
return "No expression provided.";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *RPN::InvalidExpressionException::InvalidExpressionException::what() const noexcept
|
|
||||||
{
|
|
||||||
return "Invalid RPN expression.";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *RPN::DivisionByZeroException::DivisionByZeroException::what() const noexcept
|
|
||||||
{
|
|
||||||
return "Division by zero.";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *RPN::InvalidCharacterException::InvalidCharacterException::what() const noexcept
|
|
||||||
{
|
|
||||||
return "Invalid character in expression.";
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
#include "RPN.hpp"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
if (argc != 2)
|
|
||||||
{
|
|
||||||
std::cerr << "Usage: " << argv[0] << " <RPN expression>" << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
RPN rpn(argv[1]);
|
|
||||||
int result = rpn.evaluate();
|
|
||||||
std::cout << result << std::endl;
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << "Error: " << e.what() << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,6 +1,2 @@
|
|||||||
NAME := PmergeMe
|
NAME = PmergeMe
|
||||||
SRC := main.cpp Jacobstahl.cpp
|
|
||||||
include ../common.mk
|
include ../common.mk
|
||||||
|
|
||||||
run: all
|
|
||||||
./$(NAME) $$(shuf -i 1-100000 -n 30 | tr '\n' ' ')
|
|
||||||
|
|||||||
@ -7,12 +7,12 @@ class Jacobstahl
|
|||||||
public:
|
public:
|
||||||
Jacobstahl();
|
Jacobstahl();
|
||||||
Jacobstahl(const Jacobstahl &other);
|
Jacobstahl(const Jacobstahl &other);
|
||||||
Jacobstahl(Jacobstahl &&other) noexcept;
|
|
||||||
Jacobstahl &operator=(const Jacobstahl &other);
|
Jacobstahl &operator=(const Jacobstahl &other);
|
||||||
Jacobstahl &operator=(Jacobstahl &&other) noexcept;
|
|
||||||
~Jacobstahl();
|
~Jacobstahl();
|
||||||
|
|
||||||
int get(int n);
|
int get(int n);
|
||||||
|
std::vector<int> getUpTo(int n);
|
||||||
|
int getAfter(int n);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int getRecursive(int n);
|
int getRecursive(int n);
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Jacobstahl.hpp"
|
#include "Jacobstahl.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <deque>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
class PmergeMe
|
class PmergeMe
|
||||||
@ -10,21 +12,17 @@ public:
|
|||||||
PmergeMe() = delete;
|
PmergeMe() = delete;
|
||||||
PmergeMe(const int argc, const char **argv);
|
PmergeMe(const int argc, const char **argv);
|
||||||
PmergeMe(const PmergeMe &other);
|
PmergeMe(const PmergeMe &other);
|
||||||
PmergeMe(PmergeMe &&other) noexcept;
|
|
||||||
~PmergeMe();
|
~PmergeMe();
|
||||||
|
|
||||||
PmergeMe &operator=(const PmergeMe &other);
|
PmergeMe &operator=(const PmergeMe &other);
|
||||||
PmergeMe &operator=(PmergeMe &&other) noexcept;
|
|
||||||
|
|
||||||
void sort();
|
void sort();
|
||||||
std::string getString() const;
|
std::string getString() const;
|
||||||
int getComparisons() const;
|
|
||||||
long long getTimeUs() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Container _data;
|
Container _data;
|
||||||
|
std::vector<int> _jacobstahl_numbers;
|
||||||
int _comparisons;
|
int _comparisons;
|
||||||
long long _time_us;
|
|
||||||
|
|
||||||
bool less(int a, int b);
|
bool less(int a, int b);
|
||||||
bool areAllUnique() const;
|
bool areAllUnique() const;
|
||||||
|
|||||||
@ -3,31 +3,30 @@
|
|||||||
#include "PmergeMe.hpp"
|
#include "PmergeMe.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::string getTypeName()
|
std::string getTypeName() {
|
||||||
{
|
if (std::is_same_v<T, std::vector<int>>) return "std::vector<int> ";
|
||||||
if (std::is_same_v<T, std::vector<int>>)
|
if (std::is_same_v<T, std::deque<int>>) return "std::deque<int> ";
|
||||||
return "std::vector<int> ";
|
|
||||||
if (std::is_same_v<T, std::deque<int>>)
|
|
||||||
return "std::deque<int> ";
|
|
||||||
return typeid(T).name(); // fallback to mangled name
|
return typeid(T).name(); // fallback to mangled name
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
PmergeMe<Container>::PmergeMe(const int argc, const char **argv) : _comparisons(0), _time_us(0)
|
PmergeMe<Container>::PmergeMe(const int argc, const char **argv) : _comparisons(0)
|
||||||
{
|
{
|
||||||
for (int i = 1; argv[i] != nullptr; ++i)
|
for (int i = 1; argv[i] != nullptr; ++i)
|
||||||
{
|
{
|
||||||
size_t pos;
|
size_t pos;
|
||||||
try
|
|
||||||
{
|
|
||||||
int value = std::stoi(argv[i], &pos);
|
int value = std::stoi(argv[i], &pos);
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
throw std::invalid_argument("All inputs must be non-negative integers");
|
throw std::invalid_argument("All inputs must be non-negative integers");
|
||||||
@ -36,32 +35,19 @@ PmergeMe<Container>::PmergeMe(const int argc, const char **argv) : _comparisons(
|
|||||||
|
|
||||||
_data.push_back(value);
|
_data.push_back(value);
|
||||||
}
|
}
|
||||||
catch (const std::out_of_range &e)
|
|
||||||
{
|
|
||||||
throw std::out_of_range("Input value out of range");
|
|
||||||
}
|
|
||||||
catch (const std::invalid_argument &e)
|
|
||||||
{
|
|
||||||
throw std::invalid_argument("Invalid input: not a valid integer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!areAllUnique())
|
if (!areAllUnique())
|
||||||
throw std::invalid_argument("All inputs must be unique integers");
|
throw std::invalid_argument("All inputs must be unique integers");
|
||||||
|
|
||||||
if (_data.size() != static_cast<std::size_t>(argc) - 1 || _data.empty())
|
if (_data.size() != static_cast<std::size_t>(argc) - 1 || _data.empty())
|
||||||
throw std::invalid_argument("Invalid input detected");
|
throw std::invalid_argument("Invalid input detected");
|
||||||
|
|
||||||
|
_jacobstahl_numbers = Jacobstahl().getUpTo(_data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
PmergeMe<Container>::PmergeMe(const PmergeMe<Container> &other)
|
PmergeMe<Container>::PmergeMe(const PmergeMe<Container> &other)
|
||||||
: _data(other._data), _comparisons(other._comparisons), _time_us(other._time_us)
|
: _data(other._data), _jacobstahl_numbers(other._jacobstahl_numbers)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Container>
|
|
||||||
PmergeMe<Container>::PmergeMe(PmergeMe<Container> &&other) noexcept
|
|
||||||
: _data(std::move(other._data)), _comparisons(other._comparisons), _time_us(other._time_us)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,20 +60,7 @@ PmergeMe<Container> &PmergeMe<Container>::operator=(const PmergeMe<Container> &o
|
|||||||
if (this != &other)
|
if (this != &other)
|
||||||
{
|
{
|
||||||
_data = other._data;
|
_data = other._data;
|
||||||
_comparisons = other._comparisons;
|
_jacobstahl_numbers = other._jacobstahl_numbers;
|
||||||
_time_us = other._time_us;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Container>
|
|
||||||
PmergeMe<Container> &PmergeMe<Container>::operator=(PmergeMe<Container> &&other) noexcept
|
|
||||||
{
|
|
||||||
if (this != &other)
|
|
||||||
{
|
|
||||||
_data = std::move(other._data);
|
|
||||||
_comparisons = other._comparisons;
|
|
||||||
_time_us = other._time_us;
|
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -103,7 +76,8 @@ void PmergeMe<Container>::sort()
|
|||||||
// std::cout << "Total comparisons: " << _comparisons << std::endl;
|
// std::cout << "Total comparisons: " << _comparisons << std::endl;
|
||||||
// std::cout << (std::is_sorted(_data_vector.begin(), _data_vector.end()) ? "Sorted!!!" : "ERROR!!") << 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_end = std::chrono::high_resolution_clock::now();
|
||||||
_time_us = std::chrono::duration_cast<std::chrono::microseconds>(time_end - time_start).count();
|
auto time_diff = std::chrono::duration_cast<std::chrono::microseconds>(time_end - time_start).count();
|
||||||
|
std::cout << "Time to process a range of " << _data.size() << " elements with " << getTypeName<Container>() << ": " << time_diff << " us" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
@ -113,24 +87,12 @@ std::string PmergeMe<Container>::getString() const
|
|||||||
for (auto it = _data.begin(); it != _data.end(); ++it)
|
for (auto it = _data.begin(); it != _data.end(); ++it)
|
||||||
{
|
{
|
||||||
if (it != _data.begin())
|
if (it != _data.begin())
|
||||||
result += " ";
|
result += ", ";
|
||||||
result += std::to_string(*it);
|
result += std::to_string(*it);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Container>
|
|
||||||
int PmergeMe<Container>::getComparisons() const
|
|
||||||
{
|
|
||||||
return _comparisons;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Container>
|
|
||||||
long long PmergeMe<Container>::getTimeUs() const
|
|
||||||
{
|
|
||||||
return _time_us;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Container>
|
template <typename Container>
|
||||||
bool PmergeMe<Container>::less(int a, int b)
|
bool PmergeMe<Container>::less(int a, int b)
|
||||||
{
|
{
|
||||||
@ -236,3 +198,4 @@ std::ostream &operator<<(std::ostream &os, const PmergeMe<Container> &obj)
|
|||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
#include "Jacobstahl.hpp"
|
#include "Jacobstahl.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
Jacobstahl::Jacobstahl() : _jacobstahl_numbers()
|
Jacobstahl::Jacobstahl() : _jacobstahl_numbers()
|
||||||
{
|
{
|
||||||
@ -21,17 +20,6 @@ Jacobstahl &Jacobstahl::operator=(const Jacobstahl &other)
|
|||||||
return *this;
|
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() {}
|
Jacobstahl::~Jacobstahl() {}
|
||||||
|
|
||||||
int Jacobstahl::get(int n)
|
int Jacobstahl::get(int n)
|
||||||
@ -58,3 +46,34 @@ int Jacobstahl::getRecursive(int n)
|
|||||||
_jacobstahl_numbers[n] = getRecursive(n - 1) + 2 * getRecursive(n - 2);
|
_jacobstahl_numbers[n] = getRecursive(n - 1) + 2 * getRecursive(n - 2);
|
||||||
return _jacobstahl_numbers[n];
|
return _jacobstahl_numbers[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<int> Jacobstahl::getUpTo(int n)
|
||||||
|
{
|
||||||
|
if (n < 0)
|
||||||
|
throw std::invalid_argument("n must be non-negative");
|
||||||
|
|
||||||
|
std::vector<int> 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
26
ex02/src/PmergeMe.cpp
Normal file
26
ex02/src/PmergeMe.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include "PmergeMe.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include <deque>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, const std::vector<int> &obj)
|
||||||
|
{
|
||||||
|
for (std::vector<int>::const_iterator it = obj.begin(); it != obj.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it != obj.begin())
|
||||||
|
os << " ";
|
||||||
|
os << *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include "Jacobstahl.hpp"
|
||||||
#include "PmergeMe.hpp"
|
#include "PmergeMe.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -9,21 +10,12 @@ int main(const int argc, const char **argv)
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PmergeMe<std::vector<int> > sorter_vector(argc, argv);
|
PmergeMe<std::vector<int> > sorter(argc, argv);
|
||||||
|
std::cout << "Before: " << sorter << std::endl;
|
||||||
|
sorter.sort();
|
||||||
PmergeMe<std::deque<int> > sorter_deque(argc, argv);
|
PmergeMe<std::deque<int> > sorter_deque(argc, argv);
|
||||||
|
|
||||||
std::cout << "Before: " << sorter_vector << std::endl;
|
|
||||||
|
|
||||||
sorter_vector.sort();
|
|
||||||
sorter_deque.sort();
|
sorter_deque.sort();
|
||||||
|
|
||||||
std::cout << "After: " << sorter_deque << std::endl;
|
std::cout << "After: " << sorter_deque << std::endl;
|
||||||
std::cout << "Time to process a range of " << argc - 1 << " elements with std::vector<int> : "
|
|
||||||
<< sorter_vector.getTimeUs() << " us" << std::endl;
|
|
||||||
std::cout << "Time to process a range of " << argc - 1 << " elements with std::deque<int> : "
|
|
||||||
<< 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)
|
catch (const std::invalid_argument &e)
|
||||||
@ -31,16 +23,6 @@ int main(const int argc, const char **argv)
|
|||||||
std::cerr << "Error: " << e.what() << std::endl;
|
std::cerr << "Error: " << e.what() << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
catch (const std::out_of_range &e)
|
|
||||||
{
|
|
||||||
std::cerr << "Error: "<< e.what() << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << "Unexpected error: " << e.what() << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user