diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ed05fc1..aa494f79 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,24 @@ include(cmake/function.cmake) # подхватываем функции, # и для создания исполняемого проекта в отдельные функции add_subdirectory(lib_easy_example) # подключаем дополнительный CMakeLists.txt из подкаталога с именем lib_easy_example + +add_subdirectory(lib_list) +add_subdirectory(lib_stack) +add_subdirectory(lib_queue) +add_subdirectory(lib_queue_on_list) +add_subdirectory(lib_stack_on_list) + +add_subdirectory(lib_monom) +add_subdirectory(lib_polynom) +add_subdirectory(lib_dsu) + +add_subdirectory(lib_doubly_linked_list) +add_subdirectory(lib_calculator_app) +add_subdirectory(lib_algoritm) + + + + add_subdirectory(main) # подключаем дополнительный CMakeLists.txt из подкаталога с именем main option(BTEST "build test?" ON) # указываем подключаем ли google-тесты (ON или YES) или нет (OFF или NO) diff --git a/lib_algoritm/CMakeLists.txt b/lib_algoritm/CMakeLists.txt new file mode 100644 index 00000000..b0cc27ac --- /dev/null +++ b/lib_algoritm/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Algoritm) \ No newline at end of file diff --git a/lib_algoritm/algoritm.h b/lib_algoritm/algoritm.h new file mode 100644 index 00000000..9b198a40 --- /dev/null +++ b/lib_algoritm/algoritm.h @@ -0,0 +1,407 @@ +#pragma once +#include "../lib_matrix/matrix.h" +#include "../lib_stack/stack.h" +#include "../lib_list/List.h" +#include "../lib_dsu/dsu.h" +#include +#include +#include +#include +#include +#include +template +std::pair find_min_neighbor_coords(const Matrix& matrix, size_t x, size_t y) { + T min_val = matrix[x][y]; + size_t min_x = x; + size_t min_y = y; + if (x > 0 && matrix[x - 1][y] < min_val) { + min_val = matrix[x - 1][y]; + min_x = x - 1; + min_y = y; + } + if (x < matrix.getM() - 1 && matrix[x + 1][y] < min_val) { + min_val = matrix[x + 1][y]; + min_x = x + 1; + min_y = y; + } + if (y > 0 && matrix[x][y - 1] < min_val) { + min_val = matrix[x][y - 1]; + min_x = x; + min_y = y - 1; + } + if (y < matrix.getN() - 1 && matrix[x][y + 1] < min_val) { + min_val = matrix[x][y + 1]; + min_x = x; + min_y = y + 1; + } + return { min_x, min_y }; +} +size_t getRandomIndex(size_t max) { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dist(0, max - 1); + return dist(gen); +} +template +T find_local_minimum(const Matrix& matrix) { + size_t x = getRandomIndex(matrix.getM()); + size_t y = getRandomIndex(matrix.getN()); + + while (true) { + std::pair min_coords = find_min_neighbor_coords(matrix, x, y); + size_t new_x = min_coords.first; + size_t new_y = min_coords.second; + + if (new_x == x && new_y == y) { + return matrix[x][y]; + } + + x = new_x; + y = new_y; + } +} +bool check_brackets(std::string str) { + Stack stack(str.length()); + stack.clear(); + for (char c : str) { + if (c == '(' || c == '[' || c == '{') { + stack.push(c); + } + else if (c == ')' || c == ']' || c == '}') { + if (stack.is_empty()) { + return false; + } + char top = stack.top(); + stack.pop(); + + if ((c == ')' && top != '(') || + (c == ']' && top != '[') || + (c == '}' && top != '{')) { + return false; + } + } + } + return stack.is_empty(); +} +void read_expression(std::string expression) { + std::string brackets; + enum State { + EXPECT_OPERAND, + EXPECT_OPERATOR, + EXPECT_OPERAND_OR_UNARY + }; + State current_state = EXPECT_OPERAND; + bool has_operand = false; + for (size_t i = 0; i < expression.length(); ++i) { + char c = expression[i]; + if (std::isspace(c)) { + continue; + } + // + if (c == '(' || c == '{' || c == '[' || c == ')' || c == '}' || c == ']') { + brackets += c; + if (c == '(' || c == '{' || c == '[') { + if (current_state != EXPECT_OPERAND && current_state != EXPECT_OPERAND_OR_UNARY) { + throw std::invalid_argument("Operand expected before opening bracket"); + } + current_state = EXPECT_OPERAND; + } + else { // + if (current_state == EXPECT_OPERAND) { + throw std::invalid_argument("Empty brackets"); + } + current_state = EXPECT_OPERATOR; + } + } + // + else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^') { + if ((c == '+' || c == '-') && + (current_state == EXPECT_OPERAND || current_state == EXPECT_OPERAND_OR_UNARY)) { + // - + current_state = EXPECT_OPERAND; + continue; + } + if (current_state != EXPECT_OPERATOR) { + throw std::invalid_argument("Operator '" + std::string(1, c) + "' in wrong position"); + } + current_state = EXPECT_OPERAND_OR_UNARY; + } + // + else if (std::isalnum(c)) { + if (current_state != EXPECT_OPERAND && current_state != EXPECT_OPERAND_OR_UNARY) { + throw std::invalid_argument("Operator expected before operand"); + } + has_operand = true; + // + while (i < expression.length() && std::isalnum(expression[i])) { + i++; + } + i--; + current_state = EXPECT_OPERATOR; + } + else { + throw std::invalid_argument("Invalid character '" + std::string(1, c) + "' in expression"); + } + } + // + if (!check_brackets(brackets)) { + throw std::invalid_argument("Unbalanced brackets"); + } + if (current_state == EXPECT_OPERAND || current_state == EXPECT_OPERAND_OR_UNARY) { + throw std::invalid_argument("Missing operand at the end of expression"); + } + if (!has_operand) { + throw std::invalid_argument("No operands in expression"); + } +} +template +bool is_looped1(const List& list) { + if (list.is_empty()) { + return false; + } + auto it1_fast = list.begin(); + auto it2_slow = list.begin(); + while (it1_fast != list.end()) { + it2_slow++; + it1_fast++; + if (it1_fast != list.end()) { + it1_fast++; + } + if (it1_fast == it2_slow) { + return true; + } + } + return false; +} +template +bool is_looped2(List& list) { + if (list.is_empty()) { + return false; + } + Node* original_head = list.get_head(); + Node* current = list.get_head(); + Node* prev = nullptr; + while (current != nullptr) { + Node* next_temp = current->next; + current->next = prev; + + prev = current; + current = next_temp; + } + bool has_cycle = (prev == original_head); + + current = prev; + prev = nullptr; + while (current != nullptr) { + Node* next_temp = current->next; + current->next = prev; + prev = current; + current = next_temp; + + } + return has_cycle; +} +template +Node* find_loop_start(List& list) { + if (list.is_empty()) { + return nullptr; + } + Node* it2_slow = list.get_head(); + Node* it1_fast = list.get_head(); + + while (it1_fast != nullptr && it1_fast->next != nullptr) { + it2_slow = it2_slow->next; + it1_fast = it1_fast->next->next; + + if (it2_slow == it1_fast) { + break; + } + } + if (it1_fast == nullptr || it1_fast->next == nullptr) { + return nullptr; + } + it2_slow = list.get_head(); + while (it2_slow != it1_fast) { + it2_slow = it2_slow->next; + it1_fast = it1_fast->next; + } + return it2_slow; +} +size_t get_count_of_islands(Matrix& matrix) { + if (matrix.is_empty()) { + return 0; + } + size_t N = matrix.getN(); + size_t M = matrix.getM(); + DSU islands(M * N); + + // 8 + int directions[8][2] = { + {-1, -1}, {-1, 0}, {-1, 1}, // + {0, -1}, {0, 1}, // , + {1, -1}, {1, 0}, {1, 1} // + }; + + for (size_t i = 0; i < M; i++) { + for (size_t j = 0; j < N; j++) { + if (matrix[i][j] == 1) { + // 8 + for (auto& dir : directions) { + int ni = i + dir[0]; + int nj = j + dir[1]; + + if (ni >= 0 && ni < M && nj >= 0 && nj < N) { + if (matrix[ni][nj] == 1) { + islands.dsu_union(i * N + j, ni * N + nj); + } + } + } + } + } + } + + std::unordered_set unique_roots; + for (size_t i = 0; i < M; i++) { + for (size_t j = 0; j < N; j++) { + if (matrix[i][j] == 1) { + unique_roots.insert(islands.dsu_find_recursive(i * N + j)); + } + } + } + return unique_roots.size(); +} + +Matrix generate1(int x, int y, size_t n, size_t m) { + Matrix matrix(n + 1, m + 1); + for (size_t i = 0; i < n + 1; i++) { + for (size_t j = 0; j < m + 1; j++) { + matrix[i][j] = true; + } + } + DSU dsu(n * m); + dsu.dsu_union(x, y); + for (size_t i = 0; i < n; i++) { + for (size_t j = 0; j < m; j++) { + size_t current = i * m + j; + if (j < m - 1 && getRandomIndex(9) >= 3) { + size_t right = i * m + (j + 1); + dsu.dsu_union(current, right); + + matrix[i + 1][j + 1] = false; + if (j + 2 <= m) matrix[i + 1][j + 2] = false; + } + if (i < n - 1 && getRandomIndex(9) >= 3) { + int bottom = (i + 1) * m + j; + dsu.dsu_union(current, bottom); + + matrix[i + 1][j + 1] = false; + if (i + 2 <= n) matrix[i + 2][j + 1] = false; + } + } + } + return matrix; +} +void print_labirint1(Matrix matrix, size_t n, size_t m) { + for (size_t j = 0; j < m; j++) { + std::cout << "+---"; + } + std::cout << "+" << std::endl; + + for (size_t i = 0; i < n; i++) { + std::cout << "|"; + for (size_t j = 0; j < m; j++) { + int cell_num = i * m + j; + if (cell_num < 10) std::cout << " " << cell_num << " "; + else std::cout << cell_num << " "; + + bool has_right_wall = matrix[i][j + 1] && matrix[i + 1][j + 1]; + std::cout << (has_right_wall ? "|" : " "); + } + std::cout << std::endl; + + if (i < n - 1) { + for (size_t j = 0; j < m; j++) { + std::cout << "+"; + bool has_bottom_wall = matrix[i + 1][j] && matrix[i + 1][j + 1]; + std::cout << (has_bottom_wall ? "---" : " "); + } + std::cout << "+" << std::endl; + } + } + + for (size_t j = 0; j < m; j++) { + std::cout << "+---"; + } + std::cout << "+" << std::endl; +} + +DSU generate2(int x, int y, int n, int m) { + DSU dsu(n * m); + dsu.dsu_union(x, y); + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + int current = i * m + j; + + if (j < m - 1 && getRandomIndex(9) >= 3) { + int right = i * m + (j + 1); + dsu.dsu_union(current, right); + } + if (i < n - 1 && getRandomIndex(9) >= 3) { + int bottom = (i + 1) * m + j; + dsu.dsu_union(current, bottom); + } + } + } + return dsu; +} +void print_labirint2(DSU labirint, int n, int m) { + std::cout << "+"; + for (int j = 0; j < m; j++) { + std::cout << "---+"; + } + std::cout << std::endl; + + for (int i = 0; i < n; i++) { + std::cout << "|"; + + for (int j = 0; j < m; j++) { + int cell = i * m + j; + if (cell < 10) std::cout << " " << cell << " "; + else std::cout << cell << " "; + if (j < m - 1) { + int right_cell = i * m + (j + 1); + if (labirint.dsu_find_recursive(cell) == labirint.dsu_find_recursive(right_cell)) { + std::cout << " "; + } + else { + std::cout << "|"; + } + } + else { + std::cout << "|"; + } + } + std::cout << std::endl; + if (i < n - 1) { + std::cout << "+"; + for (int j = 0; j < m; j++) { + int cell = i * m + j; + int bottom_cell = (i + 1) * m + j; + if (labirint.dsu_find_recursive(cell) == labirint.dsu_find_recursive(bottom_cell)) { + std::cout << " +"; + } + else { + std::cout << "---+"; + } + } + std::cout << std::endl; + } + } + + // - + std::cout << "+"; + for (int j = 0; j < m; j++) { + std::cout << "---+"; + } + std::cout << std::endl; +} \ No newline at end of file diff --git a/lib_calculator_app/CMakeLists.txt b/lib_calculator_app/CMakeLists.txt new file mode 100644 index 00000000..de8e9e76 --- /dev/null +++ b/lib_calculator_app/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(CalculatorApp) \ No newline at end of file diff --git a/lib_calculator_app/expression.cpp b/lib_calculator_app/expression.cpp new file mode 100644 index 00000000..24577776 --- /dev/null +++ b/lib_calculator_app/expression.cpp @@ -0,0 +1,227 @@ +#include "expression.h" +Expression::Expression(size_t id, std::string expression) : + _expression_id(id), _expression(expression) { + try { + _lexems = Parser::parse(_expression); + build_polish_notation(); + } + catch (const std::exception& ex) { + throw std::logic_error( + "Expression ID: " + std::to_string(id) + ": " + ex.what() + ); + } +} +bool Expression::isOperatorOrFunction(const Lexem& lexem) { + return lexem.getType() == Operator || lexem.getType() == Function; +} +bool Expression::shouldPopFromStack(const Lexem& stackTop, const Lexem& current) { + return stackTop.getType() != OpenBracket && + isOperatorOrFunction(stackTop) && + stackTop.getPriority() >= current.getPriority(); +} +void Expression::build_polish_notation() { + List output; + Stack stack(_polish_record.get_size()); + for (auto it = _lexems.begin(); it != _lexems.end(); ++it) { + Lexem current = *it; + switch (current.getType()) { + case Constant: + case Variable: + output.push_back(current); + break; + case Function: + case OpenBracket: + stack.push(current); + break; + case Operator: { + while (!stack.is_empty() && shouldPopFromStack(stack.top(), current)) { + output.push_back(stack.top()); + stack.pop(); + } + stack.push(current); + break; + } + case CloseBracket: { + while (!stack.is_empty() && stack.top().getType() != OpenBracket) { + output.push_back(stack.top()); + stack.pop(); + } + if (stack.is_empty()) { + throw std::logic_error(" ')'"); + } + stack.pop(); + if (!stack.is_empty() && stack.top().getType() == Function) { + output.push_back(stack.top()); + stack.pop(); + } + break; + } + default: + throw std::logic_error(" "); + } + } + while (!stack.is_empty()) { + if (stack.top().getType() == OpenBracket) { + throw std::logic_error(" '('"); + } + output.push_back(stack.top()); + stack.pop(); + } + _polish_record = output; +} +double Expression::applyOperation(double a, double b, char op) const { + switch (op) { + case '+': + return a + b; + case '-': + return a - b; + case '*': + return a * b; + case '/': + if (fabs(b) < 1e-12) { //1e-12 ~ 0.000000000001 + throw std::logic_error(" !"); + } + return a / b; + case '^': + return pow(a, b); + default: + throw std::logic_error(std::string(" : ") + op); + } +} +double Expression::calculate() { + for (Lexem lexem : _lexems) { + if (lexem.getType() == Variable && !has_variable(lexem.getName())) { + throw std::logic_error( + " : '" + lexem.getName() + "' " + ); + } + } + Stack stack(0); + for (Lexem lexem : _polish_record) { + switch (lexem.getType()) { + case Constant: + stack.push(lexem.getValue()); + break; + + case Variable: + stack.push(_variables_map.at(lexem.getName())); + break; + case Operator: { + if (stack.size() < 2) { + throw std::logic_error(" '" + + std::string(1, lexem.getOp()) + "'"); + } + double b = stack.top(); + stack.pop(); + double a = stack.top(); + stack.pop(); + double result; + try { + result = applyOperation(a, b, lexem.getOp()); + } + catch (const std::exception& ex) { + throw std::logic_error( + " : " + std::string(ex.what()) + ); + } + stack.push(result); + break; + } + case Function: { + if (stack.size() < 1) { + throw std::logic_error(" '" + + lexem.getName() + "'"); + } + double arg = stack.top(); + stack.pop(); + double result; + std::string funcName = lexem.getName(); + if (funcName == "sin") { + result = sin(arg); + } + else if (funcName == "cos") { + result = cos(arg); + } + else if (funcName == "tg") { + result = tan(arg); + if (std::isinf(result)) { + throw std::logic_error(" "); + } + } + else if (funcName == "abs") { + result = fabs(arg); + } + else { + throw std::logic_error(" : " + funcName); + } + stack.push(result); + break; + } + + default: + throw std::logic_error(" "); + } + } + if (stack.size() != 1) { + throw std::logic_error(" : "); + } + return stack.top(); +} +void Expression::print_variables() const { + std::vector all_vars; + for (Lexem lexem : _lexems) { + if (lexem.type == TypeLexem::Variable) { + if (std::find(all_vars.begin(), all_vars.end(), lexem.name) == all_vars.end()) { + all_vars.push_back(lexem.name); + } + } + } + if (all_vars.empty()) { + std::cout << " \n"; + return; + } + for (size_t i = 0; i < all_vars.size(); ++i) { + if (i > 0) { + std::cout << ", "; + } + if (has_variable(all_vars[i])) { + std::cout << all_vars[i] << " = " << _variables_map.at(all_vars[i]); + } else { + std::cout << all_vars[i] << " = ?"; + } + } +} +bool Expression::has_variable(const std::string& name) const { + return _variables_map.find(name) != _variables_map.end(); +} +void Expression::set_variable(const std::string& name, double value) { + _variables_map[name] = value; +} +void Expression::set_variables() { + std::string var_name; + double value; + std::cout << " : "; + print_variables(); + std::cout << "\n"; + std::cout << " ( stop ): "; + std::cin >> var_name; + while (var_name != "stop") { + bool found = false; + for (Lexem lexem : _lexems) { + if (lexem.getType() == Variable && lexem.getName() == var_name) { + found = true; + break; + } + } + if (found == false) { + std::cout << ": '" << var_name + << "' \n"; + } else { + std::cout << " " << var_name << ": "; + std::cin >> value; + set_variable(var_name, value); + } + std::cout << " ( stop ): "; + std::cin >> var_name; + } +} diff --git a/lib_calculator_app/expression.h b/lib_calculator_app/expression.h new file mode 100644 index 00000000..3c775414 --- /dev/null +++ b/lib_calculator_app/expression.h @@ -0,0 +1,42 @@ +#pragma once +#include "lexem.h" +#include "../lib_list/List.h" +#include "../lib_stack/stack.h" +#include +#include +#include +#include "parser.h" +#include +class Expression { +private: + std::string _expression; + size_t _expression_id; + std::map _variables_map; + List _lexems; + List _polish_record; + bool shouldPopFromStack(const Lexem& stackTop, const Lexem& current); + bool isOperatorOrFunction(const Lexem& lexem); + void build_polish_notation(); + + bool has_variable(const std::string& name) const; +public: + Expression() : _expression_id(0), _expression("") {} + Expression(size_t id, std::string expression); + const std::string& get_expression() const { + return _expression; + } + size_t get_id() const { + return _expression_id; + } + void clear_variables() { + _variables_map.clear(); + } + const std::map& variables_map() const { + return _variables_map; + } + void set_variable(const std::string& name, double value); + void set_variables(); + double calculate(); + double applyOperation(double a, double b, char op) const; + void print_variables() const; +}; diff --git a/lib_calculator_app/lexem.cpp b/lib_calculator_app/lexem.cpp new file mode 100644 index 00000000..c16bc0a9 --- /dev/null +++ b/lib_calculator_app/lexem.cpp @@ -0,0 +1 @@ +#include "lexem.h" diff --git a/lib_calculator_app/lexem.h b/lib_calculator_app/lexem.h new file mode 100644 index 00000000..22c93617 --- /dev/null +++ b/lib_calculator_app/lexem.h @@ -0,0 +1,60 @@ +#ifndef LEXEM_H +#define LEXEM_H +#include "../lib_list/List.h" +#include +#include +enum TypeLexem { + Constant, + OpenBracket, + CloseBracket, + Variable, + Function, + Operator, + OpenAbs, + CloseAbs }; +struct Lexem { + std::string name; + TypeLexem type; + double value; + int priority; + double (*function)(double); + Lexem() : name(""), type(Constant), value(0.0), + priority(-1), function(nullptr) {} + Lexem(std::string _name, TypeLexem _type, double _value = DBL_MAX, + int _priority = -1, double(*_function)(double) = nullptr): + name(_name), type(_type), value(_value), + priority(_priority), function(_function){}; + + Lexem(const Lexem& other): name(other.name), type(other.type), + value(other.value), priority(other.priority), + function(other.function){} + + Lexem(double _value): name(std::to_string(_value)), type(Constant), + value(_value), priority(-1), function(nullptr) {} + + std::string getName() const { + return name; + } + TypeLexem getType() const { + return type; + } + double getValue() const { + return value; + } + int getPriority() const { + return priority; + } + double (*getFunction() const)(double) { + return function; + } + char getOp() const { + if (type != Operator) { + throw std::logic_error(" "); + } + if (name.empty()) { + return '\0'; + } + return name[0]; + } +}; +#endif diff --git a/lib_calculator_app/main.cpp b/lib_calculator_app/main.cpp new file mode 100644 index 00000000..6e442f5f --- /dev/null +++ b/lib_calculator_app/main.cpp @@ -0,0 +1,37 @@ +//#include "expression.h" +//#include "functions.h" +//#include "lexem.h" +//#include "parser.h" +//#include "../lib_vector/vector.h" +//#include +//// main.cpp +//void printExpressionsTable(const Tvector& expressions) { +// std::cout << "+-----+-----------------------------------------------+-----------------------------+" << std::endl; +// std::cout << "| ID | EXPRESSION | VARIABLES VALUES |" << std::endl; +// std::cout << "+-----+-----------------------------------------------+-----------------------------+" << std::endl; +// +// for (int i = 0; i < expressions.size(); ++i) { +// if (expressions.exists(i)) { +// const Expression& expr = expressions[i]; +// std::cout << "| " << std::setw(3) << expr.getId() << " | " +// << std::setw(45) << std::left << expr.getOriginalExpression() << std::right << " | " +// << std::setw(27) << formatVariables(expr) << " |" << std::endl; +// } +// } +// +// std::cout << "+-----+-----------------------------------------------+-----------------------------+" << std::endl; +//} +//std::string formatVariables(const Expression& expr) { +// auto vars = expr.getVariables(); +// std::string result; +// for (const auto& [name, value] : vars) { +// if (!result.empty()) result += ", "; +// if (value == DBL_MAX) { +// result += name + " = ?"; +// } +// else { +// result += name + " = " + std::to_string(value); +// } +// } +// return result; +//} diff --git a/lib_calculator_app/parser.cpp b/lib_calculator_app/parser.cpp new file mode 100644 index 00000000..0bd3df58 --- /dev/null +++ b/lib_calculator_app/parser.cpp @@ -0,0 +1,305 @@ +#include "parser.h" +bool Parser::check_brackets(std::string str) { + Stack stack(str.length()); + stack.clear(); + for (char c : str) { + if (c == '(' || c == '[' || c == '{') { + stack.push(c); + } + else if (c == ')' || c == ']' || c == '}') { + if (stack.is_empty()) { + return false; + } + char top = stack.top(); + stack.pop(); + + if ((c == ')' && top != '(') || + (c == ']' && top != '[') || + (c == '}' && top != '{')) { + return false; + } + } + } + return stack.is_empty(); +} +void Parser::handleAbsBracket(char c, List& lexems, + bool& lastWasOperatorOrBracketOrFunction, + bool& absOpened) { + if (!absOpened) { + // Opened - abs( + lexems.push_back(Lexem("abs", TypeLexem::Function, DBL_MAX, 4, + getFunctionByName("abs"))); + lexems.push_back(Lexem("(", TypeLexem::OpenBracket)); + absOpened = true; + lastWasOperatorOrBracketOrFunction = true; + } + else { + // closed - ) + lexems.push_back(Lexem(")", TypeLexem::CloseBracket)); + absOpened = false; + lastWasOperatorOrBracketOrFunction = false; + } +} +bool Parser::isValidNumberFormat(const std::string& number) { + int dotCount = 0; + for (char c : number) { + if (c == '.') dotCount++; + } + return dotCount <= 1; +} +List Parser::parse(std::string expression) { + if (expression.empty()) { + throw std::logic_error("Expression is empty"); + } + if (check_brackets(expression) == false) { + throw std::logic_error("Mismatched brackets"); + } + List lexems; + bool lastWasOperatorOrBracketOrFunction = false; + bool absOpened = false; + size_t i = 0; + + while (i < expression.length()) { + char c = expression[i]; + if (c == ' ') { + i++; + continue; + } + if (isDigit(c)) { + std::string number = ""; + number += c; + i++; + while (i < expression.length() && + (isDigit(expression[i]) || expression[i] == '.')) { + number += expression[i]; + i++; + } + if (!isValidNumberFormat(number)) { + size_t errorPos = i - number.length(); + std::string errorMsg = formatError(expression, errorPos, + "Invalid number format: '" + number + "'"); + throw std::logic_error(errorMsg); + } + if (i < expression.length() && + (isLetter(expression[i]) || expression[i] == '_') && + expression[i] != 'e' && expression[i] != 'E') { // исключаем научную запись + size_t errorPos = i - number.length(); + std::string errorMsg = formatError(expression, errorPos, + "Invalid variable/function format: '" + number + expression[i] + "'"); + throw std::logic_error(errorMsg); + } + try { + double constant = std::stod(number); + Lexem lexem(constant); + lexems.push_back(lexem); + lastWasOperatorOrBracketOrFunction = false; + } + catch (std::exception& ex) { + size_t errorPos = i - number.length(); + std::string errorMsg = formatError(expression, errorPos, + "Invalid number format: '" + number + "'"); + throw std::logic_error(errorMsg); + } + + } else if (isOpenBracket(c)) { + Lexem lexem(std::string(1, c), TypeLexem::OpenBracket); + lexems.push_back(lexem); + lastWasOperatorOrBracketOrFunction = true; + i++; + } else if (isCloseBracket(c)) { + Lexem lexem(std::string(1, c), TypeLexem::CloseBracket); + lexems.push_back(lexem); + lastWasOperatorOrBracketOrFunction = false; + i++; + } + else if (isBinaryOperator(c)) { + bool isUnary = isUnaryOperator(c, lastWasOperatorOrBracketOrFunction, i); + if (isUnary) { + if (c == '-') { + Lexem lexem1(0.0); + Lexem lexem2("-", TypeLexem::Operator, DBL_MAX, 1); + lexems.push_back(lexem1); + lexems.push_back(lexem2); + lastWasOperatorOrBracketOrFunction = true; + } + else if (c == '+') { + lastWasOperatorOrBracketOrFunction = true; + } + } + else { + int priority = getOperatorPriority(c); + Lexem lexem(std::string(1, c), TypeLexem::Operator, DBL_MAX, priority); + lexems.push_back(lexem); + lastWasOperatorOrBracketOrFunction = true; + } + i++; + } + else if (isLetter(c) || c == '_') { //function/variable + std::string word = ""; + word += c; + i++; + while (i < expression.length() && isVariableChar(expression[i])) { + word += expression[i]; //sin + i++; + } if (isFunction(word)) { + if ( i >= expression.length() ||!isOpenBracket(expression[i])){ + size_t errorPos = i - word.length(); + std::string errorMsg = formatError(expression, errorPos, + "Invalid variable/function format: '" + word + "'"); + throw std::logic_error(errorMsg); + } + double (*funcPtr)(double) = getFunctionByName(word); + if (funcPtr == nullptr) { + size_t errorPos = i - word.length(); + std::string errorMsg = formatError(expression, errorPos, + "Invalid variable/function format: '" + word + "'"); + throw std::logic_error(errorMsg); + } + Lexem lexem(word, TypeLexem::Function, DBL_MAX, 4, funcPtr); + lexems.push_back(lexem); + lastWasOperatorOrBracketOrFunction = true; + + } else if (isValidVariableName(word)) { + Lexem lexem(word, TypeLexem::Variable); + lexems.push_back(lexem); + lastWasOperatorOrBracketOrFunction = false; + } else { + size_t errorPos = i - word.length(); + std::string errorMsg = formatError(expression, errorPos, + "Invalid variable/function format: '" + word + "'"); + throw std::logic_error(errorMsg); + } + } + else if (c == '|') { + handleAbsBracket(c, lexems, lastWasOperatorOrBracketOrFunction, absOpened); + i++; + } + else { + size_t errorPos = i; + std::string errorMsg = formatError(expression, errorPos, + "Unknown character: '" + std::string(1, c) + "'"); + throw std::logic_error(errorMsg); + } + } // cycle while i < expr. lenght + if (lastWasOperatorOrBracketOrFunction && !(lexems.get_size() == 0) ) { + size_t errorPos = expression.length() - 1; + std::string errorMsg = formatError(expression, errorPos, + "Expression cannot end with operator or function"); + throw std::logic_error(errorMsg); + } + return lexems; +} +double Parser::getSin(double value) { + return sin(value); +} + +double Parser::getCos(double value) { + return cos(value); +} + +double Parser::getTg(double value) { + return tan(value); +} +double Parser::getAbs(double value) { + return fabs(value); +} +bool Parser::isOpenBracket(char c) { + return c == '(' || c == '{' || c == '['; +} +bool Parser::isCloseBracket(char c) { + return c == ')' || c == '}' || c == ']'; +} +bool Parser::isDigit(char c) { + return c >= '0' && c <= '9'; +} +bool Parser::isLetter(char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} +bool Parser::isVariableChar(char c) { + return isDigit(c) || isLetter(c) || c == '_'; +} +bool Parser::isValidVariableName(const std::string& name) { + if (name.empty()) { + return false; + } + if (!isLetter(name[0]) && name[0] != '_') { + return false; + } + for (char c : name) { + if (!isVariableChar(c)) { + return false; + } + } + if (isFunction(name)) { + return false; + } + return true; +} +bool Parser::isFunction(const std::string& name) { + const std::string functions[] = { + "sin", "cos", "tg", "abs" + }; + for (const auto& function : functions) { + if (name == function) { + return true; + } + } + return false; +} +bool Parser::isBinaryOperator(char c) { + return c == '+' || c == '-' || c == '*' || c == '/' || c == '^'; +} +bool Parser::isUnaryOperator(char c, bool lastWasOperatorOrBracket, size_t position) { + if (c != '-') { + return false; + } + return position == 0 || lastWasOperatorOrBracket; +} +int Parser::getOperatorPriority(char c) { + switch (c) { + case '^': + return 3; + break; + case '*': case '/': + return 2; + break; + case '+': case '-': + return 1; + break; + default: + return 0; + } +} +std::string Parser::formatError(const std::string& expression, + size_t position, + const std::string& message) { + std::stringstream ss; + ss << "\nВыражение: " << expression << "\n"; + ss << "Позиция " << position + 1 << ": "; + for (size_t i = 0; i < position && i < expression.length(); i++) { + if (expression[i] == '\t') { + ss << "\t"; + } + else { + ss << " "; + } + } + ss << "^\n"; + ss << "Ошибка: " << message; + return ss.str(); +} +double (*Parser::getFunctionByName(const std::string& name))(double) { + if (name == "sin") { + return Parser::getSin; + } + if (name == "cos") { + return Parser::getCos; + } + if (name == "tg") { + return Parser::getTg; + } + if (name == "abs") { + return Parser::getAbs; + } + return nullptr; +} diff --git a/lib_calculator_app/parser.h b/lib_calculator_app/parser.h new file mode 100644 index 00000000..4316b483 --- /dev/null +++ b/lib_calculator_app/parser.h @@ -0,0 +1,34 @@ +#pragma once +#include "../lib_list/List.h" +#include "../lib_stack/stack.h" +#include "lexem.h" +#include +#include +#include +#include +#include +#include +namespace Parser { + List parse(std::string expression); + bool check_brackets(std::string str); + double getSin(double value); + double getCos(double value); + double getTg(double value); + double getAbs(double value); + bool isOpenBracket(char c); + bool isCloseBracket(char c); + bool isDigit(char c); + bool isLetter(char c); + bool isVariableChar(char c); + bool isValidVariableName(const std::string& name); + bool isFunction(const std::string& name); + bool isBinaryOperator(char c); + bool isUnaryOperator(char c, bool lastWasOperatorOrBracket, size_t position); + bool isValidNumberFormat(const std::string& number); + int getOperatorPriority(char c); + std::string formatError(const std::string& expression, size_t position, const std::string& message); + double (*getFunctionByName(const std::string& name))(double); + void handleAbsBracket(char c, List& lexems, + bool& lastWasOperatorOrBracketOrFunction, + bool& absOpened); +} diff --git a/lib_doubly_linked_list/doubly_linked_list.cpp b/lib_doubly_linked_list/doubly_linked_list.cpp new file mode 100644 index 00000000..e96b2162 --- /dev/null +++ b/lib_doubly_linked_list/doubly_linked_list.cpp @@ -0,0 +1 @@ +#include "doubly_linked_list.h" diff --git a/lib_doubly_linked_list/doubly_linked_list.h b/lib_doubly_linked_list/doubly_linked_list.h new file mode 100644 index 00000000..e6a0361e --- /dev/null +++ b/lib_doubly_linked_list/doubly_linked_list.h @@ -0,0 +1,327 @@ +#pragma once +#include +template +struct Node { + T value; + Node* next; + Node* previous; + Node(T value_, Node* next_ = nullptr, Node* previous_ = nullptr) : value(value_), next(next_), previous(previous_) {} +}; +template +class DoublyLinkedList { +private: + Node* _head; + Node* _tail; + size_t _count_elements; +public: + class Iterator { + private: + Node* _current; + public: + Iterator() : _current(nullptr) {} + Iterator(Node* node) : _current(node) {} + Iterator(const Iterator& other) : _current(other._current) {} + Iterator& operator=(const Iterator& other) { + _current = other._current; + return *this; + } + Iterator& operator+=(size_t n) { + for (size_t i = 0; i < n && _current != nullptr; ++i) { + _current = _current->next; + } + return *this; + } + Iterator& operator-=(size_t n) { + for (size_t i = 0; i < n && _current != nullptr; ++i) { + _current = _current->previous; + } + return *this; + } + Iterator& operator++() { + if (_current != nullptr) { + _current = _current->next; + } + return *this; + } + Iterator operator++(int) { + Iterator it = *this; + if (_current != nullptr) { + _current = _current->next; + } + return it; + } + Iterator& operator--() { + if (_current != nullptr) { + _current = _current->previous; + } + return *this; + } + Iterator operator--(int) { + Iterator it = *this; + if (_current != nullptr) { + _current = _current->previous; + } + return it; + } + bool operator==(const Iterator& it) const { + return this->_current == it._current; + } + bool operator!=(const Iterator& it) const { + return !(*this == it); + } + T& operator*() { + if (_current == nullptr) { + throw std::runtime_error("Dereferencing end iterator"); + } + return _current->value; + } + const T& operator*() const { + if (_current == nullptr) { + throw std::runtime_error("Dereferencing end iterator"); + } + return _current->value; + } + }; + Iterator begin() { + return Iterator(_head); + } + Iterator end() { + return Iterator(nullptr); + } + Iterator begin() const { + return Iterator(_head); + } + Iterator end() const { + return Iterator(nullptr); + } + DoublyLinkedList(); + ~DoublyLinkedList(); + DoublyLinkedList(const DoublyLinkedList& other_list); + size_t get_size() const noexcept; + Node* get_head() const noexcept; + Node* get_tail() const noexcept; + + bool operator==(const DoublyLinkedList& other) const; + bool operator!=(const DoublyLinkedList& other) const; + DoublyLinkedList& operator=(const DoublyLinkedList other); + + bool is_empty() const noexcept; + void push_back(const T& value) noexcept; + void push_front(const T& value) noexcept; + void insert(size_t position, const T& value); + void insert(Node* node, const T& value); + void pop_front(); + void pop_back(); + void erase(size_t position); + void erase(Node* node); +}; +template +DoublyLinkedList::DoublyLinkedList(): _head(nullptr), _tail(nullptr), _count_elements(0) {} +template +DoublyLinkedList::DoublyLinkedList(const DoublyLinkedList& other_list): _head(nullptr), _tail(nullptr), _count_elements(0) { + for (auto it = other_list.begin(); it != other_list.end(); ++it) { + this->push_back(*it); + } +} +template +DoublyLinkedList::~DoublyLinkedList() { + while (_head != nullptr) { + Node* temporary = _head; + _head = _head->next; + delete temporary; + } +} +template +size_t DoublyLinkedList::get_size() const noexcept { + return _count_elements; +} +template +Node* DoublyLinkedList::get_head() const noexcept { + return _head; +} +template +Node* DoublyLinkedList::get_tail() const noexcept { + return _tail; +} +template +bool DoublyLinkedList::operator==(const DoublyLinkedList& other) const { + if (this->get_size() != other.get_size()) { + return false; + } + auto it_this = this->begin(); + auto it_other = other.begin(); + while (it_this != this->end() && it_other != other.end()) { + if (*it_this != *it_other) { + return false; + } + ++it_this; + ++it_other; + } + return true; +} +template +bool DoublyLinkedList::operator!=(const DoublyLinkedList& other) const { + return !(*this == other); +} +template +DoublyLinkedList& DoublyLinkedList::operator=(DoublyLinkedList other) { + std::swap(_head, other._head); + std::swap(_tail, other._tail); + std::swap(_count_elements, other._count_elements); + return *this; +} +template +bool DoublyLinkedList::is_empty() const noexcept { + return _head == nullptr && _tail == nullptr; +} +template +void DoublyLinkedList::push_back(const T& value) noexcept { + Node* node = new Node(value); + if (this->is_empty()) { + _head = node; + _tail = node; + } + else { + node->previous = _tail; + _tail->next = node; + _tail = node; + } + _count_elements++; +} +template +void DoublyLinkedList::push_front(const T& value) noexcept { + Node* node = new Node(value); + if (this->is_empty()) { + _head = node; + _tail = node; + } + else { + _head->previous = node; + node->next = _head; + _head = node; + } + _count_elements++; +} +template +void DoublyLinkedList::insert(size_t position, const T& value) { + if (position == 0) { + this->push_front(value); + return; + } + if (position == _count_elements - 1) { + this->push_back(value); + return; + } + Node* current = _head; + size_t current_position = 0; + while (current != nullptr && current_position != position - 1) { + current = current->next; + current_position++; + } + if (current == nullptr) { + throw std::invalid_argument("Uncorrect position"); + } + this->insert(current, value); +} +template +void DoublyLinkedList::insert(Node* node, const T& value) { + if (node == nullptr || this->is_empty()) { + throw std::logic_error("The transmitted node or/and the list can't be empty!"); + } + Node* new_node = new Node(value); + new_node->previous = node; + new_node->next = node->next; + + node->next = new_node; + if (new_node->next != nullptr) { + new_node->next->previous = new_node; + } + if (node == _tail) { + _tail = new_node; + } + _count_elements++; +} +template +void DoublyLinkedList::pop_front() { + if (this->is_empty()) { + throw std::logic_error("Can't pop the first element at empty list!"); + } + if (_head == _tail) { + delete _head; + _head = nullptr; + _tail = nullptr; + _count_elements--; + return; + } + Node* temporary = _head; + _head = _head->next; + _head->previous = nullptr; + delete temporary; + _count_elements--; +} +template +void DoublyLinkedList::pop_back() { + if (this->is_empty()) { + throw std::logic_error("Can't pop the last element at empty list!"); + } + if (_head == _tail) { + delete _head; + _tail = nullptr; + _head = nullptr; + _count_elements--; + return; + } + Node* temporary = _tail; + _tail = _tail->previous; + _tail->next = nullptr; + delete temporary; + _count_elements--; +} +template +void DoublyLinkedList::erase(size_t position) { + if (position == 0) { + this->pop_front(); + return; + } + if (position == _count_elements - 1) { + this->pop_back(); + return; + } + Node* current = _head; + size_t current_position = 0; + while (current != nullptr) { + if (current_position == position) { + break; + } + current = current->next; + current_position++; + } + if (current == nullptr) { + throw std::invalid_argument("Uncorrect position"); + } + + Node* temporary = current; + current->previous->next = current->next; + current->next->previous = current->previous; + delete temporary; + _count_elements--; +} +template +void DoublyLinkedList::erase(Node* node) { + if (node == nullptr || this->is_empty()) { + throw std::logic_error("The transmitted node or/and the list can't be empty!"); + } + if (node == _head) { + this->pop_front(); + return; + } + if (node == _tail) { + this->pop_back(); + return; + } // 10 20 <- 30 -> 40 50 + Node* temporary = node; + temporary->previous->next = temporary->next; + temporary->next->previous = temporary->previous; + delete temporary; + _count_elements--; +} diff --git a/lib_dsu/CMakeLists.txt b/lib_dsu/CMakeLists.txt new file mode 100644 index 00000000..424d2417 --- /dev/null +++ b/lib_dsu/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(DSU) \ No newline at end of file diff --git a/lib_dsu/dsu.cpp b/lib_dsu/dsu.cpp new file mode 100644 index 00000000..208653ad --- /dev/null +++ b/lib_dsu/dsu.cpp @@ -0,0 +1,80 @@ +#include "dsu.h" +DSU::DSU(size_t size) { + _size = size; + _parent = new int[_size]; + _rank = new int[_size]; + for (size_t i = 0; i < _size; i++) { + _parent[i] = i; + _rank[i] = 0; + } +} +DSU::DSU(const DSU& other) { + _size = other._size; + _parent = new int[_size]; + _rank = new int[_size]; + for (size_t i = 0; i < _size; i++) { + this->_parent[i] = other._parent[i]; + this->_rank[i] = other._rank[i]; + } +} +DSU::~DSU() { + delete[] _parent; + delete[] _rank; + _parent = nullptr; + _rank = nullptr; +} +size_t DSU::size() const noexcept { + return _size; +} +int* DSU::parent() const noexcept { + return _parent; +} +int* DSU::rank() const noexcept { + return _rank; +} +void DSU::dsu_union(int x, int y) { + if (x == y) { + return; + } + if (x >= _size || y >= _size || x < 0 || y < 0) { + throw std::logic_error("Uncorrect arguments"); + } + int parent_x = dsu_find_recursive(x); + int parent_y = dsu_find_recursive(y); + if (parent_x == parent_y) { + return; + } + if (_rank[parent_x] < _rank[parent_y]) { + _parent[parent_x] = parent_y; + } + else if (_rank[parent_x] > _rank[parent_y]) { + _parent[parent_y] = parent_x; + } + else { + _parent[parent_y] = parent_x; + _rank[parent_x]++; + } +} +int DSU::dsu_find_recursive(int x) { + if (x >= _size || x < 0) { + throw std::logic_error("Uncorrect argument"); + } + if (_parent[x] == x) { + return x; + } + return _parent[x] = dsu_find_recursive(_parent[x]); +} +DSU& DSU::operator=(const DSU& other) { + if (this != &other) { + delete[] _parent; + delete[] _rank; + _size = other._size; + _parent = new int[_size]; + _rank = new int[_size]; + for (size_t i = 0; i < _size; i++) { + this->_parent[i] = other._parent[i]; + this->_rank[i] = other._rank[i]; + } + } + return *this; +} diff --git a/lib_dsu/dsu.h b/lib_dsu/dsu.h new file mode 100644 index 00000000..9331fa80 --- /dev/null +++ b/lib_dsu/dsu.h @@ -0,0 +1,18 @@ +#pragma once +#include +class DSU { +private: + int* _parent; + int* _rank; + size_t _size; +public: + DSU(size_t size); + DSU(const DSU& other); + ~DSU(); + size_t size() const noexcept; + int* parent() const noexcept; + int* rank() const noexcept; + void dsu_union(int x, int y); + int dsu_find_recursive(int x); + DSU& operator=(const DSU& other); +}; diff --git a/lib_list/List.cpp b/lib_list/List.cpp new file mode 100644 index 00000000..ad08685d --- /dev/null +++ b/lib_list/List.cpp @@ -0,0 +1 @@ +#include "List.h" diff --git a/lib_list/List.h b/lib_list/List.h new file mode 100644 index 00000000..5226cd53 --- /dev/null +++ b/lib_list/List.h @@ -0,0 +1,323 @@ +#pragma once +#include +template +struct Node { + T value; + Node* next; + Node(T value_, Node* next_ = nullptr) : value(value_), next(next_) {} +}; +template +class List { +private: + Node* _head; + Node* _tail; + size_t _count_elements; +public: + class Iterator { + private: + Node* _current; + public: + Iterator() : _current(nullptr) {} + Iterator(Node* node): _current(node) {} + Iterator(const Iterator& other): _current(other._current) {} + Iterator& operator=(const Iterator& other) { + _current = other._current; + return *this; + } + Iterator& operator+=(size_t n) { + for (size_t i = 0; i < n && _current != nullptr; ++i) { + _current = _current->next; + } + return *this; + } + Iterator& operator++() { + if (_current != nullptr) { + _current = _current->next; + } + return *this; + } + Iterator operator++(int) { + Iterator it = *this; + if (_current != nullptr) { + _current = _current->next; + } + return it; + } + bool operator==(const Iterator& it) const { + return this->_current == it._current; + } + bool operator!=(const Iterator& it) const { + return !(*this == it); + } + T& operator*() { + if (_current == nullptr) { + throw std::runtime_error("Dereferencing end iterator"); + } + return _current->value; + } + const T& operator*() const { + if (_current == nullptr) { + throw std::runtime_error("Dereferencing end iterator"); + } + return _current->value; + } + }; + Iterator begin() { + return Iterator(_head); + } + Iterator end() { + return Iterator(nullptr); + } + Iterator begin() const { + return Iterator(_head); + } + Iterator end() const { + return Iterator(nullptr); + } + List(); + ~List(); + List(const List& other_list); + size_t get_size() const noexcept { + return _count_elements; + } + Node* get_head() const noexcept { + return _head; + } + Node* get_tail() const noexcept { + return _tail; + } + T& get_last_element() { + if (_tail == nullptr) { + throw std::runtime_error("List is empty"); + } + return _tail->value; + } + const T& get_last_element() const { + if (_tail == nullptr) { + throw std::runtime_error("List is empty"); + } + return _tail->value; + } + + bool operator==(const List& other) const; + bool operator!=(const List& other) const; + List& operator=(const List& other); + + bool is_empty() const noexcept; + void push_back(const T& value) noexcept; + void push_front(const T& value) noexcept; + void insert(size_t position, const T& value); + void insert(Node* node, const T& value); + void pop_front(); + void pop_back(); + void erase(size_t position); + void erase(Node* node); +}; +template +List::List() : _head(nullptr), _tail(nullptr), _count_elements(0) {} +template +List::~List() { + while (_head != nullptr) { + Node* temporary = _head; + _head = _head->next; + delete temporary; + } +} +template +List::List(const List& other_list) : _head(nullptr), _tail(nullptr), +_count_elements(0) { + for (auto it = other_list.begin(); it != other_list.end(); ++it) { + this->push_back(*it); + } +} +template +bool List::is_empty() const noexcept { + return _head == nullptr && _tail == nullptr; +} +template +void List::push_front(const T& value) noexcept { + Node* node = new Node(value); + if (this->is_empty()) { + _head = node; + _tail = node; + _count_elements++; + return; + } + node->next = _head; + _head = node; + _count_elements++; +} +template +void List::push_back(const T& value) noexcept { + Node* node = new Node(value); + if (this->is_empty()) { + _head = node; + _tail = node; + _count_elements++; + return; + } + _tail->next = node; + _tail = node; + _count_elements++; +} +template +void List::pop_front() { + if (this->is_empty()) { + throw std::logic_error("Can't pop the first element at empty list!"); + } + if (_head == _tail) { + delete _head; + _head = nullptr; + _tail = nullptr; + _count_elements--; + return; + } + Node* temporary = _head; + _head = _head->next; + delete temporary; + _count_elements--; +} +template +void List::pop_back() { + if (this->is_empty()) { + throw std::logic_error("Can't pop the last element at empty list!"); + } + if (_head == _tail) { + delete _head; + _tail = nullptr; + _head = nullptr; + _count_elements--; + return; + } + Node* current = _head; + while (current->next != _tail) { + current = current->next; + } + Node* temporary = current->next; + _tail = current; + _tail->next = nullptr; + delete temporary; + _count_elements--; +} +template +bool List::operator==(const List& other) const { + if (this->get_size() != other.get_size()) { + return false; + } + auto it_this = this->begin(); + auto it_other = other.begin(); + while (it_this != this->end() && it_other != other.end()) { + if (*it_this != *it_other) { + return false; + } + ++it_this; + ++it_other; + } + return true; +} +template +bool List::operator!=(const List& other) const { + return !(*this == other); +} +template +List& List::operator=(const List& other) { + if (this != &other) { + while (_head != nullptr) { + Node* temporary = _head; + _head = _head->next; + delete temporary; + } + _head = nullptr; + _tail = nullptr; + _count_elements = 0; + for (auto it = other.begin(); it != other.end(); ++it) { + this->push_back(*it); + } + } + return *this; +} +template +void List::insert(size_t position, const T& value) { + if (position == 0) { + this->push_front(value); + return; + } + if (position == _count_elements - 1) { + this->push_back(value); + return; + } + Node* current = _head; + size_t current_position = 0; + while (current != nullptr && current_position != position - 1) { + current = current->next; + current_position++; + } + if (current == nullptr) { + throw std::invalid_argument("Uncorrect position"); + } + this->insert(current, value); +} +template +void List::insert(Node* node, const T& value) { + if (node == nullptr || this->is_empty()) { + throw std::logic_error("The transmitted node or/and the list can't be empty!"); + } + Node* new_node = new Node(value); + new_node->next = node->next; + node->next = new_node; + if (node == _tail) { + _tail = new_node; + } + _count_elements++; +} +template +void List::erase(size_t position) { + if (position == 0) { + this->pop_front(); + return; + } + if (position == _count_elements - 1) { + this->pop_back(); + return; + } + Node* current = _head; + size_t current_position = 0; + while (current != nullptr) { + if (current_position == position - 1) { + break; + } + current = current->next; + current_position++; + } + if (current == nullptr) { + throw std::invalid_argument("Uncorrect position"); + } + Node* temporary = current->next; + current->next = temporary->next; + delete temporary; + _count_elements--; +} +template +void List::erase(Node* node) { + if (node == nullptr || this->is_empty()) { + throw std::logic_error("The transmitted node or/and the list can't be empty!"); + } + if (node == _head) { + this->pop_front(); + return; + } + if (node == _tail) { + this->pop_back(); + return; + } + Node* current = _head; + while (current != nullptr && current->next != node) { + current = current->next; + } + if (current == nullptr) { + throw std::invalid_argument("Uncorrect position"); + } + current->next = node->next; + delete node; + _count_elements--; +} diff --git a/lib_math_vector/math_vector.cpp b/lib_math_vector/math_vector.cpp new file mode 100644 index 00000000..9e86fff9 --- /dev/null +++ b/lib_math_vector/math_vector.cpp @@ -0,0 +1 @@ +#include "math_vector.h" diff --git a/lib_math_vector/math_vector.h b/lib_math_vector/math_vector.h new file mode 100644 index 00000000..fa1671ac --- /dev/null +++ b/lib_math_vector/math_vector.h @@ -0,0 +1,191 @@ +#pragma once +#include +#include "../lib_vector/vector.h" + +template +class MathVector:public Tvector { +protected: + size_t _start_index = 0; +public: + MathVector(); + MathVector(size_t size); + MathVector(size_t size, size_t start_index); + MathVector(T* data, size_t size); + MathVector(T* data, size_t size, size_t start_index); + MathVector(const MathVector& other); + virtual ~MathVector(); + + size_t get_start_index() const { + return _start_index; + } + void set_start_index(size_t index) { + _start_index = index; + } + + T& at(size_t index); + const T& at(size_t index) const; + + MathVector operator * (T value) const; + MathVector operator / (T value) const; + + MathVector& operator *= (T value); + MathVector& operator /= (T value); + + MathVector operator + (const MathVector& vector) const; + MathVector operator - (const MathVector& vector) const; + T operator * (const MathVector& vector) const; + + MathVector& operator += (const MathVector& vector); + MathVector& operator -= (const MathVector& vector); + MathVector& operator=(const MathVector& other); + friend std::ostream& operator<< (std::ostream& out, const MathVector& vector); + T& operator[](size_t index); + const T& operator[](size_t index) const; +}; +template +std::ostream& operator<<(std::ostream& out, const MathVector& vector) { + out << "["; + for (size_t i = 0; i < vector.get_size(); ++i) { + out << vector[i]; + if (i < vector.get_size() - 1) { + out << ", "; + } + } + out << "]"; + return out; +} +template +MathVector::MathVector() : Tvector() {} +template +MathVector::MathVector(size_t size) : Tvector(size) {} +template +MathVector::MathVector(size_t size, size_t start_index) : Tvector(size), _start_index(start_index) {} +template +MathVector::MathVector(T* data, size_t size) : Tvector(data, size) {} +template +MathVector::MathVector(T* data, size_t size, size_t start_index) : + Tvector(data, size), _start_index(start_index) {} +template +MathVector::MathVector(const MathVector& other) : + Tvector(other), _start_index(other._start_index) {} +template +MathVector::~MathVector() = default; +template +MathVector MathVector::operator * (T value) const { + MathVector result(this->get_size()); + for (size_t i = 0; i < this->get_size(); ++i) { + result[i] = (*this)[i] * value; + } + return result; +} +template +MathVector MathVector::operator / (T value) const { + if (value == 0) { + throw std::logic_error("Can't divide by zero!"); + } + MathVector result(this->get_size()); + for (size_t i = 0; i < this->get_size(); ++i) { + result[i] = (*this)[i] / value; + } + return result; +} +template +MathVector& MathVector::operator *= (T value) { + for (size_t i = 0; i < this->get_size(); ++i) { + (*this)[i] *= value; + } + return *this; +} +template +MathVector& MathVector::operator /= (T value) { + if (value == 0) { + throw std::logic_error("Can't divide by zero!"); + } + for (size_t i = 0; i < this->get_size(); ++i) { + (*this)[i] /= value; + } + return *this; +} +template +MathVector MathVector::operator + (const MathVector& vector) const { + if (this->get_size() != vector.get_size()) { + throw std::logic_error("Vectors must have the same dimension"); + } + MathVector result(this->get_size()); + for (size_t i = 0; i < this->get_size(); ++i) { + result[i] = (*this)[i] + vector[i]; + } + return result; +} +template +MathVector MathVector::operator - (const MathVector& vector) const { + if (this->get_size() != vector.get_size()) { + throw std::logic_error("Vectors must have the same dimension"); + } + MathVector result(this->get_size()); + for (size_t i = 0; i < this->get_size(); ++i) { + result[i] = (*this)[i] - vector[i]; + } + return result; +} +template +T MathVector::operator * (const MathVector& vector) const { + if (this->get_size() != vector.get_size()) { + throw std::logic_error("Vectors must have the same dimension"); + } + T result{}; + for (size_t i = 0; i < this->get_size(); ++i) { + result += (*this)[i] * vector[i]; + } + return result; +} +template +MathVector& MathVector::operator += (const MathVector& vector) { + if (this->get_size() != vector.get_size()) { + throw std::logic_error("Vectors must have the same dimension"); + } + for (size_t i = 0; i < this->get_size(); ++i) { + (*this)[i] += vector[i]; + } + return *this; +} +template +MathVector& MathVector::operator -= (const MathVector& vector) { + if (this->get_size() != vector.get_size()) { + throw std::logic_error("Vectors must have the same dimension"); + } + for (size_t i = 0; i < this->get_size(); ++i) { + (*this)[i] -= vector[i]; + } + return *this; +} +template +MathVector& MathVector::operator=(const MathVector& other) { + if (this != &other) { + Tvector::operator=(other); + _start_index = other._start_index; + } + return *this; +} +template +T& MathVector::operator[](size_t index) { + return this->Tvector::operator[](index - _start_index); +} +template +const T& MathVector::operator[](size_t index) const { + return this->Tvector::operator[](index - _start_index); +} +template +T& MathVector::at(size_t index) { + if (index < _start_index || index >= _start_index + this->get_size()) { + throw std::logic_error("MathVector index out of range"); + } + return this->Tvector::operator[](index - _start_index); +} +template +const T& MathVector::at(size_t index) const { + if (index < _start_index || index >= _start_index + this->get_size()) { + throw std::std::logic_error("MathVector index out of range"); + } + return this->Tvector::operator[](index - _start_index); +} diff --git a/lib_matrix/CMakeLists.txt b/lib_matrix/CMakeLists.txt new file mode 100644 index 00000000..91c1bacc --- /dev/null +++ b/lib_matrix/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Matrix) \ No newline at end of file diff --git a/lib_matrix/matrix.cpp b/lib_matrix/matrix.cpp new file mode 100644 index 00000000..0d415b5a --- /dev/null +++ b/lib_matrix/matrix.cpp @@ -0,0 +1 @@ +#include "matrix.h" \ No newline at end of file diff --git a/lib_matrix/matrix.h b/lib_matrix/matrix.h new file mode 100644 index 00000000..10acab73 --- /dev/null +++ b/lib_matrix/matrix.h @@ -0,0 +1,189 @@ +#pragma once +#include +#include "../lib_math_vector/math_vector.h" +template class TriangleMatrix; + +template +class Matrix : public MathVector> { +protected: + size_t _M; + size_t _N; + Matrix transpose() const { + Matrix result(_N, _M); + for (size_t i = 0; i < _M; ++i) { + for (size_t j = 0; j < _N; ++j) { + result[j][i] = (*this)[i][j]; + } + } + return result; + } +public: + Matrix(); + Matrix(size_t M, size_t N); + Matrix(T* data, size_t M, size_t N); + Matrix(const Matrix& other); + virtual ~Matrix(); + size_t getM() const noexcept; + size_t getN() const noexcept; + + Matrix operator * (T value) const; + Matrix operator / (T value) const; + + Matrix& operator *= (T value); + Matrix& operator /= (T value); + + Matrix operator + (const Matrix& other_matrix) const; + Matrix operator - (const Matrix& other_matrix) const; + Matrix operator * (const Matrix& other_matrix) const; + + MathVector operator * (const MathVector& vector) const; + + Matrix& operator += (const Matrix& other_matrix); + Matrix& operator -= (const Matrix& other_matrix); + template + friend std::ostream& operator<<(std::ostream&, const Matrix& matrix); + + Matrix& operator=(const Matrix& other); +}; +template +size_t Matrix::getM() const noexcept { + return _M; +} +template +size_t Matrix::getN() const noexcept { + return _N; +} +template +Matrix::Matrix() : MathVector>(), _M(0), _N(0) {} +template +Matrix::Matrix(size_t M, size_t N) : MathVector>(M) { + _M = M; + _N = N; + for (size_t i = 0; i < _M; ++i) { + (*this)[i] = MathVector(_N); + } +} +template +Matrix::Matrix(T* data, size_t M, size_t N) : MathVector>(M) { + _M = M; + _N = N; + for (size_t i = 0; i < _M; ++i) { + (*this)[i] = MathVector(data + i * _N, _N); + } +} +template +Matrix::Matrix(const Matrix& other) : + MathVector>(other), _M(other._M), _N(other._N) {} +template +Matrix::~Matrix() = default; +template +Matrix Matrix::operator * (T value) const { + return Matrix(*this) *= value; +} +template +Matrix Matrix::operator / (T value) const { + if (value == 0) { + throw std::logic_error("Division by zero!"); + } + return Matrix(*this) /= value; +} +template +Matrix& Matrix::operator *= (T value) { + template + Matrix& Matrix::operator *= (T value) { + for (size_t i = 0; i < _M; ++i) { + (*this)[i] *= value; + } + return *this; + } +} +template +Matrix& Matrix::operator /= (T value) { + if (value == 0) { + throw std::logic_error("Division by zero!"); + } + for (size_t i = 0; i < _M; ++i) { + (*this)[i] /= value; + } + return *this; +} +template +Matrix Matrix::operator + (const Matrix& other_matrix) const { + if (_M != other_matrix.getM() || _N != other_matrix.getN()) { + throw std::logic_error("The matrices have different sizes!"); + } + return Matrix(*this) += other_matrix; +} +template +Matrix Matrix::operator - (const Matrix& other_matrix) const { + if (_M != other_matrix.getM() || _N != other_matrix.getN()) { + throw std::logic_error("The matrices have different sizes!"); + } + return Matrix(*this) -= other_matrix; +} +template +Matrix Matrix::operator * (const Matrix& other_matrix) const { + if (_N != other_matrix.getM()) { + throw std::logic_error + ("The sizes of the matrices are not compatible for this operation!"); + } + Matrix result(_M, other_matrix.getN()); + Matrix matrix_t = other_matrix.transpose(); + for (size_t i = 0; i < _M; ++i) { + for (size_t j = 0; j < matrix_t.getM(); ++j) { + result[i][j] = (*this)[i] * matrix_t[j]; + } + } + return result; +} +template +MathVector Matrix::operator * (const MathVector& vector) const { + if (_N != vector.get_size()) { + throw std::logic_error + ("Size of matrix aren't compatible with vector's size for this operation!"); + } + MathVector result(_M); + for (size_t i = 0; i < _M; ++i) { + result[i] = (*this)[i] * vector; + } + return result; +} +template +Matrix& Matrix::operator += (const Matrix& other_matrix) { + if (_M != other_matrix.getM() || _N != other_matrix.getN()) { + throw std::logic_error("The matrices have different sizes!"); + } + for (size_t i = 0; i < _M; ++i) { + (*this)[i] += other_matrix[i]; + } + return *this; +} +template +Matrix& Matrix::operator -= (const Matrix& other_matrix) { + if (_M != other_matrix.getM() || _N != other_matrix.getN()) { + throw std::logic_error("The matrices have different sizes!"); + } + for (size_t i = 0; i < _M; ++i) { + (*this)[i] -= other_matrix[i]; + } + return *this; +} +template +Matrix& Matrix::operator=(const Matrix& other) { + if (this != &other) { + MathVector>::operator=(other); + _M = other._M; + _N = other._N; + } + return *this; +} +template +std::ostream& operator<<(std::ostream& out, const Matrix& matrix) { + for (size_t i = 0; i < matrix.getM(); ++i) { + for (size_t j = 0; j < matrix.getN(); ++j) { + out << matrix[i][j] << "\t"; + } + out << std::endl; + } + return out; +} diff --git a/lib_monom/CMakeLists.txt b/lib_monom/CMakeLists.txt new file mode 100644 index 00000000..c81f4342 --- /dev/null +++ b/lib_monom/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Monom) \ No newline at end of file diff --git a/lib_monom/monom.cpp b/lib_monom/monom.cpp new file mode 100644 index 00000000..5621484c --- /dev/null +++ b/lib_monom/monom.cpp @@ -0,0 +1,199 @@ +#include "monom.h" +const double EPSILON = 1e-10; +bool Monom::operator ==(const Monom& other_monom) const { + return this->powerX() == other_monom.powerX() && + this->powerY() == other_monom.powerY() && + this->powerZ() == other_monom.powerZ(); +} +bool Monom::operator !=(const Monom& other_monom) const { + return !(*this == other_monom); +} +bool Monom::operator >(const Monom& other_monom) const { + int total_degree_this = this->powerX() + this->powerY() + this->powerZ(); + int total_degree_other = other_monom.powerX() + other_monom.powerY() + other_monom.powerZ(); + + if (total_degree_this == total_degree_other) { + + int pow_x_this = this->powerX(); + int pow_y_this = this->powerY(); + int pow_z_this = this->powerZ(); + + int pow_x_other = other_monom.powerX(); + int pow_y_other = other_monom.powerY(); + int pow_z_other = other_monom.powerZ(); + + if (pow_x_this != pow_x_other) { + return (pow_x_this > pow_x_other); + } + if (pow_y_this != pow_y_other) { + return (pow_y_this > pow_y_other); + } + if (pow_z_this != pow_z_other) { + return (pow_z_this > pow_z_other); + } + return false; + } + return total_degree_this > total_degree_other; +} +bool Monom::operator<(const Monom& other_monom) const { + return other_monom > *this; +} +Monom Monom::operator +(const Monom& other_monom) const { + if (*this != other_monom) { + throw std::invalid_argument("Monoms must be similar"); + } + double new_coefficient = this->get_coefficient() + other_monom.get_coefficient(); + return Monom(new_coefficient, this->powerX(), this->powerY(), this->powerZ()); +} +Monom Monom::operator -(const Monom& other_monom) const { + if (*this != other_monom) { + throw std::invalid_argument("Monoms must be similar"); + } + double new_coefficient = this->get_coefficient() - other_monom.get_coefficient(); + return Monom(new_coefficient, this->powerX(), this->powerY(), this->powerZ()); +} +Monom Monom::operator *(const Monom& other_monom) const { + double new_coefficient = this->get_coefficient() * other_monom.get_coefficient(); + int new_x = this->powerX() + other_monom.powerX(); + int new_y = this->powerY() + other_monom.powerY(); + int new_z = this->powerZ() + other_monom.powerZ(); + return Monom(new_coefficient, new_x, new_y, new_z); +} +Monom Monom::operator *(double value) const { + double new_coefficient = value * this->get_coefficient(); + return Monom(new_coefficient, this->powerX(), this->powerY(), this->powerZ()); +} +Monom Monom::operator /(const Monom& other_monom) const { + if (std::abs(other_monom.get_coefficient()) < EPSILON) { + throw std::invalid_argument("Division by zero"); + } + if (other_monom.powerX() > this->powerX() || + other_monom.powerY() > this->powerY() || + other_monom.powerZ() > this->powerZ()) { + throw std::invalid_argument("Negative power in division"); + } + double new_coefficient = this->get_coefficient() / other_monom.get_coefficient(); + int new_x = this->powerX() - other_monom.powerX(); + int new_y = this->powerY() - other_monom.powerY(); + int new_z = this->powerZ() - other_monom.powerZ(); + return Monom(new_coefficient, new_x, new_y, new_z); +} +Monom Monom::operator /(double value) const { + if (std::abs(value) < EPSILON) { + throw std::invalid_argument("Division by zero"); + } + double new_coefficient = this->get_coefficient() / value; + return Monom(new_coefficient, this->powerX(), this->powerY(), this->powerZ()); +} +Monom& Monom::operator +=(const Monom& other_monom) { + if (*this != other_monom) { + throw std::invalid_argument("Monoms must be similar"); + } + double new_coefficient = this->get_coefficient() + other_monom.get_coefficient(); + this->set_coefficient(new_coefficient); + return *this; +} +Monom& Monom::operator -=(const Monom& other_monom) { + if (*this != other_monom) { + throw std::invalid_argument("Monoms must be similar"); + } + double new_coefficient = this->get_coefficient() - other_monom.get_coefficient(); + this->set_coefficient(new_coefficient); + return *this; +} +Monom& Monom::operator *=(const Monom& other_monom) { + double new_coefficient = this->get_coefficient() * other_monom.get_coefficient(); + int new_x = this->powerX() + other_monom.powerX(); + int new_y = this->powerY() + other_monom.powerY(); + int new_z = this->powerZ() + other_monom.powerZ(); + this->set_coefficient(new_coefficient); + this->set_powers(new_x, new_y, new_z); + return *this; +} +Monom& Monom::operator *=(double value) { + this->set_coefficient(this->get_coefficient() * value); + return *this; +} +Monom& Monom::operator /=(const Monom& other_monom) { + if (std::abs(other_monom.get_coefficient()) < EPSILON) { + throw std::invalid_argument("Division by zero"); + } + if (other_monom.powerX() > this->powerX() || + other_monom.powerY() > this->powerY() || + other_monom.powerZ() > this->powerZ()) { + throw std::invalid_argument("Negative power in division"); + } + double new_coefficient = this->get_coefficient() / other_monom.get_coefficient(); + int new_x = this->powerX() - other_monom.powerX(); + int new_y = this->powerY() - other_monom.powerY(); + int new_z = this->powerZ() - other_monom.powerZ(); + this->set_coefficient(new_coefficient); + this->set_powers(new_x, new_y, new_z); + return *this; +} +Monom& Monom::operator /=(double value) { + if (std::abs(value) < EPSILON) { + throw std::invalid_argument("Division by zero"); + } + this->set_coefficient(this->get_coefficient() / value); + return *this; +} +double Monom::calculate(double x, double y, double z) const { + return _coefficient * + std::pow(x, _powers[0]) * + std::pow(y, _powers[1]) * + std::pow(z, _powers[2]); +} +std::ostream& operator<<(std::ostream& out, const Monom& monom) { + double coefficient = monom.get_coefficient(); + int power_x = monom.powerX(); + int power_y = monom.powerY(); + int power_z = monom.powerZ(); + + if (std::abs(coefficient) < EPSILON) { + out << "0"; + return out; + } + if (std::abs(coefficient - 1.0) > EPSILON || + (power_x == 0 && power_y == 0 && power_z == 0)) { + out << coefficient; + } + if (power_x > 0) { + out << "x"; + if (power_x > 1) { + out << "^" << power_x; + } + } + if (power_y > 0) { + out << "y"; + if (power_y > 1) { + out << "^" << power_y; + } + } + if (power_z > 0) { + out << "z"; + if (power_z > 1) { + out << "^" << power_z; + } + } + if (std::abs(coefficient - 1.0) < EPSILON && + power_x == 0 && power_y == 0 && power_z == 0) { + out << "1"; + } + return out; +} +std::istream& operator>>(std::istream& input, Monom& monom) { + double coefficient; + int power_x, power_y, power_z; + input >> coefficient >> power_x >> power_y >> power_z; + if (input) { + if (power_x >= 0 && power_y >= 0 && power_z >= 0) { + monom.set_coefficient(coefficient); + monom.set_powers(power_x, power_y, power_z); + } + else { + input.setstate(std::ios::failbit); + } + } + return input; +} diff --git a/lib_monom/monom.h b/lib_monom/monom.h new file mode 100644 index 00000000..412d4085 --- /dev/null +++ b/lib_monom/monom.h @@ -0,0 +1,73 @@ +#include +#include +#include +class Monom { +private: + static constexpr size_t VAR_COUNT = 3; // Monom ( ) + double _coefficient; + int _powers[VAR_COUNT]; +public: + double get_coefficient() const noexcept { + return _coefficient; + } + int powerX() const noexcept { + return _powers[0]; + } + int powerY() const noexcept { + return _powers[1]; + } + int powerZ() const noexcept { + return _powers[2]; + } + void set_coefficient(double value) { + _coefficient = value; + } + void set_powers(int value1, int value2, int value3) { + if (value1 < 0 || value2 < 0 || value3 < 0) { + throw std::invalid_argument("Powers cannot be negative"); + } + _powers[0] = value1; + _powers[1] = value2; + _powers[2] = value3; + } + Monom(double coefficient = 0.0): _coefficient(coefficient) { + for (size_t i = 0; i < VAR_COUNT; i++) { + _powers[i] = 0; + } + } + Monom(double coefficient, int x_power, int y_power, int z_power) + : _coefficient(coefficient) + , _powers{ x_power, y_power, z_power } { + if (x_power < 0 || y_power < 0 || z_power < 0) { + throw std::invalid_argument("Powers cannot be negative"); + } + } + Monom(const Monom& other) = default; + bool operator ==(const Monom& other_monom) const; + bool operator !=(const Monom& other_monom) const; + bool operator >(const Monom& other_monom) const; + bool operator <(const Monom& other_monom) const; + + Monom& operator=(const Monom& other) = default; + + Monom operator +(const Monom& other_monom) const; + Monom operator -(const Monom& other_monom) const; + Monom operator *(const Monom& other_monom) const; + Monom operator *(double value) const; + Monom operator /(const Monom& other_monom) const; + Monom operator /(double value) const; + + Monom& operator +=(const Monom& other_monom); + Monom& operator -=(const Monom& other_monom); + Monom& operator *=(const Monom& other_monom); + Monom& operator *=(double value); + Monom& operator /=(const Monom& other_monom); + Monom& operator /=(double value); + + Monom operator -() const { + return Monom(_coefficient * (-1), _powers[0], _powers[1], _powers[2]); + } + double calculate(double x, double y, double z) const; + friend std::ostream& operator<<(std::ostream& out, const Monom& monom); + friend std::istream& operator>>(std::istream& input, Monom& monom); +}; diff --git a/lib_polynom/CMakeLists.txt b/lib_polynom/CMakeLists.txt new file mode 100644 index 00000000..e0f32730 --- /dev/null +++ b/lib_polynom/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Polynom) \ No newline at end of file diff --git a/lib_polynom/polynom.cpp b/lib_polynom/polynom.cpp new file mode 100644 index 00000000..a8da31ae --- /dev/null +++ b/lib_polynom/polynom.cpp @@ -0,0 +1,255 @@ +#include "polynom.h" +Polynom::Polynom(const std::string& str) { + if (str.empty()) { + return; + } + std::stringstream ss(str); + std::string token; + char sign = '+'; + while (ss >> token) { + if (token == "+" || token == "-") { + sign = token[0]; + continue; + } + Monom monom = parseMonom(token); + if (sign == '-') { + monom.set_coefficient(-monom.get_coefficient()); + } + *this += monom; + + sign = '+'; + } + simplify(); +} +Polynom Polynom::operator +(const Polynom& other_polynom) const { + Polynom result = *this; + for (auto it = other_polynom._polynom.begin(); it != other_polynom._polynom.end(); it++) { + result += *it; + } + return result; +} +Polynom Polynom::operator -(const Polynom& other_polynom) const { + Polynom result = *this; + for (auto it = other_polynom._polynom.begin(); it != other_polynom._polynom.end(); it++) { + result -= *it; + } + return result; +} +Polynom Polynom::operator *(const Polynom& other_polynom) const { + Polynom result; + for (auto it1 = _polynom.begin(); it1 != _polynom.end(); it1++) { + for (auto it2 = other_polynom._polynom.begin(); it2 != other_polynom._polynom.end(); it2++) { + result += (*it1) * (*it2); + } + } + return result; +} +Polynom& Polynom::operator +=(const Polynom& other_polynom) { + *this = *this + other_polynom; + return *this; +} +Polynom& Polynom::operator -=(const Polynom& other_polynom) { + *this = *this - other_polynom; + return *this; +} +Polynom& Polynom::operator *=(const Polynom& other_polynom) { + *this = *this * other_polynom; + return *this; +} +Polynom Polynom::operator+(const Monom& other_monom) const { + Polynom result = *this; + result += other_monom; + return result; +} +Polynom Polynom::operator -(const Monom& other_monom) const { + Polynom result = *this; + result -= other_monom; + return result; +} +Polynom Polynom::operator *(const Monom& other_monom) const { + Polynom result = *this; + result *= other_monom; + return result; +} + +Polynom& Polynom::operator+=(const Monom& other_monom) { + _polynom.push_back(other_monom); + simplify(); + return *this; +} +Polynom& Polynom::operator-=(const Monom& other_monom) { + _polynom.push_back(-other_monom); + simplify(); + return *this; +} +Polynom& Polynom::operator *=(const Monom& other_monom) { + for (auto it = _polynom.begin(); it != _polynom.end(); it++) { + *it = *it * other_monom; + } + return *this; +} +Polynom& Polynom::operator=(const Polynom& other) { + if (this != &other) { + _polynom = other._polynom; + } + return *this; +} +Polynom Polynom::operator-() const { + Polynom result; + for (auto it = _polynom.begin(); it != _polynom.end(); it++) { + result += -(*it); + } + return result; +} +double Polynom::calculate(double x, double y, double z) const { + double result = 0.0; + for (auto it = _polynom.begin(); it != _polynom.end(); it++) { + result += (*it).calculate(x, y, z); + } + return result; +} +std::ostream& operator<<(std::ostream& out, const Polynom& polynom) { + if (polynom.is_zero()) { + out << "0"; + return out; + } + auto it = polynom._polynom.begin(); + out << *it; + for (++it; it != polynom._polynom.end(); it++) { + double coef = (*it).get_coefficient(); + + if (coef > 0) { + out << " + " << *it; + } + else { + out << " - " << -(*it); + } + } + return out; +} +std::istream& operator>>(std::istream& input, Polynom& polynom) { + polynom = Polynom(); + char c; + bool positive = true; + std::string monom_str; + while (input.get(c)) { + if (c == '+' || c == '-') { + if (!monom_str.empty()) { + try { + Monom m; + std::istringstream iss(monom_str); + iss >> m; + if (!positive) { + m = -m; + } + polynom._polynom.push_back(m); + } + catch (std::exception& ex) { + input.setstate(std::ios::failbit); + return input; + } + monom_str.clear(); + } + positive = (c == '+'); + } + else if (!isspace(c)) { + monom_str += c; + } + } + if (!monom_str.empty()) { + try { + Monom m; + std::istringstream iss(monom_str); + iss >> m; + if (!positive) { + m = -m; + } + polynom._polynom.push_back(m); + } + catch (std::exception& ex) { + input.setstate(std::ios::failbit); + return input; + } + } + polynom.sort(); + polynom.simplify(); + + return input; +} +void Polynom::sort() { + if (_polynom.get_size() <= 1) return; + std::vector temp; + for (auto it = _polynom.begin(); it != _polynom.end(); ++it) { + temp.push_back(*it); + } + std::sort(temp.begin(), temp.end(), + [](const Monom& a, const Monom& b) { return a > b; }); + while (!_polynom.is_empty()) { + _polynom.pop_back(); + } + for (const auto& m : temp) { + _polynom.push_back(m); + } +} +void Polynom::simplify() { + sort(); + size_t i = 0; + while (i + 1 < _polynom.get_size()) { + auto it1 = _polynom.begin(); + for (size_t k = 0; k < i; ++k) ++it1; + auto it2 = it1; + ++it2; + if ((*it1) == (*it2)) { + double new_coef = (*it1).get_coefficient() + (*it2).get_coefficient(); + (*it1).set_coefficient(new_coef); + _polynom.erase(i + 1); + } + else { + ++i; + } + } + i = 0; + while (i < _polynom.get_size()) { + auto it = _polynom.begin(); + for (size_t k = 0; k < i; ++k) ++it; + if (std::abs((*it).get_coefficient()) < EPSILON) { + _polynom.erase(i); + } + else { + ++i; + } + } +} +Monom Polynom::parseMonom(const std::string& token) const { + if (token.empty()) { + throw std::invalid_argument("Empty monom token"); + } + double coefficient = 1.0; + int powers[3] = { 0, 0, 0 }; // [x, y, z] + size_t pos = 0; + if (isdigit(token[pos]) || token[pos] == '.') { + size_t end; + coefficient = std::stod(token.substr(pos), &end); + pos = end; + } + while (pos < token.length()) { + char var = token[pos]; + pos++; + + int var_index = -1; + if (var == 'x') var_index = 0; + else if (var == 'y') var_index = 1; + else if (var == 'z') var_index = 2; + else throw std::invalid_argument("Invalid variable: " + std::string(1, var)); + + int power = 1; + if (pos < token.length() && token[pos] == '^') { + pos++; + size_t end; + power = std::stoi(token.substr(pos), &end); + pos += end; + } + powers[var_index] = power; + } + return Monom(coefficient, powers[0], powers[1], powers[2]); +} diff --git a/lib_polynom/polynom.h b/lib_polynom/polynom.h new file mode 100644 index 00000000..42fa776a --- /dev/null +++ b/lib_polynom/polynom.h @@ -0,0 +1,61 @@ +#include "../lib_monom/monom.h" +#include "../lib_list/List.h" +#include +#include +#include +#include +#include +#include +class Polynom { +private: + List _polynom; + static constexpr double EPSILON = 1e-10; + void simplify(); + void sort(); + Monom parseMonom(const std::string& token) const; +public: + Polynom() : _polynom() {} + Polynom(const Monom& monom) { + _polynom.push_back(monom); + } + Polynom(const std::string& string); + Polynom(const char* str) { + if (!str) { + throw std::invalid_argument("Null string pointer"); + } + // C- std::string + *this = Polynom(std::string(str)); + } + Polynom(const Polynom& other) { + _polynom = other._polynom; + } + Polynom& operator=(const Polynom& other); + + Polynom operator +(const Polynom& other_polynom) const; + Polynom operator -(const Polynom& other_polynom) const; + Polynom operator *(const Polynom& other_polynom) const; + + Polynom& operator +=(const Polynom& other_polynom); + Polynom& operator -=(const Polynom& other_polynom); + Polynom& operator *=(const Polynom& other_polynom); + + Polynom operator +(const Monom& other_monom) const; + Polynom operator -(const Monom& other_monom) const; + Polynom operator *(const Monom& other_monom) const; + + Polynom& operator *=(const Monom& other_monom); + Polynom& operator +=(const Monom& other_monom); + Polynom& operator -=(const Monom& other_monom); + + Polynom operator-() const; + + double calculate(double x, double y, double z) const; + bool is_zero() const noexcept { + return _polynom.is_empty(); + } + size_t size() const noexcept { + return _polynom.get_size(); + } + friend std::ostream& operator<<(std::ostream& out, const Polynom& polynom); + friend std::istream& operator>>(std::istream& input, Polynom& polynom); +}; diff --git a/lib_queue/CMakeLists.txt b/lib_queue/CMakeLists.txt new file mode 100644 index 00000000..f0846b24 --- /dev/null +++ b/lib_queue/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Queue) \ No newline at end of file diff --git a/lib_queue/queue.cpp b/lib_queue/queue.cpp new file mode 100644 index 00000000..462f7c08 --- /dev/null +++ b/lib_queue/queue.cpp @@ -0,0 +1 @@ +#include "queue.h" \ No newline at end of file diff --git a/lib_queue/queue.h b/lib_queue/queue.h new file mode 100644 index 00000000..f88f6b11 --- /dev/null +++ b/lib_queue/queue.h @@ -0,0 +1,93 @@ +#pragma once +#include +template +class Queue { +private: + T* _data; + size_t _size; + size_t _head; + size_t _tail; + size_t _count; +public: + explicit Queue(size_t size); + Queue(const Queue& other); + ~Queue(); + inline T head() const; + inline T tail() const; + size_t size() const noexcept; + size_t count() const noexcept; + bool is_empty() const noexcept; + bool is_full() const noexcept; + void push(T value); + void pop(); + void clear() noexcept; +}; +template +Queue::Queue(size_t size): _size(size), _head(0), _tail(0), _count(0) { + _data = new T[size]; +} +template +Queue::Queue(const Queue& other): _size(other._size), _head(other._head), _tail(other._tail), _count(other._count) { + _data = new T[other._size]; + for (size_t i = 0; i < _size; ++i) { + _data[i] = other._data[i]; + } +} +template +Queue::~Queue() { + delete[] _data; + _data = nullptr; +} +template +inline T Queue::head() const { + if (this->is_empty()) { + throw std::runtime_error("Can't get head: queue is empty"); + } + return _data[_head]; +} +template +inline T Queue::tail() const { + if (this->is_empty()) { + throw std::runtime_error("Can't get tail: queue is empty"); + } + return _data[(_tail + _size - 1) % _size]; +} +template +size_t Queue::size() const noexcept { + return _size; +} +template +size_t Queue::count() const noexcept { + return _count; +} +template +bool Queue::is_empty() const noexcept { + return _count == 0; +} +template +bool Queue::is_full() const noexcept { + return _count == _size; +} +template +void Queue::push(T value) { + if (this->is_full()) { + throw std::logic_error("The queue is full, you can't push the element"); + } + _data[_tail] = value; + _tail = (_tail + 1) % _size; + _count++; +} +template +void Queue::pop() { + if (this->is_empty()) { + throw std::logic_error("The queue is empty, you can't pop the element"); + } + _head = (_head + 1) % _size; + _count--; +} +template +void Queue::clear() noexcept { + _head = 0; + _tail = 0; + _count = 0; +} diff --git a/lib_queue_on_list/CMakeLists.txt b/lib_queue_on_list/CMakeLists.txt new file mode 100644 index 00000000..fcef8d62 --- /dev/null +++ b/lib_queue_on_list/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(QueueOnList) \ No newline at end of file diff --git a/lib_queue_on_list/queue_on_list.cpp b/lib_queue_on_list/queue_on_list.cpp new file mode 100644 index 00000000..69794cd2 --- /dev/null +++ b/lib_queue_on_list/queue_on_list.cpp @@ -0,0 +1 @@ +#include "queue_on_list.h" diff --git a/lib_queue_on_list/queue_on_list.h b/lib_queue_on_list/queue_on_list.h new file mode 100644 index 00000000..704b8e33 --- /dev/null +++ b/lib_queue_on_list/queue_on_list.h @@ -0,0 +1,113 @@ +#pragma once +#include "../lib_list/List.h" +template +class QueueOnList { +private: + List _list; + size_t _max_size; + bool _has_max_size = false; +public: + QueueOnList(size_t size = 0); + QueueOnList(const QueueOnList& other); + ~QueueOnList() = default; + QueueOnList& operator=(const QueueOnList& other); + bool operator ==(const QueueOnList& other) const; + bool operator !=(const QueueOnList& other) const; + inline T head() const; + inline T tail() const; + size_t size() const noexcept; + size_t max_size() const noexcept; + bool has_max_size() const noexcept; + bool is_empty() const noexcept; + void push(T value); + void pop(); + inline bool is_full() const noexcept; + void clear() noexcept; +}; +template +QueueOnList::QueueOnList(size_t size) { + _max_size = size; + if (_max_size != 0) { + _has_max_size = true; + } +} +template +QueueOnList::QueueOnList(const QueueOnList& other) { + _list = other._list; + _max_size = other._max_size; + _has_max_size = other._has_max_size; +} +template +T QueueOnList::head() const { + if (_list.is_empty()) { + throw std::runtime_error("Can't get head: queue is empty"); + } + return *(_list.begin()); +} +template +T QueueOnList::tail() const { + if (this->is_empty()) { + throw std::runtime_error("Can't get tail: queue is empty"); + } + return _list.get_last_element(); +} +template +size_t QueueOnList::size() const noexcept { + return _list.get_size(); +} +template +size_t QueueOnList::max_size() const noexcept { + return _max_size; +} +template +bool QueueOnList::has_max_size() const noexcept { + return _has_max_size; +} +template +bool QueueOnList::is_empty() const noexcept { + return _list.is_empty(); +} +template +void QueueOnList::push(T value) { + if (is_full()) { + throw std::logic_error("Can't push element: queue is full"); + } + _list.push_back(value); +} +template +void QueueOnList::pop() { + if (_list.is_empty()) { + throw std::logic_error("Can't pop from empty queue"); + } + _list.pop_front(); +} +template +bool QueueOnList::is_full() const noexcept { + if (_has_max_size == false) { + return false; + } + return _max_size == _list.get_size(); +} +template +void QueueOnList::clear() noexcept { + while (!_list.is_empty()) { + _list.pop_front(); + } +} +template +QueueOnList& QueueOnList::operator=(const QueueOnList& other) { + if (this != &other) { + _list = other._list; + _max_size = other._max_size; + _has_max_size = other._has_max_size; + } + return *this; +} +template +bool QueueOnList::operator ==(const QueueOnList& other) const { + return this->_list == other._list; +} +template +bool QueueOnList::operator !=(const QueueOnList& other) const { + return !(this->_list == other._list); +} diff --git a/lib_skip_list/CMakeLists.txt b/lib_skip_list/CMakeLists.txt new file mode 100644 index 00000000..63e5c186 --- /dev/null +++ b/lib_skip_list/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(SkipList) \ No newline at end of file diff --git a/lib_skip_list/skip_list.cpp b/lib_skip_list/skip_list.cpp new file mode 100644 index 00000000..5fc215d4 --- /dev/null +++ b/lib_skip_list/skip_list.cpp @@ -0,0 +1 @@ +#include "skip_list.h" diff --git a/lib_skip_list/skip_list.h b/lib_skip_list/skip_list.h new file mode 100644 index 00000000..20f5e8a4 --- /dev/null +++ b/lib_skip_list/skip_list.h @@ -0,0 +1,25 @@ +#pragma once +#include "../lib_list/List.h" +template +struct SkipListNode { //- + std::pair data_; + SkipListNode** next_; + size_t height_; +public: + SkipListNode(); + ~SkipListNode(); +}; +template +class SkipList { + size_t _max_count_levels; + size_t _current_count_levels; + List*> _heads; +public: + SkipList(); + ~SkipList(); + void insert(const Tkey& key, const Tvalue& value); + void print() const noexcept; +protected: + size_t flip_coin() const noexcept; // insert + SkipListNode* find_nearest(const Tkey& key) const noexcept; +}; diff --git a/lib_stack/CMakeLists.txt b/lib_stack/CMakeLists.txt new file mode 100644 index 00000000..b6bedb01 --- /dev/null +++ b/lib_stack/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(Stack) \ No newline at end of file diff --git a/lib_stack/stack.cpp b/lib_stack/stack.cpp new file mode 100644 index 00000000..3d38ae2e --- /dev/null +++ b/lib_stack/stack.cpp @@ -0,0 +1 @@ +#include "stack.h" \ No newline at end of file diff --git a/lib_stack/stack.h b/lib_stack/stack.h new file mode 100644 index 00000000..1a50b9d5 --- /dev/null +++ b/lib_stack/stack.h @@ -0,0 +1,82 @@ +#pragma once +#include "../lib_vector/vector.h" +template +class Stack { +private: + Tvector _data; +public: + Stack(size_t size); + Stack(const Stack& other); + size_t size(); + const Tvector& getData() const; + Stack& operator=(const Stack& other); + bool operator ==(const Stack& other) const; + bool operator !=(const Stack& other) const; + void push(T value); + void pop(); + inline T top() const; + inline bool is_empty() const noexcept; + inline bool is_full() const noexcept; + void clear() noexcept; +}; +template +size_t Stack::size() { + return _data.get_size(); +} +template +Stack::Stack(size_t size): _data(size) { +} +template +Stack::Stack(const Stack& other): _data(other.getData()) {} +template +const Tvector& Stack::getData() const { + return _data; +} +template +Stack& Stack::operator=(const Stack& other) { + if (this != &other) { + _data = other.getData(); + } + return *this; +} +template +bool Stack::operator ==(const Stack& other) const { + return _data == other.getData(); +} +template +bool Stack::operator !=(const Stack& other) const { + return !(_data == other.getData()); +} +template +inline T Stack::top() const { + if (is_empty()) { + throw std::logic_error("Stack is empty, you can't get top element's index"); + } + return _data.back(); +} +template +void Stack::push(T value) { + if (is_full()) { + throw std::logic_error("You can't push the element, because stack is full"); + } + _data.push_back(value); +} +template +void Stack::pop() { + if (is_empty()) { + throw std::logic_error("You can't pop the element, because stack is empty"); + } + _data.pop_back(); +} +template +inline bool Stack::is_empty() const noexcept { + return _data.is_empty(); +} +template +inline bool Stack::is_full() const noexcept { + return _data.is_full(); +} +template +void Stack::clear() noexcept { + _data.clear(); +} diff --git a/lib_stack_on_list/CMakeLists.txt b/lib_stack_on_list/CMakeLists.txt new file mode 100644 index 00000000..5e9177c1 --- /dev/null +++ b/lib_stack_on_list/CMakeLists.txt @@ -0,0 +1 @@ +create_project_lib(StackOnList) \ No newline at end of file diff --git a/lib_stack_on_list/stack_on_list.cpp b/lib_stack_on_list/stack_on_list.cpp new file mode 100644 index 00000000..4c67494b --- /dev/null +++ b/lib_stack_on_list/stack_on_list.cpp @@ -0,0 +1 @@ +#include "stack_on_list.h" diff --git a/lib_stack_on_list/stack_on_list.h b/lib_stack_on_list/stack_on_list.h new file mode 100644 index 00000000..c945c182 --- /dev/null +++ b/lib_stack_on_list/stack_on_list.h @@ -0,0 +1,107 @@ +#pragma once +#include "../lib_list/List.h" +#include + +template +class StackOnList { +private: + List _list; + size_t _max_size; + bool _has_max_size = false; +public: + StackOnList(size_t size = 0); + StackOnList(const StackOnList& other); + ~StackOnList() = default; + StackOnList& operator=(const StackOnList& other); + bool operator ==(const StackOnList& other) const; + bool operator !=(const StackOnList& other) const; + void push(T value); + void pop(); + inline T top() const; + inline bool is_empty() const noexcept; + inline bool is_full() const noexcept; + void clear() noexcept; + size_t size() const noexcept; + size_t max_size() const noexcept; + bool has_max_size() const noexcept; +}; +template +StackOnList::StackOnList(size_t size) { + _max_size = size; + if (_max_size != 0) { + _has_max_size = true; + } +} +template +StackOnList::StackOnList(const StackOnList& other) { + _list = other._list; + _max_size = other._max_size; + _has_max_size = other._has_max_size; +} +template +size_t StackOnList::size() const noexcept { + return _list.get_size(); +} +template +size_t StackOnList::max_size() const noexcept { + return _max_size; +} +template +bool StackOnList::has_max_size() const noexcept { + return _has_max_size; +} +template +StackOnList& StackOnList::operator=(const StackOnList& other) { + if (this != &other) { + _list = other._list; + _max_size = other._max_size; + _has_max_size = other._has_max_size; + } + return *this; +} +template +bool StackOnList::operator==(const StackOnList& other) const { + return this->_list == other._list; +} +template +bool StackOnList::operator !=(const StackOnList& other) const { + return !(this->_list == other._list); +} +template +void StackOnList::push(T value) { + if (is_full()) { + throw std::logic_error("Can't push the element: stack is full"); + } + _list.push_front(value); +} +template +void StackOnList::pop() { + if (_list.is_empty()) { + throw std::logic_error("Can't pop from empty stack"); + } + _list.pop_front(); +} +template +inline T StackOnList::top() const { + if (_list.is_empty()) { + throw std::logic_error("Stack is empty, you can't get top element"); + } + return *(_list.begin()); +} +template +inline bool StackOnList::is_empty() const noexcept { + return _list.is_empty(); +} +template +bool StackOnList::is_full() const noexcept { + if (_has_max_size == false) { + return false; + } + return _max_size == _list.get_size(); +} +template +void StackOnList::clear() noexcept { + while (!_list.is_empty()) { + _list.pop_front(); + } +} diff --git a/lib_triangle_matrix/triangle_matrix.h b/lib_triangle_matrix/triangle_matrix.h new file mode 100644 index 00000000..d4a05bb3 --- /dev/null +++ b/lib_triangle_matrix/triangle_matrix.h @@ -0,0 +1,245 @@ +#pragma once +#include "../lib_matrix/matrix.h" + +template +class TriangleMatrix : public Matrix { +public: + TriangleMatrix(); + TriangleMatrix(size_t size); + TriangleMatrix(T* data, size_t size); + TriangleMatrix(const TriangleMatrix& other); + ~TriangleMatrix(); + + + size_t getSize() const { + return this->_M; + } + + TriangleMatrix operator + (T value) const; + TriangleMatrix operator - (T value) const; + TriangleMatrix operator * (T value) const; + TriangleMatrix operator / (T value) const; + + TriangleMatrix& operator += (T value); + TriangleMatrix& operator -= (T value); + TriangleMatrix& operator *= (T value); + TriangleMatrix& operator /= (T value); + + MathVector operator * (const MathVector& vector) const; + + TriangleMatrix operator + (const TriangleMatrix& other) const; + TriangleMatrix operator - (const TriangleMatrix& other) const; + TriangleMatrix operator * (const TriangleMatrix& other) const; + + TriangleMatrix& operator += (const TriangleMatrix& other); + TriangleMatrix& operator -= (const TriangleMatrix& other); + TriangleMatrix& operator= (const TriangleMatrix& other); + + friend std::ostream& operator<<(std::ostream& out, const TriangleMatrix& matrix) { + for (size_t i = 0; i < matrix.getSize(); ++i) { + for (size_t j = 0; j < matrix.getSize(); ++j) { + if (i <= j) { + out << matrix[i][j] << "\t"; + } + else { + out << "0\t"; + } + } + out << std::endl; + } + return out; + } +}; +template +TriangleMatrix::TriangleMatrix() : Matrix() {} +template +TriangleMatrix::TriangleMatrix(size_t size) : Matrix(size, size) { + for (size_t i = 0; i < size; ++i) { + (*this)[i] = MathVector(size - i, i); + } +} +template +TriangleMatrix::TriangleMatrix(T* data, size_t size) : Matrix(size, size) { + size_t data_index = 0; + for (size_t i = 0; i < size; ++i) { + (*this)[i] = MathVector(size - i, i); + for (size_t j = i; j < size; ++j) { + (*this)[i][j] = data[data_index++]; + } + } +} +template +TriangleMatrix::TriangleMatrix(const TriangleMatrix& other) : Matrix(other) {} +template +TriangleMatrix::~TriangleMatrix() = default; +template +TriangleMatrix& TriangleMatrix::operator= (const TriangleMatrix& other) { + if (this != &other) { + Matrix::operator=(other); + } + return *this; +} +template +TriangleMatrix TriangleMatrix::operator + (T value) const { + TriangleMatrix result(this->getSize()); + for (size_t i = 0; i < result.getSize(); ++i) { + for (size_t j = i; j < result.getSize(); ++j) { + result[i][j] = (*this)[i][j] + value; + } + } + return result; +} +template +TriangleMatrix TriangleMatrix::operator - (T value) const { + TriangleMatrix result(this->getSize()); + for (size_t i = 0; i < result.getSize(); ++i) { + for (size_t j = i; j < result.getSize(); ++j) { + result[i][j] = (*this)[i][j] - value; + } + } + return result; +} +template +TriangleMatrix TriangleMatrix::operator * (T value) const { + TriangleMatrix result(this->getSize()); + for (size_t i = 0; i < result.getSize(); ++i) { + for (size_t j = i; j < result.getSize(); ++j) { + result[i][j] = (*this)[i][j] * value; + } + } + return result; +} +template +TriangleMatrix TriangleMatrix::operator / (T value) const { + if (value == 0) { + throw std::logic_error("Division by zero!"); + } + TriangleMatrix result(this->getSize()); + for (size_t i = 0; i < result.getSize(); ++i) { + for (size_t j = i; j < result.getSize(); ++j) { + result[i][j] = (*this)[i][j] / value; + } + } + return result; +} +template +TriangleMatrix& TriangleMatrix::operator += (T value) { + for (size_t i = 0; i < this->getSize(); ++i) { + for (size_t j = i; j < this->getSize(); ++j) { + (*this)[i][j] += value; + } + } + return *this; +} +template +TriangleMatrix& TriangleMatrix::operator -= (T value) { + for (size_t i = 0; i < this->getSize(); ++i) { + for (size_t j = i; j < this->getSize(); ++j) { + (*this)[i][j] -= value; + } + } + return *this; +} +template +TriangleMatrix& TriangleMatrix::operator *= (T value) { + for (size_t i = 0; i < this->getSize(); ++i) { + for (size_t j = i; j < this->getSize(); ++j) { + (*this)[i][j] *= value; + } + } + return *this; +} +template +TriangleMatrix& TriangleMatrix::operator /= (T value) { + if (value == 0) { + throw std::logic_error("Division by zero!"); + } + for (size_t i = 0; i < this->getSize(); ++i) { + for (size_t j = i; j < this->getSize(); ++j) { + (*this)[i][j] /= value; + } + } + return *this; +} +template +MathVector TriangleMatrix::operator * (const MathVector& vector) const { + if (this->getSize() != vector.get_size()) { + throw std::logic_error("Matrix columns must equal vector size"); + } + MathVector result(this->getSize()); + for (size_t i = 0; i < this->getSize(); ++i) { + T sum = T(); + for (size_t j = i; j < this->getSize(); ++j) { + sum += (*this)[i][j] * vector[j]; + } + result[i] = sum; + } + return result; +} +template +TriangleMatrix TriangleMatrix::operator + (const TriangleMatrix& other) const { + if (this->getSize() != other.getSize()) { + throw std::logic_error("Matrices must have the same size"); + } + TriangleMatrix result(this->getSize()); + for (size_t i = 0; i < this->getSize(); ++i) { + for (size_t j = i; j < this->getSize(); ++j){ + result[i][j] = (*this)[i][j] + other[i][j]; + } + } + return result; +} +template +TriangleMatrix TriangleMatrix::operator - (const TriangleMatrix& other) const { + if (this->getSize() != other.getSize()) { + throw std::logic_error("Matrices must have the same size"); + } + TriangleMatrix result(this->getSize()); + for (size_t i = 0; i < this->getSize(); ++i) { + for (size_t j = i; j < this->getSize(); ++j){ + result[i][j] = (*this)[i][j] - other[i][j]; + } + } + return result; +} +template +TriangleMatrix& TriangleMatrix::operator += (const TriangleMatrix& other) { + if (this->getSize() != other.getSize()) { + throw std::logic_error("Matrices must have the same size"); + } + for (size_t i = 0; i < this->getSize(); ++i) { + for (size_t j = i; j < this->getSize(); ++j) { + (*this)[i][j] += other[i][j]; + } + } + return *this; +} +template +TriangleMatrix& TriangleMatrix::operator -= (const TriangleMatrix& other) { + if (this->getSize() != other.getSize()) { + throw std::logic_error("Matrices must have the same size"); + } + for (size_t i = 0; i < this->getSize(); ++i) { + for (size_t j = i; j < this->getSize(); ++j) { + (*this)[i][j] -= other[i][j]; + } + } + return *this; +} +template +TriangleMatrix TriangleMatrix::operator * (const TriangleMatrix& other) const { + if (this->getSize() != other.getSize()) { + throw std::logic_error("Matrices must have the same size"); + } + TriangleMatrix result(this->getSize()); + for (size_t i = 0; i < this->getSize(); ++i) { + for (size_t j = i; j < this->getSize(); ++j) { + T sum = T(); + for (size_t k = i; k <= j; ++k) { + sum += (*this)[i][k] * other[k][j]; + } + result[i][j] = sum; + } + } + return result; +} diff --git a/lib_vector/vector.cpp b/lib_vector/vector.cpp new file mode 100644 index 00000000..863a6a8a --- /dev/null +++ b/lib_vector/vector.cpp @@ -0,0 +1 @@ +#include "vector.h" \ No newline at end of file diff --git a/lib_vector/vector.h b/lib_vector/vector.h new file mode 100644 index 00000000..421992ad --- /dev/null +++ b/lib_vector/vector.h @@ -0,0 +1,776 @@ + // Copyright 2025 Zabytina Julia. All rights reserved. + #pragma once + #include + #include + #include + #include + #include + #include + #include + #include + #include + template + class Tvector { + public: + enum State { + empty, busy, deleted + }; + protected: + static constexpr size_t RESERVE_MEMORY = 15; + static constexpr size_t MAX_PERCENT_DELETED = 15; + + size_t _size; + size_t _capacity; + T* _data; + State* _states; + size_t _deleted; + size_t get_real_position(size_t busy_index) const noexcept; + void resize(size_t new_size); + void resize(size_t new_size, const T& value); + void shrink_to_fit(); + void reserve(size_t new_capacity); + void compact_storage(); + public: + class Iterator { + private: + T* _current; + public: + Iterator() : _current(nullptr) {} + Iterator(T* ptr) : _current(ptr) {} + Iterator(const Iterator& other) : _current(other._current) {} + Iterator& operator=(const Iterator& other) { + _current = other._current; + return *this; + } + Iterator& operator+=(size_t n) { + if (_current != nullptr) { + _current += n; + } + return *this; + } + Iterator& operator-=(size_t n) { + if (_current != nullptr) { + _current -= n; + } + return *this; + } + Iterator& operator--() { + if (_current != nullptr) { + _current --; + } + return *this; + } + Iterator operator--(int) { + Iterator it = *this; + if (_current != nullptr) { + _current --; + } + return it; + } + Iterator& operator++() { + if (_current != nullptr) { + _current ++; + } + return *this; + } + Iterator operator++(int) { + Iterator it = *this; + if (_current != nullptr) { + _current ++; + } + return it; + } + bool operator==(const Iterator& it) const { + return this->_current == it._current; + } + bool operator!=(const Iterator& it) const { + return !(*this == it); + } + T& operator*() { + if (_current == nullptr) { + throw std::runtime_error("Dereferencing nullptr"); + } + return *_current; + } + const T& operator*() const { + if (_current == nullptr) { + throw std::runtime_error("Dereferencing nullptr"); + } + return *_current; + } + }; + Tvector() noexcept; + Tvector(size_t size); + Tvector(T* data, size_t size); + Tvector(const Tvector& other_vector); + virtual ~Tvector() noexcept; + inline bool is_full() const noexcept { + return _size == _capacity; + } + inline bool is_empty() const noexcept { + return _size == 0; + } + inline const T* get_data() const noexcept { + return _data; + } + inline T* get_data() noexcept { + return _data; + } + inline const State* get_states() const noexcept { + return _states; + } + inline State* get_states() noexcept { + return _states; + } + inline T& front(); + inline T& back(); + inline const T& front() const; + inline const T& back() const; + size_t get_size() const noexcept { + return _size; + } + size_t get_deleted() const noexcept { + return _deleted; + } + size_t get_capacity() const noexcept { + return _capacity; + } + inline Iterator begin() const noexcept { + return Iterator(_data); + } + inline Iterator end() const noexcept { + return Iterator(_data + _size); + } + bool operator==(const Tvector& vector) const; + bool operator!=(const Tvector& vector) const; + Tvector& operator=(const Tvector& vector); + inline const T& operator[](size_t index) const; + inline T& operator[](size_t index); + T& at(size_t index); + const T& at(size_t index) const; + void assign(const Tvector& vector); + void clear(); + void emplace(size_t index, const T& value); + void push_front(const T& value); + void insert(const T& value, size_t position); + void push_back(const T& value); + void pop_back(); + void erase(size_t position); + void pop_front(); + + template + friend std::ostream& operator<<(std::ostream&, const Tvector& vector); + template friend void shell_sort(Tvector& object) noexcept; + template friend void shuffle(Tvector& object) noexcept; + template friend size_t find_first_element(const Tvector& object, const U& value); + template friend size_t find_last_element(const Tvector& object, const U& value); + template friend size_t find_count_of_all_suitable_elements(const Tvector& object, const U& value); + }; + template + size_t Tvector::get_real_position(size_t busy_index) const noexcept { + size_t busy_count = 0; + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == busy) { + if (busy_count == busy_index) { + return i; + } + ++busy_count; + } + } + return _size; + } + template + void Tvector::resize(size_t new_size) { + if (new_size == _size) { + return; + } + else if (new_size < _size) { + for (size_t i = new_size; i < _size; ++i) { + if (_states[i] == State::deleted) { + _deleted--; + } + _data[i].~T(); + _states[i] = State::empty; + } + _size = new_size; + } + else { + size_t new_capacity = new_size + RESERVE_MEMORY; + T* new_data = static_cast(::operator new(new_capacity * sizeof(T))); + State* new_states = new State[new_capacity]; + for (size_t i = new_size; i < new_capacity; ++i) { + new_states[i] = State::empty; + } + try { + for (size_t i = 0; i < _size; ++i) { + new (new_data + i) T(std::move(_data[i])); + new_states[i] = _states[i]; + } + for (size_t i = _size; i < new_size; ++i) { + new (new_data + i) T(); + new_states[i] = State::busy; + } + for (size_t i = 0; i < _size; ++i) { + _data[i].~T(); + } + ::operator delete(_data); + delete[] _states; + + _data = new_data; + _states = new_states; + _capacity = new_capacity; + _size = new_size; + } + catch (...) { + for (size_t i = 0; i < new_size; ++i) { + new_data[i].~T(); + } + ::operator delete(new_data); + delete[] new_states; + throw; + } + } + } + template + void Tvector::resize(size_t new_size, const T& value) { + if (new_size == _size) { + return; + } + else if (new_size < _size) { + for (size_t i = new_size; i < _size; ++i) { + if (_states[i] == State::deleted) { + _deleted--; + } + _data[i].~T(); + _states[i] = State::empty; + } + _size = new_size; + } + else { + size_t new_capacity = new_size + RESERVE_MEMORY; + T* new_data = static_cast(::operator new(new_capacity * sizeof(T))); + State* new_states = new State[new_capacity]; + for (size_t i = new_size; i < new_capacity; ++i) { + new_states[i] = State::empty; + } + try { + for (size_t i = 0; i < _size; ++i) { + new (new_data + i) T(std::move(_data[i])); + new_states[i] = _states[i]; + } + for (size_t i = _size; i < new_size; ++i) { + new (new_data + i) T(value); + new_states[i] = State::busy; + } + for (size_t i = 0; i < _size; ++i) { + _data[i].~T(); + } + ::operator delete(_data); + delete[] _states; + + _data = new_data; + _states = new_states; + _capacity = new_capacity; + _size = new_size; + } + catch (...) { + for (size_t i = 0; i < new_size; ++i) { + new_data[i].~T(); + } + ::operator delete(new_data); + delete[] new_states; + throw; + } + } + } + template + void Tvector::shrink_to_fit() { + if (_size >= _capacity) { + return; + } + else if (_size == 0) { + delete[] _data; + delete[] _states; + _data = nullptr; + _states = nullptr; + _capacity = 0; + _deleted = 0; + } + else { + T* new_data = new T[_size]; + State* new_states = new State[_size]; + for (size_t i = 0; i < _size; ++i) { + new_data[i] = std::move(_data[i]); + new_states[i] = _states[i]; + } + delete[] _data; + delete[] _states; + _data = new_data; + _states = new_states; + _capacity = _size; + } + } + template + void Tvector::reserve(size_t new_capacity) { + if (new_capacity <= _capacity) { + return; + } + T* new_data = new T[new_capacity]; + State* new_states = new State[new_capacity]; + std::fill_n(new_states, new_capacity, State::empty); + for (size_t i = 0; i < _size; ++i) { + new_data[i] = std::move(_data[i]); + new_states[i] = _states[i]; + } + delete[] _data; + delete[] _states; + _data = new_data; + _states = new_states; + _capacity = new_capacity; + } + template + void Tvector::compact_storage() { + size_t busy_count = 0; + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == State::busy) { + busy_count++; + } + } + std::cout << "compact_storage(): busy_count = " << busy_count << "\n"; + size_t new_capacity = busy_count + RESERVE_MEMORY; + T* new_data = new T[new_capacity]; + State* new_states = new State[new_capacity]; + size_t new_index = 0; + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == State::busy) { + new_data[new_index] = std::move(_data[i]); + new_states[new_index] = State::busy; + new_index++; + } + } + for (size_t i = 0; i < _size; ++i) { + if (_states[i] != State::empty) { + _data[i].~T(); + } + } + delete[] _data; + delete[] _states; + _data = new_data; + _states = new_states; + _capacity = new_capacity; + _size = busy_count; + _deleted = 0; + } + template + Tvector::Tvector() noexcept { + _size = 0; + _capacity = 0; + _data = nullptr; + _states = nullptr; + _deleted = 0; + } + template + Tvector::Tvector(size_t size) { + _size = size; + _capacity = size + RESERVE_MEMORY; + _data = new T[_capacity]; + + try { + _states = new State[_capacity]; + } + catch (const std::bad_alloc&) { + delete[] _data; + throw; + } + _deleted = 0; + + for (size_t i = 0; i < _capacity; ++i) { + _states[i] = i < _size ? State::busy : State::empty; + } + } + template + Tvector::Tvector(T* data, size_t size) { + if (size > 0 && data == nullptr) { + throw std::invalid_argument("Null data pointer with non-zero size"); + } + _size = size; + _capacity = _size + RESERVE_MEMORY; + _data = new T[_capacity]; + try { + _states = new State[_capacity]; + } + catch (const std::bad_alloc&) { + delete[] _data; + throw; + } + for (size_t i = 0; i < _capacity; ++i) { + if (i < _size) { + _data[i] = data[i]; + _states[i] = State::busy; + } + else { + _states[i] = State::empty; + } + } + _deleted = 0; + } + template + Tvector::Tvector(const Tvector& other_vector) { + _size = other_vector._size; + _capacity = other_vector._capacity; + _data = nullptr; + _states = nullptr; + try { + _data = new T[_capacity]; + } + catch (const std::bad_alloc&) { + throw; + } + try { + _states = new State[_capacity]; + } + catch (const std::bad_alloc&) { + delete[] _data; + throw; + } + _deleted = other_vector._deleted; + + for (size_t i = 0; i < other_vector._size; ++i) { + _data[i] = other_vector._data[i]; + _states[i] = other_vector._states[i]; + } + for (size_t i = other_vector._size; i < other_vector._capacity; ++i) { + _states[i] = State::empty; + } + } + template + Tvector::~Tvector() noexcept { + delete[] _data; + delete[] _states; + } + template + inline T& Tvector::front() { + if (_size == 0) { + throw std::out_of_range("Vector is empty"); + } + return _data[0]; + } + template + inline T& Tvector::back() { + if (_size == 0) { + throw std::out_of_range("Vector is empty"); + } + return _data[_size - 1]; + } + template + inline const T& Tvector::front() const { + if (_size == 0) { + throw std::out_of_range("Vector is empty"); + } + return _data[0]; + } + template + inline const T& Tvector::back() const { + if (_size == 0) { + throw std::out_of_range("Vector is empty"); + } + return _data[_size - 1]; + } + template + bool Tvector::operator==(const Tvector& vector) const { + if (this->_size != vector._size) + return false; + + for (size_t i = 0; i < _size; ++i) { + if ((*this)[i] != vector[i]) + return false; + } + return true; + } + template + bool Tvector::operator!=(const Tvector& vector) const { + return !(*this == vector); + } + template + Tvector& Tvector::operator=(const Tvector& vector) { + if (this == &vector) { + return *this; + } + T* new_data = new T[vector._capacity]; + State* new_states = new State[vector._capacity]; + for (size_t i = 0; i < vector._size; ++i) { + new_data[i] = vector._data[i]; + new_states[i] = vector._states[i]; + } + for (size_t i = vector._size; i < vector._capacity; ++i) { + new_states[i] = empty; + } + delete[] _data; + delete[] _states; + _data = new_data; + _states = new_states; + _capacity = vector._capacity; + _size = vector._size; + _deleted = vector._deleted; + + return *this; + } + template + inline const T& Tvector::operator[](size_t index) const { + size_t real_index = get_real_position(index); + return _data[real_index]; + } + template + inline T& Tvector::operator[](size_t index) { + size_t real_index = get_real_position(index); + return _data[real_index]; + } + template + T& Tvector::at(size_t index) { + if (index >= _size) { + throw std::out_of_range("Index out of range"); + } + if (_states[index] != busy) { + throw std::logic_error("Element at this index is not available (deleted or empty)"); + } + size_t real_index = get_real_position(index); + return _data[real_index]; + } + template + const T& Tvector::at(size_t index) const { + size_t real_index = get_real_position(index); + return const_cast(this)->at(real_index); + } + template + void Tvector::assign(const Tvector& vector) { + if (this == &vector) { + return; + } + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == State::busy) { + _data[i].~T(); + } + } + delete[] _data; + delete[] _states; + _capacity = vector._capacity; + _size = vector._size; + _deleted = vector._deleted; + + _data = new T[_capacity]; + _states = new State[_capacity]; + for (size_t i = 0; i < _size; ++i) { + if (vector._states[i] == State::busy) { + new (&_data[i]) T(vector._data[i]); + } + _states[i] = vector._states[i]; + } + std::fill(_states + _size, _states + _capacity, State::empty); + } + template + void Tvector::clear() { + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == State::busy) { + _states[i] = State::empty; + } + } + _size = 0; + _deleted = 0; + } + template + void Tvector::emplace(size_t index, const T& value) { + if (index >= _size) { + throw std::out_of_range("Index out of range"); + } + size_t real_index = get_real_position(index); + if (_states[real_index] == State::deleted) { + --_deleted; + } + _data[real_index] = value; + _states[real_index] = State::busy; + } + template + void Tvector::push_front(const T& value) { + if (_size >= _capacity) { + reserve(_capacity + RESERVE_MEMORY); + } + for (size_t i = _size; i > 0; --i) { + _data[i] = std::move(_data[i - 1]); + _states[i] = _states[i - 1]; + } + _data[0] = value; + _states[0] = State::busy; + _size++; + } + template + void Tvector::insert(const T& value, size_t position) { + if (_size == 0) { + resize(RESERVE_MEMORY); + } + if (position >= _size) { + throw std::out_of_range("Insert position out of range"); + } + size_t real_pos = get_real_position(position); + for (size_t i = _size; i > real_pos; --i) { + _data[i] = std::move(_data[i - 1]); + _states[i] = _states[i - 1]; + } + _data[real_pos] = value; + _states[real_pos] = State::busy; + _size++; + } + template + void Tvector::push_back(const T& value) { + if (_size >= _capacity) { + reserve(_capacity + RESERVE_MEMORY); + } + _data[_size] = value; + _states[_size] = State::busy; + _size++; + } + template + void Tvector::pop_back() { + if (_size == 0) { + throw std::out_of_range("Vector has size = 0"); + } + _states[_size - 1] = State::empty; + _size--; + } + template + void Tvector::erase(size_t position) { + if (position >= _size) { + throw std::out_of_range("Invalid position"); + } + _states[position] = State::deleted; + _deleted++; + if (_deleted * 100 > _size * MAX_PERCENT_DELETED) { + T* new_data = new T[_size - _deleted + RESERVE_MEMORY]; + State* new_states = new State[_size - _deleted + RESERVE_MEMORY]; + size_t new_index = 0; + for (size_t i = 0; i < _size; i++) { + if (_states[i] == State::busy) { + new_data[new_index] = std::move(_data[i]); + new_states[new_index] = State::busy; + new_index++; + } + } + delete[] _data; + delete[] _states; + + _data = new_data; + _states = new_states; + _size = new_index; + _capacity = _size + RESERVE_MEMORY; + _deleted = 0; + } + } + template + void Tvector::pop_front() { + if (_size == 0) { + throw std::out_of_range("Vector has size = 0"); + } + for (size_t i = 0; i < _size; ++i) { + if (_states[i] == State::busy) { + _states[i] = State::deleted; + _deleted++; + if (_deleted * 100 > _size * MAX_PERCENT_DELETED) { + compact_storage(); + } + return; + } + } + } + + template + std::ostream& operator<<(std::ostream& out, const Tvector& vector) { + out << "["; + bool first = true; + for (size_t i = 0; i < vector._size; ++i) { + if (vector._states[i] == Tvector::State::busy) { + if (!first) out << ", "; + out << vector._data[i]; + first = false; + } + } + out << "]"; + return out; + } + template + void shell_sort(Tvector& object) noexcept { + if (object._size < 2 || object._data == nullptr + || object._states == nullptr) { + return; + } + size_t h = 1; + while (h < object._size / 3) { + h = 3 * h + 1; + } + while (h >= 1) { + for (size_t i = h; i < object._size; ++i) { + for (size_t j = i; j >= h; j -= h) { + size_t previous = j - h; + if (object._data[j] < object._data[previous]) { + std::swap(object._data[j], object._data[previous]); + std::swap(object._states[j], object._states[previous]); + } + else { + break; + } + } + } + h /= 3; + } + } + template + void shuffle(Tvector& object) noexcept { + if (object._size < 2 || object._data == nullptr || object._states == nullptr) { + return; + } + std::random_device rd; + std::mt19937 gen(rd()); + for (size_t i = object._size - 1; i > 0; --i) { + std::uniform_int_distribution dist(0, i); + size_t j = dist(gen); + std::swap(object._data[i], object._data[j]); + std::swap(object._states[i], object._states[j]); + } + } + template + size_t find_first_element(const Tvector& object, const U& value) { + size_t result = 0; + for (size_t i = 0; i < object._size; i++) { + if (object._states[i] == object.State::deleted) { + continue; + } + else if (object._data[i] == value && object._states[i] == object.State::busy) { + return result + 1; + } + result++; + } + return 0; + } + template + size_t find_last_element(const Tvector& object, const U& value) { + size_t last_pos = 0; + size_t current_pos = 0; + for (size_t i = 0; i < object._size; i++) { + if (object._states[i] == object.State::deleted) { + continue; + } + current_pos++; + if (object._data[i] == value && object._states[i] == object.State::busy) { + last_pos = current_pos; + } + } + return last_pos; + } + template + size_t find_count_of_all_suitable_elements(const Tvector& object, const U& value) { + size_t count = 0; + for (size_t i = 0; i < object._size; ++i) { + if (object._data[i] == value && object._states[i] == object.State::busy) { + count++; + } + } + return count; + } diff --git a/main/main.cpp b/main/main.cpp index 217f8971..50e3f9ce 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1,37 +1,643 @@ -// Copyright 2024 Marina Usova +// Copyright 2025 Julia Zabytia +//#define EASY_EXAMPLE +//#define CIRCLES_AND_SPHERES -#define EASY_EXAMPLE -#ifdef EASY_EXAMPLE +//#define CALCULATOR +#define DSU_LABIRINT +#ifdef EASY_EXAMPLE #include #include #include "../lib_easy_example/easy_example.h" int main() { - int a, b; - float result; + int a, b; + float result; + + a = 1; b = 4; + + try { + result = division(a, b); + std::cout << a << " / " << b << " = " + << std::setprecision(2) << result << std::endl; + } + catch (std::exception err) { + std::cerr << err.what() << std::endl; + } + + a = 1; b = 0; + + try { + result = division(a, b); + std::cout << a << " / " << b << " = " + << std::setprecision(2) << result << std::endl; + } + catch (std::exception err) { + std::cerr << err.what() << std::endl; + } + + return 0; +} + +#endif +#ifdef CIRCLES_AND_SPHERES +#include +#include +#include "../lib_sphere/sphere.h" +#include "../lib_circle/circle.h" +#include "../lib_point/point.h" +#include "../lib_point3d/point3d.h" +enum result_of_compare +{ + Equal, + Intersecting, + NotIntersecting, + FirstTouchSecond, + OneInsideOther, + OneInsideOtherTouching +}; +result_of_compare Compare(int d, int r1, int r2, int sum, int diff) { + if (d == 0 && r1 == r2) { + return Equal; + } + if (d > sum) { + return NotIntersecting; + } + if (d == sum) { + return FirstTouchSecond; + } + if (d > diff && d < sum) { + return Intersecting; + } + if (d == diff && d > 0) { + return OneInsideOtherTouching; + } + if (d < diff) { + return OneInsideOther; + } + return result_of_compare::NotIntersecting; +} +result_of_compare CompareCircles(const Circle& circle1, const Circle& circle2) { + int d = circle1.getDistanceTo(circle2); + int r1 = circle1.getR(); + int r2 = circle2.getR(); + int sum = r1 + r2; + int diff = std::abs(r1 - r2); + return Compare(d, r1, r2, sum, diff); +} +result_of_compare CompareSpheres(const Sphere& sphere1, const Sphere& sphere2) { + int d = sphere1.getDistanceTo(sphere2); + int r1 = sphere1.getR(); + int r2 = sphere2.getR(); + int sum = r1 + r2; + int diff = std::abs(r1 - r2); + return Compare(d, r1, r2, sum, diff); +} +int main() { + + Point center1(0, 0); + Circle circle1(center1, 5); + Point center2(6, 0); + Circle circle2(center2, 4); + result_of_compare circle_result = CompareCircles(circle1, circle2); + + switch (circle_result) { + case Equal: + std::cout << "Circles is equal\n"; + break; + case Intersecting: + std::cout << "Circles is intersecting\n"; + break; + case NotIntersecting: + std::cout << "Circles is not intersecting\n"; + break; + case FirstTouchSecond: + std::cout << "First circle touch second circle\n"; + break; + case OneInsideOther: + std::cout << "One circle inside other circle\n"; + break; + case OneInsideOtherTouching: + std::cout << "One circle inside other circle (with touching)\n"; + break; + default: + std::cout << "Unknown result\n"; + break; + } + return 0; +} +#endif +#ifdef MATRIX +#include +#include "../lib_math_vector/math_vector.h" +#include "../lib_matrix/matrix.h" +#include "../lib_triangle_matrix/triangle_matrix.h" + +void printMainMenu() { + std::cout << "==========================================\n"; + std::cout << "| CALCULATOR FOR VARIOUS MATRICES |\n"; + std::cout << "| (REGULAR AND TRIANGULAR) |\n"; + std::cout << "==========================================\n"; + std::cout << "\n"; + std::cout << "MAIN MENU =====\n"; + std::cout << " 1. Matrix addition\n"; + std::cout << " 2. Matrix subtraction\n"; + std::cout << " 3. Matrix multiplication\n"; + std::cout << " 4. Add scalar to matrix\n"; + std::cout << " 5. Subtract scalar from matrix\n"; + std::cout << " 6. Multiply matrix by scalar\n"; + std::cout << " 7. Division by scalar\n"; + std::cout << " 8. Multiply matrix by vector\n"; + std::cout << " 9. Exit\n"; +} + +template +void fillMatrix(Matrix& matrix) { + for (size_t i = 0; i < matrix.getM(); ++i) { + for (size_t j = 0; j < matrix.getN(); ++j) { + T value; + std::cout << "Element [" << i << "][" << j << "]: "; + std::cin >> value; + matrix[i][j] = value; + } + } +} + +template +void fillTriangleMatrix(TriangleMatrix& matrix) { + for (size_t i = 0; i < matrix.getSize(); ++i) { + for (size_t j = i; j < matrix.getSize(); ++j) { + T value; + std::cout << "Element [" << i << "][" << j << "]: "; + std::cin >> value; + matrix[i][j] = value; + } + } +} + +template +void fillVector(MathVector& vector) { + for (size_t i = 0; i < vector.get_size(); ++i) { + T value; + std::cout << "Element [" << i << "]: "; + std::cin >> value; + vector[i] = value; + } +} + +int main() { + setlocale(LC_ALL, "Russian"); + int user_choice; + + do { + printMainMenu(); + std::cout << "Your choice: "; + std::cin >> user_choice; + + if (user_choice == 9) { + break; + } - a = 1; b = 4; + int matrix_type; + std::cout << "Choose matrix type:\n"; + std::cout << "1. Regular matrix\n"; + std::cout << "2. Triangular matrix\n"; + std::cin >> matrix_type; - try { - result = division(a, b); - std::cout << a << " / " << b << " = " - << std::setprecision(2) << result << std::endl; - } catch (std::exception err) { - std::cerr << err.what() << std::endl; - } + if (matrix_type == 1) { + // Regular Matrix operations + size_t M, N; + std::cout << "Enter dimensions of matrix 1 (M - rows, N - columns)\n"; + std::cout << "M = "; + std::cin >> M; + std::cout << "N = "; + std::cin >> N; - a = 1; b = 0; + Matrix matrix1(M, N); + std::cout << "Enter elements of matrix 1:\n"; + fillMatrix(matrix1); + + switch (user_choice) { + case 1: { + std::cout << "Enter dimensions of matrix 2 (must be " << M << " x " << N << ")\n"; + Matrix matrix2(M, N); + std::cout << "Enter elements of matrix 2:\n"; + fillMatrix(matrix2); + Matrix result = matrix1 + matrix2; + std::cout << "Result:\n" << result; + break; + } + case 2: { + std::cout << "Enter dimensions of matrix 2 (must be " << M << " x " << N << ")\n"; + Matrix matrix2(M, N); + std::cout << "Enter elements of matrix 2:\n"; + fillMatrix(matrix2); + Matrix result = matrix1 - matrix2; + std::cout << "Result:\n" << result; + break; + } + case 3: { + size_t K; + std::cout << "Enter number of columns for matrix 2 (must be " << N << " rows)\n"; + std::cout << "K = "; + std::cin >> K; + Matrix matrix2(N, K); + std::cout << "Enter elements of matrix 2:\n"; + fillMatrix(matrix2); + Matrix result = matrix1 * matrix2; + std::cout << "Result:\n" << result; + break; + } + case 4: { + int scalar; + std::cout << "Enter scalar: "; + std::cin >> scalar; + Matrix result = matrix1 + scalar; + std::cout << "Result:\n" << result; + break; + } + case 5: { + int scalar; + std::cout << "Enter scalar: "; + std::cin >> scalar; + Matrix result = matrix1 - scalar; + std::cout << "Result:\n" << result; + break; + } + case 6: { + int scalar; + std::cout << "Enter scalar: "; + std::cin >> scalar; + Matrix result = matrix1 * scalar; + std::cout << "Result:\n" << result; + break; + } + case 7: { + int scalar; + std::cout << "Enter scalar: "; + std::cin >> scalar; + try { + Matrix result = matrix1 / scalar; + std::cout << "Result:\n" << result; + } + catch (const std::exception& e) { + std::cout << "Error: " << e.what() << std::endl; + } + break; + } + case 8: { + size_t size; + std::cout << "Enter vector size (must be " << N << "): "; + std::cin >> size; + if (size != N) { + std::cout << "Error: Vector size must match matrix columns!\n"; + break; + } + MathVector mathvector(size); + std::cout << "Enter vector elements:\n"; + fillVector(mathvector); + try { + MathVector result = matrix1 * mathvector; + std::cout << "Result:\n" << result; + } + catch (const std::exception& e) { + std::cout << "Error: " << e.what() << std::endl; + } + break; + } + default: { + std::cout << "Invalid input! Please try again\n"; + break; + } + } + } + else if (matrix_type == 2) { + // Triangular Matrix operations + size_t size; + std::cout << "Enter size of triangular matrix: "; + std::cin >> size; + + TriangleMatrix matrix1(size); + std::cout << "Enter elements of triangular matrix (only upper triangle):\n"; + fillTriangleMatrix(matrix1); + + switch (user_choice) { + case 1: { + TriangleMatrix matrix2(size); + std::cout << "Enter elements of second triangular matrix:\n"; + fillTriangleMatrix(matrix2); + try { + TriangleMatrix result = matrix1 + matrix2; + std::cout << "Result:\n" << result; + } + catch (const std::exception& e) { + std::cout << "Error: " << e.what() << std::endl; + } + break; + } + case 2: { + TriangleMatrix matrix2(size); + std::cout << "Enter elements of second triangular matrix:\n"; + fillTriangleMatrix(matrix2); + try { + TriangleMatrix result = matrix1 - matrix2; + std::cout << "Result:\n" << result; + } + catch (const std::exception& e) { + std::cout << "Error: " << e.what() << std::endl; + } + break; + } + case 3: { + std::cout << "Matrix multiplication for triangular matrices not implemented in this example\n"; + break; + } + case 4: { + int scalar; + std::cout << "Enter scalar: "; + std::cin >> scalar; + TriangleMatrix result = matrix1 + scalar; + std::cout << "Result:\n" << result; + break; + } + case 5: { + int scalar; + std::cout << "Enter scalar: "; + std::cin >> scalar; + TriangleMatrix result = matrix1 - scalar; + std::cout << "Result:\n" << result; + break; + } + case 6: { + int scalar; + std::cout << "Enter scalar: "; + std::cin >> scalar; + TriangleMatrix result = matrix1 * scalar; + std::cout << "Result:\n" << result; + break; + } + case 7: { + int scalar; + std::cout << "Enter scalar: "; + std::cin >> scalar; + try { + TriangleMatrix result = matrix1 / scalar; + std::cout << "Result:\n" << result; + } + catch (const std::exception& e) { + std::cout << "Error: " << e.what() << std::endl; + } + break; + } + case 8: { + MathVector mathvector(size); + std::cout << "Enter vector elements:\n"; + fillVector(mathvector); + try { + MathVector result = matrix1 * mathvector; + std::cout << "Result:\n" << result; + } + catch (const std::exception& e) { + std::cout << "Error: " << e.what() << std::endl; + } + break; + } + default: { + std::cout << "Invalid input! Please try again\n"; + break; + } + } + } + std::cout << "\nPress Enter to continue..."; + std::cin.ignore(); + std::cin.get(); + system("cls"); + + } while (true); + return 0; +} +#endif +#ifdef CALCULATOR +#include "../lib_calculator_app/expression.h" +#include "../lib_vector/vector.h" +#include +#include +#include +#include +void print_table_header() { + std::cout << "+" << std::string(80, '-') << "+" << std::endl; + std::cout << "| " << std::left << std::setw(4) << "ID" + << "| " << std::setw(40) << "" + << "| " << std::setw(30) << " " + << " |" << std::endl; + std::cout << "+" << std::string(80, '-') << "+" << std::endl; +} +void show_all_expressions(Tvector& expressions) { + if (expressions.get_size() == 0) { + std::cout << "| " << std::setw(78) << " " << " |" << std::endl; + } + else { + for (size_t i = 0; i < expressions.get_size(); ++i) { + std::cout << "| " << std::setw(4) << expressions[i].get_id() + << "| " << std::setw(40) << expressions[i].get_expression() + << "| "; + std::vector vars; + for (auto& pair : expressions[i].variables_map()) { + std::stringstream ss; + ss << std::fixed << std::setprecision(3) << pair.second; + vars.push_back(pair.first + "=" + ss.str()); + } + if (vars.empty()) { + std::cout << std::setw(30) << " "; + } + else { + std::string vars_str; + for (size_t j = 0; j < vars.size(); ++j) { + if (j > 0) vars_str += ", "; + vars_str += vars[j]; + } + std::cout << std::setw(30) << vars_str.substr(0, 30); + } + std::cout << " |" << std::endl; + } + } + std::cout << "+" << std::string(80, '-') << "+" << std::endl; +} +void create_new_expression(Tvector& expressions, int& next_id) { + system("cls"); + std::cout << " : "; + std::cin.ignore(std::numeric_limits::max(), '\n'); + std::string str; + std::getline(std::cin, str); + if (str.empty()) { + std::cout << ": !\n"; + system("pause"); + return; + } + try { + Expression new_expression(next_id, str); + expressions.push_back(new_expression); + next_id++; - try { - result = division(a, b); - std::cout << a << " / " << b << " = " - << std::setprecision(2) << result << std::endl; - } catch (std::exception err) { - std::cerr << err.what() << std::endl; - } + std::cout << " !\n"; + system("pause"); + } + catch (const std::exception& ex) { + std::cout << " : " << ex.what() << "\n"; + system("pause"); + } +} +void delete_expression(Tvector& expressions) { + system("cls"); + if (expressions.get_size() == 0) { + std::cout << " .\n"; + system("pause"); + return; + } + std::cout << " :\n"; + for (size_t i = 0; i < expressions.get_size(); ++i) { + std::cout << i + 1 << ". ID: " << expressions[i].get_id() + << " - " << expressions[i].get_expression() << "\n"; + } + std::cout << "\n \n"; + size_t choice; + std::cin >> choice; + if (choice < 1 || choice > expressions.get_size()) { + std::cout << " \n"; + system("pause"); + return; + } + try { + expressions.erase(choice-1); + std::cout << " \n"; + system("pause"); + } + catch (const std::exception& ex) { + std::cout << ": " << ex.what() << "\n"; + system("pause"); + } +} +void set_variables_for_expression(Tvector& expressions) { + system("cls"); + if (expressions.get_size() == 0) { + std::cout << " .\n"; + system("pause"); + return; + } + std::cout << " :\n"; + print_table_header(); + show_all_expressions(expressions); + std::cout << "\n ID : "; + int id; + std::cin >> id; + if (id < 1 || id > static_cast(expressions.get_size())) { + std::cout << " ID\n"; + system("pause"); + return; + } + try { + expressions[id - 1].set_variables(); + std::cout << " \n"; + system("pause"); + } + catch (const std::exception& ex) { + std::cout << ": " << ex.what() << "\n"; + system("pause"); + } +} +void calculate_expression(Tvector& expressions) { + system("cls"); + if (expressions.get_size() == 0) { + std::cout << " \n"; + system("pause"); + return; + } + std::cout << " :\n"; + print_table_header(); + show_all_expressions(expressions); + std::cout << "\n ID : "; + int id; + std::cin >> id; + if (id < 1 || id > static_cast(expressions.get_size())) { + std::cout << " ID\n"; + system("pause"); + return; + } + try { + double result = expressions[id - 1].calculate(); + std::cout << "\n : " << result << "\n"; + system("pause"); + } + catch (const std::exception& ex) { + std::cout << " : " << ex.what() << "\n"; + system("pause"); + } +} +int main() { + setlocale(LC_ALL, "Russian"); + Tvector expressions; + int next_id = 1; + while (true) { + system("cls"); + std::cout << "\n" << std::string(50, '=') << std::endl; + std::cout << " " << std::endl; + std::cout << std::string(50, '=') << std::endl; + print_table_header(); + show_all_expressions(expressions); + std::cout << "\n:" << std::endl; + std::cout << "1. " << std::endl; + std::cout << "2. " << std::endl; + std::cout << "3. " << std::endl; + std::cout << "4. " << std::endl; + std::cout << "5. " << std::endl; + std::cout << std::string(50, '-') << std::endl; + std::cout << " : "; + int choice; + bool want_exit = false; + std::cin >> choice; + switch (choice) { + case 1: + create_new_expression(expressions, next_id); + break; + case 2: + delete_expression(expressions); + break; + case 3: + set_variables_for_expression(expressions); + break; + case 4: + calculate_expression(expressions); + break; + case 5: + want_exit = true; + break; + default: + std::cout << "\n . ." << std::endl; + std::cout << "\n Enter ..."; + std::cin.ignore(); + std::cin.get(); + break; + } - return 0; + if (want_exit) { + break; + } + } + return 0; } +#endif +#ifdef DSU_LABIRINT +#include "../lib_dsu/dsu.h" +#include "../lib_algoritm/algoritm.h" +int main() { + int n = 5, m = 10; + int x = 1; + int y = n * m - 1; -#endif // EASY_EXAMPLE + DSU dsu = generate(x, y, n, m); + print_labirint(dsu, n, m); + + return 0; + +} +#endif \ No newline at end of file diff --git a/tests/test_algoritm.cpp b/tests/test_algoritm.cpp new file mode 100644 index 00000000..6356cb3a --- /dev/null +++ b/tests/test_algoritm.cpp @@ -0,0 +1,322 @@ +#include "../lib_algoritm/algoritm.h" +#include +#include +TEST(TestAlgoritmLib, test_for_one_local_min) { + int data[9] = { 1, 20, 30, + 40, 50, 60 , + 70, 80, 90 }; + Matrix matrix(data, 3, 3); + int result = find_local_minimum(matrix); + EXPECT_EQ(result, 1); +} +TEST(TestAlgoritmLib, test_for_many_local_min) { + int data[9] = { 1, 4, 3, + 8, 10, 6 , + 7, 9, 2 }; + Matrix matrix(data, 3, 3); + int result = find_local_minimum(matrix); + EXPECT_TRUE(result == 1 || result == 3 || result == 7 || result == 2); +} +TEST(TestAlgoritmLib, test_top_left_corner_minimum) { + int data[9] = { 1, 3, 4, + 2, 5, 6, + 7, 8, 9 }; + Matrix matrix(data, 3, 3); + int result = find_local_minimum(matrix); + + EXPECT_TRUE(result == 1); +} +TEST(TestAlgoritmLib, test_bottom_right_corner_minimum) { + int data[9] = { 9, 8, 7, + 6, 5, 4, + 3, 2, 1 }; + Matrix matrix(data, 3, 3); + int result = find_local_minimum(matrix); + EXPECT_EQ(result, 1); +} +TEST(TestAlgoritmLib, test_center_minimum) { + int data[9] = { 9, 8, 7, + 6, 1, 5, + 4, 2, 3 }; + Matrix matrix(data, 3, 3); + int result = find_local_minimum(matrix); + EXPECT_EQ(result, 1); +} +TEST(TestAlgoritmLib, test_single_element) { + int data[1] = { 5 }; + Matrix matrix(data, 1, 1); + int result = find_local_minimum(matrix); + EXPECT_EQ(result, 5); +} +TEST(TestAlgoritmLib, test_2x2_matrix) { + int data[4] = { 4, 3, + 1, 2 }; + Matrix matrix(data, 2, 2); + int result = find_local_minimum(matrix); + EXPECT_TRUE(result == 3 || result == 1); +} +TEST(TestAlgoritmLib, test_5x5_matrix) { + int data[25] = { 10, 11, 12, 13, 14, + 15, 16, 1, 17, 18, + 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33 }; + Matrix matrix(data, 5, 5); + int result = find_local_minimum(matrix); + EXPECT_TRUE(result == 1 || result == 10 || result == 14 || result == 19 + || result == 23 || result == 29 || result == 33); +} +TEST(TestAlgorithmLib, test_check_brackets_false1) { + std::string string = ")"; + EXPECT_EQ(check_brackets(string), false); + +} +TEST(TestAlgorithmLib, test_check_brackets_false2) { + std::string string = "["; + EXPECT_EQ(check_brackets(string), false); +} +TEST(TestAlgorithmLib, test_check_brackets_false3) { + std::string string = "())"; + EXPECT_EQ(check_brackets(string), false); +} +TEST(TestAlgorithmLib, test_check_brackets_false4) { + std::string string = "({)"; + EXPECT_EQ(check_brackets(string), false); +} +TEST(TestAlgorithmLib, test_check_brackets_false5) { + std::string string = "({})]"; + EXPECT_EQ(check_brackets(string), false); +} +TEST(TestAlgorithmLib, test_check_brackets_true1) { + std::string string = "()"; + EXPECT_EQ(check_brackets(string), true); +} +TEST(TestAlgorithmLib, test_check_brackets_true2) { + std::string string = "{}"; + EXPECT_EQ(check_brackets(string), true); +} +TEST(TestAlgorithmLib, test_check_brackets_true3) { + std::string string = "[()]"; + EXPECT_EQ(check_brackets(string), true); +} +TEST(TestAlgorithmLib, test_check_brackets_true4) { + std::string string = "{[()]}"; + EXPECT_EQ(check_brackets(string), true); +} +TEST(TestAlgorithmLib, test_check_brackets_true5) { + std::string string = "()[]{}"; + EXPECT_EQ(check_brackets(string), true); +} +TEST(TestAlgorithmLib, test_check_brackets_true6) { + std::string string = ""; + EXPECT_EQ(check_brackets(string), true); +} + +TEST(TestAlgorithmLib, test_read_expression_empty_brackets) { + std::string expression = "a + b - ()"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_read_expression_operator_in_wrong_position1) { + std::string expression = "a + * b"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_read_expression_operator_in_wrong_position2) { + std::string expression = "(* a)"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_read_expression_operands_without_operator1) { + std::string expression = "(a b)"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_read_expression_operands_without_operator2) { + std::string expression = "a b"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_read_expression_operands_without_operator3) { + std::string expression = "a + b c"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_read_expression_invalid_character) { + std::string expression = "(a@b)"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} + + +TEST(TestAlgorithmLib, test_read_expression_unbalanced_brackets) { + std::string expression = "(a-b)*c + (d + f)))"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_read_expression_missing_operand_at_the_end) { + std::string expression = "a + b - "; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_read_expression_no_operands_in_expression) { + std::string expression = "+ -"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_read_expression_no_operand_before_opening_bracket) { + std::string expression = "a ( a + b)"; + EXPECT_THROW(read_expression(expression), std::invalid_argument); +} +TEST(TestAlgorithmLib, test_find_loop_in_list_1_false) { + // Arrange & Act + List list; + list.push_back(90); + list.push_back(30); + list.push_back(100); + // Assert + EXPECT_FALSE(is_looped1(list)); +} +TEST(TestAlgorithmLib, test_find_loop_in_list_1_true) { + // Arrange & Act + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + list.push_back(30); + list.get_tail()->next = list.get_head(); + // Assert + EXPECT_TRUE(is_looped1(list)); + list.get_tail()->next = nullptr; +} +TEST(TestAlgorithmLib, test_find_loop_in_list_1_with_empty_list) { + // Arrange & Act + List list; + // Assert + EXPECT_FALSE(is_looped1(list)); +} + +TEST(TestAlgorithmLib, test_find_loop_in_list_2_false) { + // Arrange & Act + List list; + list.push_back(8); + list.push_back(5); + list.push_back(100); + list.push_back(1); + // Assert + EXPECT_FALSE(is_looped2(list)); +} +TEST(TestAlgorithmLib, test_find_loop_in_list_2_true) { + // Arrange & Act + List list; + list.push_back(103); + list.push_back(2); + list.push_back(304); + list.push_back(70); + list.get_tail()->next = list.get_head(); + // Assert + EXPECT_TRUE(is_looped2(list)); + list.get_tail()->next = nullptr; +} + +TEST(TestAlgorithmLib, test_find_loop_in_list_2_with_empty_list) { + // Arrange & Act + List list; + // Assert + EXPECT_FALSE(is_looped2(list)); +} + +TEST(TestAlgorithmLib, test_find_loop_start_in_list) { + // Arrange & Act + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(50); + + list.push_back(70); + list.get_tail()->next = list.get_head(); + // Assert + EXPECT_EQ(find_loop_start(list), list.get_head()); + list.get_tail()->next = nullptr; +} +TEST(TestAlgorithmLib, test_find_loop_start_no_loop) { + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + + EXPECT_EQ(find_loop_start(list), nullptr); +} +TEST(TestAlgorithmLib, test_find_loop_start_in_middle) { + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + list.push_back(50); + + list.get_tail()->next = list.get_head()->next->next; + + EXPECT_EQ(find_loop_start(list), list.get_head()->next->next); + + list.get_tail()->next = nullptr; +} +TEST(TestAlgorithmLib, test_dsu_find_count_of_islands1) { + // Arrange & Act + int data[] = { 1, 1, + 0, 0 }; + Matrix matrix(data, 2, 2); + // Assert + EXPECT_EQ(1, get_count_of_islands(matrix)); +} +TEST(TestAlgorithmLib, test_dsu_find_count_of_islands2_empty_matrix) { + // Arrange & Act + Matrix matrix(10, 10); + // Assert + EXPECT_EQ(0, get_count_of_islands(matrix)); +} +TEST(TestAlgorithmLib, test_dsu_find_count_of_islands3) { + // Arrange & Act + int data[] = {1, 1, + 0, 1, + 1, 1, + 0, 1}; + Matrix matrix(data, 4, 2); + // Assert + EXPECT_EQ(1, get_count_of_islands(matrix)); +} +TEST(TestAlgorithmLib, test_dsu_find_count_of_islands5) { + // Arrange & Act + int data[] = { 0,0, + 0, 0, + 0, 0, + 0, 0}; + Matrix matrix(data, 4, 2); + // Assert + EXPECT_EQ(0, get_count_of_islands(matrix)); +} +TEST(TestAlgorithmLib, test_dsu_find_count_of_islands6_large_matrix) { + // Arrange & Act + int data[] = { + 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0 + }; + + Matrix matrix(data, 10, 10); + + // Assert + EXPECT_EQ(6, get_count_of_islands(matrix)); +} +TEST(TestAlgorithmLib, test_dsu_find_count_of_islands7_diagonal) { + // Arrange & Act + int data[] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + }; + Matrix matrix(data, 4, 4); + + // Assert + EXPECT_EQ(1, get_count_of_islands(matrix)); +} diff --git a/tests/test_calculator_app.cpp b/tests/test_calculator_app.cpp new file mode 100644 index 00000000..ad80333d --- /dev/null +++ b/tests/test_calculator_app.cpp @@ -0,0 +1,296 @@ +// Copyright 2025 Julia Zabytina +#include +#include +#include "../lib_calculator_app/expression.h" + +TEST(TestCalculatorAppLib, parse_expression_empty) { + // Arrange & Act + std::string expression = ""; + // Assert + ASSERT_THROW(Parser::parse(expression), std::logic_error); +} +TEST(TestCalculatorAppLib, parse_expression_invalid_number_format) { + // Arrange & Act + std::string expression = "a+b-2...33"; + // Assert + ASSERT_THROW(Parser::parse(expression), std::logic_error); +} +TEST(TestCalculatorAppLib, parse_expression_invalid_variable_format) { + // Arrange & Act + std::string expression = "(a+b)*9d-10"; + // Assert + ASSERT_THROW(Parser::parse(expression), std::logic_error); +} +TEST(TestCalculatorAppLib, parse_expression_invalid_funcion_format) { + // Arrange & Act + std::string expression = "a+b-cos("; + // Assert + ASSERT_THROW(Parser::parse(expression), std::logic_error); +} +TEST(TestCalculatorAppLib, parse_expression_end_with_operator) { + // Arrange & Act + std::string expression = "c/d-a*(s-h)+"; + // Assert + ASSERT_THROW(Parser::parse(expression), std::logic_error); +} +TEST(TestCalculatorAppLib, parse_expression_with_unkown_symbol) { + // Arrange & Act + std::string expression = "c/d-a*$"; + // Assert + ASSERT_THROW(Parser::parse(expression), std::logic_error); +} +TEST(TestCalculatorAppLib, parse_expression_mismatched_brackets) { + std::string expression = "(a+b"; + ASSERT_THROW(Parser::parse(expression), std::logic_error); +} +TEST(TestCalculatorAppLib, parse_correct_expression1) { + std::string expression = "a+b*2"; + ASSERT_NO_THROW(Parser::parse(expression)); +} +TEST(TestCalculatorAppLib, parse_correct_expression2) { + std::string expression = "-a+b*2-(c-d)"; + ASSERT_NO_THROW(Parser::parse(expression)); +} +TEST(TestCalculatorAppLib, parse_correct_expression3_with_functions) { + std::string expression = "sin(x)+cos(y)"; + ASSERT_NO_THROW(Parser::parse(expression)); +} +TEST(TestCalculatorAppLib, parse_correct_expression4_with_abs) { + std::string expression = "|a-b|+c"; + ASSERT_NO_THROW(Parser::parse(expression)); +} +TEST(TestCalculatorAppLib, parse_correct_expression5_complex) { + std::string expression = "a+b*(c-d)/e^2"; + ASSERT_NO_THROW(Parser::parse(expression)); +} +TEST(TestCalculatorAppLib, calculate_simple_expression) { + // Arrange + std::string expr_str = "2+3"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), 5.0); +} +TEST(TestCalculatorAppLib, calculate_with_variables) { + // Arrange + std::string expr_str = "a+b"; + Expression expr(1, expr_str); + expr.set_variable("a", 2.5); + expr.set_variable("b", 3.5); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), 6.0); +} +TEST(TestCalculatorAppLib, calculate_with_operations) { + // Arrange + std::string expr_str = "2+3*4"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), 14.0); +} +TEST(TestCalculatorAppLib, calculate_with_brackets) { + // Arrange + std::string expr_str = "(2+3)*4"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), 20.0); +} +TEST(TestCalculatorAppLib, calculate_with_division) { + // Arrange + std::string expr_str = "10/2"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), 5.0); +} +TEST(TestCalculatorAppLib, calculate_with_power) { + // Arrange + std::string expr_str = "2^3"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), 8.0); +} +TEST(TestCalculatorAppLib, calculate_with_function) { + // Arrange + std::string expr_str = "sin(0)"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), 0.0); +} +TEST(TestCalculatorAppLib, calculate_with_abs) { + // Arrange + std::string expr_str = "|-5|"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), 5.0); +} +TEST(TestCalculatorAppLib, calculate_complex_expression) { + // Arrange + std::string expr_str = "2+3*sin(0)-|-5|/5"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + // 2 + 3*0 - 5/5 = 2 - 1 = 1 + ASSERT_DOUBLE_EQ(expr.calculate(), 1.0); +} +TEST(TestCalculatorAppLib, calculate_division_by_zero) { + // Arrange + std::string expr_str = "1/0"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_THROW(expr.calculate(), std::logic_error); +} +TEST(TestCalculatorAppLib, calculate_missing_variable) { + // Arrange + std::string expr_str = "a+5"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_THROW(expr.calculate(), std::logic_error); +} +TEST(TestCalculatorAppLib, calculate_with_unary_minus1) { + // Arrange + std::string expr_str = "3+(-5)"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), -2.0); +} +TEST(TestCalculatorAppLib, calculate_with_unary_minus2) { + // Arrange + std::string expr_str = "-5+3"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), -2.0); +} +TEST(TestCalculatorAppLib, calculate_with_nested_functions) { + // Arrange + std::string expr_str = "sin(cos(0))"; + Expression expr(1, expr_str); + + // Act & Assert + ASSERT_NO_THROW(expr.calculate()); + ASSERT_NEAR(expr.calculate(), 0.8414709848, 1e-9); +} +TEST(TestCalculatorAppLib, expression_getters) { + // Arrange + std::string expr_str = "a+b"; + Expression expr(42, expr_str); + expr.set_variable("a", 2.0); + expr.set_variable("b", 3.0); + + // Act & Assert + ASSERT_EQ(expr.get_id(), 42); + ASSERT_EQ(expr.get_expression(), "a+b"); + ASSERT_DOUBLE_EQ(expr.calculate(), 5.0); +} +TEST(TestCalculatorAppLib, expression_variables_map) { + // Arrange + std::string expr_str = "x+y"; + Expression expr(1, expr_str); + expr.set_variable("x", 10.0); + expr.set_variable("y", 20.0); + // Act + auto vars = expr.variables_map(); + // Assert + ASSERT_EQ(vars.size(), 2); + ASSERT_DOUBLE_EQ(vars["x"], 10.0); + ASSERT_DOUBLE_EQ(vars["y"], 20.0); +} +TEST(TestCalculatorAppLib, expression_build_polish_notation_simple_addition) { + // Arrange + std::string expr_str = "a+b"; + Expression expr(1, expr_str); + // Act & Assert + ASSERT_NO_THROW(Expression expr(1, expr_str)); +} +TEST(TestCalculatorAppLib, expression_build_polish_notation_operator_priority) { + // Arrange & Act + Expression expr(1, "a+b*c"); + // Assert + expr.set_variable("a", 1.0); + expr.set_variable("b", 2.0); + expr.set_variable("c", 3.0); + ASSERT_NO_THROW(expr.calculate()); + ASSERT_DOUBLE_EQ(expr.calculate(), 7.0); +} +TEST(TestCalculatorAppLib, expression_build_polish_notation_with_parentheses) { + // Arrange & Act + Expression expr(1, "(a+b)*c"); + // Assert + expr.set_variable("a", 1.0); + expr.set_variable("b", 2.0); + expr.set_variable("c", 3.0); + ASSERT_DOUBLE_EQ(expr.calculate(), 9.0); +} +TEST(TestCalculatorAppLib, expression_build_polish_notation_complex) { + // Arrange & Act + Expression expr(1, "a+b*(c-d)/e"); + // Assert + expr.set_variable("a", 1.0); + expr.set_variable("b", 2.0); + expr.set_variable("c", 5.0); + expr.set_variable("d", 3.0); + expr.set_variable("e", 4.0); + ASSERT_DOUBLE_EQ(expr.calculate(), 2.0); +} +TEST(TestCalculatorAppLib, expression_build_polish_notation_power_operator) { + // Arrange & Act + Expression expr(1, "a^b*c"); + // Assert + expr.set_variable("a", 2.0); + expr.set_variable("b", 3.0); + expr.set_variable("c", 4.0); + ASSERT_DOUBLE_EQ(expr.calculate(), 32.0); +} +TEST(TestCalculatorAppLib, expression_build_polish_notation_with_functions) { + // Arrange & Act + Expression expr(1, "sin(a)+cos(b)"); + // Assert + expr.set_variable("a", 0.0); + expr.set_variable("b", 0.0); + ASSERT_DOUBLE_EQ(expr.calculate(), 1.0); +} +TEST(TestCalculatorAppLib, expression_build_polish_notation_nested_functions) { + // Arrange & Act + Expression expr(1, "sin(cos(a))"); + // Assert + expr.set_variable("a", 0.0); + ASSERT_NEAR(expr.calculate(), 0.8414709848, 1e-9); +} +TEST(TestCalculatorAppLib, expression_build_polish_notation_with_abs_bars) { + // Arrange & Act + Expression expr(1, "|a-b|+c"); + // Assert + expr.set_variable("a", 5.0); + expr.set_variable("b", 8.0); + expr.set_variable("c", 2.0); + // |5-8| + 2 = 3 + 2 = 5 + ASSERT_DOUBLE_EQ(expr.calculate(), 5.0); +} +TEST(TestCalculatorAppLib, expression_build_polish_notation_unary_minus) { + // Arrange & Act + Expression expr(1, "-a+b"); + // Assert + expr.set_variable("a", 5.0); + expr.set_variable("b", 3.0); + ASSERT_DOUBLE_EQ(expr.calculate(), -2.0); +} diff --git a/tests/test_doubly_linked_list.cpp b/tests/test_doubly_linked_list.cpp new file mode 100644 index 00000000..fcb98e41 --- /dev/null +++ b/tests/test_doubly_linked_list.cpp @@ -0,0 +1,787 @@ +#include +#include "../lib_doubly_linked_list/doubly_linked_list.h" +TEST(TestDoublyLinkedListLib, doubly_linked_list_default_constructor) { + // Arrange & Act + DoublyLinkedList list; + // Assert + EXPECT_EQ(list.get_head(), nullptr); + EXPECT_EQ(list.get_tail(), nullptr); + EXPECT_EQ(list.get_size(), 0); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_copy_constructor) { + // Arrange & Act + DoublyLinkedList list1; + list1.push_back(10); + list1.push_back(20); + DoublyLinkedList list2(list1); + // Assert + EXPECT_NE(list1.get_head(), list2.get_head()); + EXPECT_NE(list1.get_tail(), list2.get_tail()); + + EXPECT_EQ(list1.get_head()->value, list2.get_head()->value); + EXPECT_EQ(list1.get_tail()->value, list2.get_tail()->value); + EXPECT_EQ(list1.get_size(), list2.get_size()); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_is_empty_false) { + // Arrange & Act + DoublyLinkedList list; + list.push_back(10); + list.push_back(10); + // Assert + EXPECT_FALSE(list.is_empty()); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_is_empty_true) { + // Arrange & Act + DoublyLinkedList list; + // Assert + EXPECT_TRUE(list.is_empty()); +} +TEST(TestDoublyLinkedListLib, push_back_with_empty_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_back(19); + // Assert + EXPECT_EQ(list.get_size(), 1); + EXPECT_EQ(list.get_head(), list.get_tail()); +} +TEST(TestDoublyLinkedListLib, push_back_with_several_elements_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_back(300); + list.push_back(0); + list.push_back(500); + list.push_back(3); + list.push_back(5); + list.push_back(800); + list.push_back(2); + // Assert + EXPECT_EQ(list.get_tail()->value, 2); + EXPECT_EQ(list.get_size(), 7); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_operator_equal_true) { + // Arrange & Act + DoublyLinkedList list1; + DoublyLinkedList list2; + list1.push_back(20); + list1.push_back(20); + list1.push_back(20); + + list2.push_back(20); + list2.push_back(20); + list2.push_back(20); + // Assert + EXPECT_TRUE(list1 == list2); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_operator_equal_false) { + // Arrange & Act + DoublyLinkedList list1; + DoublyLinkedList list2; + list1.push_back(29); + list1.push_back(40); + list1.push_back(22); + list1.push_back(100); + + list2.push_back(30); + list2.push_back(88); + list2.push_back(66); + // Assert + EXPECT_FALSE(list1 == list2); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_operator_not_equal_true) { + // Arrange & Act + DoublyLinkedList list1; + DoublyLinkedList list2; + list1.push_back(70); + list1.push_back(80); + list1.push_back(90); + list1.push_back(700); + + list2.push_back(1); + list2.push_back(2); + list2.push_back(3); + // Assert + EXPECT_TRUE(list1 != list2); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_operator_not_equal_false) { + // Arrange & Act + DoublyLinkedList list1; + DoublyLinkedList list2; + list1.push_back(70); + list1.push_back(70); + list1.push_back(70); + + list2.push_back(70); + list2.push_back(70); + list2.push_back(70); + // Assert + EXPECT_FALSE(list1 != list2); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_operator_assign) { + // Arrange & Act + DoublyLinkedList list1; + DoublyLinkedList list2; + list1.push_back(30); + list1.push_back(800); + list1.push_back(70); + list1.push_back(600); + + list2.push_back(30); + list2.push_back(20); + list2.push_back(30); + list2 = list1; + // Assert + EXPECT_TRUE(list1 == list2); +} +TEST(TestDoublyLinkedListLib, push_front_with_empty_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_front(10); + // Assert + EXPECT_EQ(list.get_size(), 1); + EXPECT_EQ(list.get_head(), list.get_tail()); +} +TEST(TestDoublyLinkedListLib, push_front_with_several_elements_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_front(100); + list.push_front(550); + list.push_front(39); + list.push_front(400); + list.push_front(30); + // Assert + EXPECT_EQ(list.get_head()->value, 30); + EXPECT_EQ(list.get_size(), 5); +} +TEST(TestDoublyLinkedListLib, push_back_check_onnections_between_nodes_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + // Assert + EXPECT_EQ(list.get_head()->value, 10); + EXPECT_EQ(list.get_head()->next->value, 20); + EXPECT_EQ(list.get_head()->next->next->value, 30); + + EXPECT_EQ(list.get_tail()->value, 30); + EXPECT_EQ(list.get_tail()->previous->value, 20); + EXPECT_EQ(list.get_tail()->previous->previous->value, 10); +} +TEST(TestDoublyLinkedListLib, push_back_check_boundary_conditions_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + // Assert + EXPECT_EQ(list.get_head()->previous, nullptr); + EXPECT_EQ(list.get_tail()->next, nullptr); +} +TEST(TestDoublyLinkedListLib, push_front_check_onnections_between_nodes_doubly_linked_list) { + DoublyLinkedList list; + list.push_front(10); + list.push_front(20); + list.push_front(30); + + EXPECT_EQ(list.get_head()->value, 30); + EXPECT_EQ(list.get_head()->next->value, 20); + EXPECT_EQ(list.get_head()->next->next->value, 10); + + EXPECT_EQ(list.get_tail()->value, 10); + EXPECT_EQ(list.get_tail()->previous->value, 20); + EXPECT_EQ(list.get_tail()->previous->previous->value, 30); +} +TEST(TestDoublyLinkedListLib, push_front_check_boundary_conditions_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_front(10); + list.push_front(20); + list.push_front(30); + // Assert + EXPECT_EQ(list.get_head()->previous, nullptr); + EXPECT_EQ(list.get_tail()->next, nullptr); +} +TEST(TestDoublyLinkedListLib, pop_back_with_empty_doubly_linked_list_exception) { + // Arrange & Act + DoublyLinkedList list; + // Assert + ASSERT_THROW(list.pop_back(), std::logic_error); +} +TEST(TestDoublyLinkedListLib, pop_back_with_one_doubly_linked_list_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_back(30); + list.pop_back(); + // Assert + EXPECT_EQ(list.get_head(), nullptr); + EXPECT_EQ(list.get_tail(), nullptr); + EXPECT_EQ(list.get_size(), 0); +} +TEST(TestDoublyLinkedListLib, pop_back_with_several_elements_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_back(40); + list.push_back(44); + list.push_back(43); + list.push_back(1); + list.push_back(5); + list.pop_back(); + list.pop_back(); + // Assert + EXPECT_EQ(list.get_tail()->value, 43); + EXPECT_EQ(list.get_size(), 3); +} +TEST(TestDoublyLinkedListLib, pop_front_with_empty_doubly_linked_list_exception) { + // Arrange & Act + DoublyLinkedList list; + // Assert + ASSERT_THROW(list.pop_front(), std::logic_error); +} +TEST(TestDoublyLinkedListLib, pop_front_with_one_element_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_back(79); + list.pop_front(); + // Assert + EXPECT_EQ(list.get_head(), nullptr); + EXPECT_EQ(list.get_tail(), nullptr); + EXPECT_EQ(list.get_size(), 0); +} +TEST(TestDoublyLinkedListLib, pop_front_with_several_elements_doubly_linked_list) { + // Arrange & Act + DoublyLinkedList list; + list.push_back(1110); + list.push_back(20); + list.push_back(52); + list.push_back(4); + list.push_back(5220); + list.push_back(50); + list.push_back(50); + + list.pop_front(); + list.pop_front(); + list.pop_front(); + // Assert + EXPECT_EQ(list.get_head()->value, 4); + EXPECT_EQ(list.get_size(), 4); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_position_insert_in_end) { + // Arrange + DoublyLinkedList list; + list.push_back(320); + list.push_back(22); + list.push_back(1000); + list.push_back(42); + list.push_back(520); + size_t position = 4; + // Act + list.insert(position, 900); + // Assert + EXPECT_EQ(list.get_size(), 6); + EXPECT_EQ(list.get_head()->value, 320); + EXPECT_EQ(list.get_head()->next->value, 22); + EXPECT_EQ(list.get_head()->next->next->value, 1000); + EXPECT_EQ(list.get_head()->next->next->next->value, 42); + EXPECT_EQ(list.get_head()->next->next->next->next->value, 520); + EXPECT_EQ(list.get_head()->next->next->next->next->next->value, 900); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_position_insert) { + // Arrange + DoublyLinkedList list; + list.push_back(30); + list.push_back(4); + list.push_back(30); + list.push_back(2); + list.push_back(3); + size_t position = 2; + // Act + list.insert(position, 250); + // Assert + EXPECT_EQ(list.get_size(), 6); + EXPECT_EQ(list.get_head()->value, 30); + EXPECT_EQ(list.get_head()->next->value, 4); + EXPECT_EQ(list.get_head()->next->next->value, 250); + EXPECT_EQ(list.get_head()->next->next->next->value, 30); + EXPECT_EQ(list.get_head()->next->next->next->next->value, 2); + EXPECT_EQ(list.get_head()->next->next->next->next->next->value, 3); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_position_insert_with_exception) { + // Arrange + DoublyLinkedList list; + list.push_back(1); + list.push_back(50); + list.push_back(30); + list.push_back(40); + list.push_back(1); + size_t position = 10; + // Act & Assert + ASSERT_THROW(list.insert(position, 500), std::invalid_argument); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_node_insert) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(2); + list.push_back(30); + list.push_back(77); + list.push_back(50); + // Act + Node* node = list.get_head()->next; + list.insert(node, 700); + // Assert + EXPECT_EQ(list.get_size(), 6); + EXPECT_EQ(list.get_head()->value, 10); + EXPECT_EQ(list.get_head()->next->value, 2); + EXPECT_EQ(list.get_head()->next->next->value, 700); + EXPECT_EQ(list.get_head()->next->next->next->value, 30); + EXPECT_EQ(list.get_head()->next->next->next->next->value, 77); + EXPECT_EQ(list.get_head()->next->next->next->next->next->value, 50); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_node_insert_with_exception) { + // Arrange + DoublyLinkedList list; + Node* node = list.get_head(); + // Act & Assert + ASSERT_THROW(list.insert(node, 1), std::logic_error); +} + + +TEST(TestDoublyLinkedListLib, doubly_linked_list_position_erase_in_begin) { + // Arrange + DoublyLinkedList list; + list.push_back(3); + list.push_back(7); + list.push_back(830); + list.push_back(1); + list.push_back(20); + size_t position = 0; + // Act + list.erase(position); + // Assert + EXPECT_EQ(list.get_size(), 4); + EXPECT_EQ(list.get_head()->value, 7); + EXPECT_EQ(list.get_head()->next->value, 830); + EXPECT_EQ(list.get_head()->next->next->value, 1); + EXPECT_EQ(list.get_head()->next->next->next->value, 20); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_position_erase_in_end) { + // Arrange + DoublyLinkedList list; + list.push_back(60); + list.push_back(2); + list.push_back(80); + list.push_back(90); + list.push_back(20); + size_t position = 4; + // Act + list.erase(position); + // Assert + EXPECT_EQ(list.get_size(), 4); + EXPECT_EQ(list.get_head()->value, 60); + EXPECT_EQ(list.get_head()->next->value, 2); + EXPECT_EQ(list.get_head()->next->next->value, 80); + EXPECT_EQ(list.get_head()->next->next->next->value, 90); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_position_erase) { + // Arrange + DoublyLinkedList list; + list.push_back(320); + list.push_back(4); + list.push_back(0); + list.push_back(40); + list.push_back(570); + size_t position = 3; + // Act + list.erase(position); + // Assert + EXPECT_EQ(list.get_size(), 4); + EXPECT_EQ(list.get_head()->value, 320); + EXPECT_EQ(list.get_head()->next->value, 4); + EXPECT_EQ(list.get_head()->next->next->value, 0); + EXPECT_EQ(list.get_head()->next->next->next->value, 570); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_position_erase_with_exception1) { + // Arrange + DoublyLinkedList list; + size_t position = 100; + // Act & Assert + ASSERT_THROW(list.erase(position), std::invalid_argument); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_position_erase_with_exception2) { + // Arrange + DoublyLinkedList list; + list.push_back(32000); + list.push_back(8220); + list.push_back(320); + list.push_back(40); + list.push_back(50); + size_t position = 20; + // Act & Assert + ASSERT_THROW(list.erase(position), std::invalid_argument); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_node_erase) { + // Arrange + DoublyLinkedList list; + list.push_back(1); + list.push_back(840007); + list.push_back(3); + list.push_back(40); + list.push_back(55770); + Node* node = list.get_head()->next; + // Act + list.erase(node); + // Assert + EXPECT_EQ(list.get_size(), 4); + EXPECT_EQ(list.get_head()->value, 1); + EXPECT_EQ(list.get_head()->next->value, 3); + EXPECT_EQ(list.get_head()->next->next->value, 40); + EXPECT_EQ(list.get_head()->next->next->next->value, 55770); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_node_erase_with_exception) { + // Arrange + DoublyLinkedList list; + Node* node = list.get_head(); + // Act & Assert + ASSERT_THROW(list.erase(node), std::logic_error); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_read) { + // Arrange + DoublyLinkedList list; + list.push_back(1); + list.push_back(3); + list.push_back(17); + // Act + auto it = list.begin(); + it += 2; + // Assert + EXPECT_EQ(17, *it); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_write) { + // Arrange + DoublyLinkedList list; + list.push_back(50); + list.push_back(1); + list.push_back(79876); + list.push_back(12); + list.push_back(300); + // Act + auto it = list.begin(); + it += 3; + // Assert + EXPECT_EQ(12, *it); + *it = 900; + EXPECT_EQ(900, *it); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_empty_list) { + // Arrange + DoublyLinkedList list; + // Act & Assert + EXPECT_EQ(list.begin(), list.end()); + + auto it = list.begin(); + ++it; + EXPECT_EQ(it, list.end()); + + auto end_it = list.end(); + ++end_it; + EXPECT_EQ(end_it, list.end()); + + auto it2 = list.begin(); + it2 += 5; + EXPECT_EQ(it2, list.end()); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_prefix_increment) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + + // Act + auto it = list.begin(); + ++it; + + // Assert + EXPECT_EQ(20, *it); + ++it; + EXPECT_EQ(30, *it); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_postfix_increment) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + + // Act + auto it = list.begin(); + auto it_copy = it++; + + // Assert + EXPECT_EQ(10, *it_copy); + EXPECT_EQ(20, *it); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_prefix_decrement) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + // Act + auto it = list.end(); + + it = list.begin(); + ++it; + ++it; + + --it; + + // Assert + EXPECT_EQ(20, *it); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_postfix_decrement) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + + // Act + auto it = list.begin(); + ++it; + ++it; + + auto it_copy = it--; + + // Assert + EXPECT_EQ(30, *it_copy); + EXPECT_EQ(20, *it); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_compound_addition) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + list.push_back(50); + + // Act + auto it = list.begin(); + it += 3; + + // Assert + EXPECT_EQ(40, *it); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_compound_subtraction) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + list.push_back(50); + // Act + auto it = list.end(); + it = list.begin(); + it += 4; + + it -= 2; + + // Assert + EXPECT_EQ(30, *it); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_equality_operators) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + + // Act & Assert + auto it1 = list.begin(); + auto it2 = list.begin(); + EXPECT_TRUE(it1 == it2); + + ++it1; + EXPECT_FALSE(it1 == it2); + EXPECT_TRUE(it1 != it2); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_dereference_const) { + // Arrange + DoublyLinkedList list; + list.push_back(100); + list.push_back(200); + + // Act + const auto& const_list = list; + auto it = const_list.begin(); + + // Assert + EXPECT_EQ(100, *it); + ++it; + EXPECT_EQ(200, *it); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_range_based_for_loop) { + // Arrange + DoublyLinkedList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + list.push_back(4); + list.push_back(5); + + // Act + std::vector values; + for (const auto& value : list) { + values.push_back(value); + } + + // Assert + ASSERT_EQ(5, values.size()); + EXPECT_EQ(1, values[0]); + EXPECT_EQ(2, values[1]); + EXPECT_EQ(3, values[2]); + EXPECT_EQ(4, values[3]); + EXPECT_EQ(5, values[4]); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_range_based_for_loop_modify) { + // Arrange + DoublyLinkedList list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + for (auto& value : list) { + value += 10; + } + // Assert + auto it = list.begin(); + EXPECT_EQ(11, *it); + ++it; + EXPECT_EQ(12, *it); + ++it; + EXPECT_EQ(13, *it); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_manual_for_loop) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + + // Act + std::vector values; + for (auto it = list.begin(); it != list.end(); ++it) { + values.push_back(*it); + } + + // Assert + ASSERT_EQ(4, values.size()); + EXPECT_EQ(10, values[0]); + EXPECT_EQ(20, values[1]); + EXPECT_EQ(30, values[2]); + EXPECT_EQ(40, values[3]); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_manual_reverse_traversal) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + // Act + std::vector values; + + auto it = list.begin(); + ++it; + ++it; + values.push_back(*it); + --it; + values.push_back(*it); + --it; + values.push_back(*it); + + // Assert + ASSERT_EQ(3, values.size()); + EXPECT_EQ(30, values[0]); + EXPECT_EQ(20, values[1]); + EXPECT_EQ(10, values[2]); +} +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_copy_constructor) { + // Arrange + DoublyLinkedList list; + list.push_back(100); + list.push_back(200); + + // Act + auto it1 = list.begin(); + auto it2 = it1; + + // Assert + EXPECT_TRUE(it1 == it2); + EXPECT_EQ(100, *it1); + EXPECT_EQ(100, *it2); + + ++it1; + EXPECT_FALSE(it1 == it2); + EXPECT_EQ(200, *it1); + EXPECT_EQ(100, *it2); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_assignment_operator) { + // Arrange + DoublyLinkedList list; + list.push_back(100); + list.push_back(200); + list.push_back(300); + + // Act + auto it1 = list.begin(); + auto it2 = list.begin(); + ++it2; + ++it2; + + it1 = it2; + + // Assert + EXPECT_TRUE(it1 == it2); + EXPECT_EQ(300, *it1); + EXPECT_EQ(300, *it2); +} + +TEST(TestDoublyLinkedListLib, doubly_linked_list_iterator_bidirectional_traversal) { + // Arrange + DoublyLinkedList list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + + // Act + auto it = list.begin(); + ++it; + ++it; + --it; + + // Assert + EXPECT_EQ(20, *it); + + ++it; + ++it; + --it; + --it; + EXPECT_EQ(20, *it); +} diff --git a/tests/test_dsu.cpp b/tests/test_dsu.cpp new file mode 100644 index 00000000..d14114d6 --- /dev/null +++ b/tests/test_dsu.cpp @@ -0,0 +1,97 @@ +// Copyright 2025 Julia Zabytina +#include +#include "../lib_dsu/dsu.h" + +TEST(TestDSULib, dsu_constructor_with_size) { + // Arrange & Act + size_t size = 6; + DSU dsu(size); + // Assert + EXPECT_EQ(dsu.size(), size); + for (size_t i = 0; i < dsu.size(); i++) { + EXPECT_EQ(dsu.parent()[i], i); + EXPECT_EQ(dsu.rank()[i], 0); + } +} +TEST(TestDSULib, dsu_copy_constructor) { + // Arrange + size_t size = 10; + DSU dsu1(size); + // Act + DSU dsu2(dsu1); + // Assert + EXPECT_EQ(dsu1.size(), dsu2.size()); + for (size_t i = 0; i < dsu2.size(); i++) { + EXPECT_EQ(dsu1.parent()[i], dsu2.parent()[i]); + EXPECT_EQ(dsu1.rank()[i], dsu2.rank()[i]); + } +} +TEST(TestDSULib, dsu_union1) { + // Arran & Act + size_t size = 5; + DSU dsu(size); + dsu.dsu_union(1, 2); + dsu.dsu_union(4, 3); + EXPECT_EQ(dsu.dsu_find_recursive(1), dsu.dsu_find_recursive(2)); + EXPECT_EQ(dsu.dsu_find_recursive(4), dsu.dsu_find_recursive(3)); +} +TEST(TestDSULib, dsu_union2) { + DSU dsu(5); + dsu.dsu_union(0, 1); + dsu.dsu_union(1, 2); + EXPECT_EQ(dsu.dsu_find_recursive(0), dsu.dsu_find_recursive(2)); +} +TEST(TestDSULib, dsu_union_same_element) { + DSU dsu(3); + dsu.dsu_union(1, 1); + EXPECT_EQ(dsu.dsu_find_recursive(1), 1); +} +TEST(TestDSULib, dsu_union_with_exception) { + // Arrange & Act + size_t size = 5; + DSU dsu(size); + // Assert + ASSERT_THROW(dsu.dsu_union(-1, 2), std::logic_error); +} +TEST(TestDSULib, dsu_find_recursive) { + // Arrange & Act + size_t size = 7; + DSU dsu(size); + dsu.dsu_union(5, 4); + dsu.dsu_union(5, 6); + // Assert + EXPECT_EQ(dsu.dsu_find_recursive(6), 5); + EXPECT_EQ(dsu.dsu_find_recursive(4), 5); +} +TEST(TestDSULib, dsu_find_path_compression) { + // Arrange + DSU dsu(5); + for (int i = 0; i < 4; i++) { + dsu.dsu_union(i, i + 1); + } + // Act + int root = dsu.dsu_find_recursive(4); + // Assert + for (int i = 0; i < 5; i++) { + EXPECT_EQ(dsu.parent()[i], root); + } +} +TEST(TestDSULib, dsu_find_recursive_with_exception) { + // Arrange & Act + size_t size = 3; + DSU dsu(size); + // Assert + ASSERT_THROW(dsu.dsu_find_recursive(5), std::logic_error); +} +TEST(TestDSULib, dsu_operator_assign) { + // Arrange & Act + size_t size = 3; + DSU dsu1(size); + DSU dsu2 = dsu1; + // Assert + EXPECT_EQ(dsu1.size(), dsu2.size()); + for (size_t i = 0; i < size; i++) { + EXPECT_EQ(dsu1.parent()[i], dsu2.parent()[i]); + EXPECT_EQ(dsu1.rank()[i], dsu2.rank()[i]); + } +} diff --git a/tests/test_list.cpp b/tests/test_list.cpp new file mode 100644 index 00000000..8d76e0f2 --- /dev/null +++ b/tests/test_list.cpp @@ -0,0 +1,664 @@ +// Copyright 2025 Zabytina Julia + +#include +#include "../lib_list/List.h" +TEST(TestListLib, list_default_constructor) { + // Arrange & Act + List list; + // Assert + EXPECT_EQ(list.get_head(), nullptr); + EXPECT_EQ(list.get_tail(), nullptr); + EXPECT_EQ(list.get_size(), 0); +} +TEST(TestListLib, list_copy_constructor) { + // Arrange & Act + List list1; + list1.push_back(10); + list1.push_back(20); + List list2(list1); + // Assert + EXPECT_NE(list1.get_head(), list2.get_head()); + EXPECT_NE(list1.get_tail(), list2.get_tail()); + + EXPECT_EQ(list1.get_head()->value, list2.get_head()->value); + EXPECT_EQ(list1.get_tail()->value, list2.get_tail()->value); + EXPECT_EQ(list1.get_size(), list2.get_size()); +} +TEST(TestListLib, list_is_empty_false) { + // Arrange & Act + List list; + list.push_back(10); + list.push_back(10); + // Assert + EXPECT_FALSE(list.is_empty()); +} +TEST(TestListLib, list_is_empty_true) { + // Arrange & Act + List list; + // Assert + EXPECT_TRUE(list.is_empty()); +} +TEST(TestListLib, push_front_with_empty_list) { + // Arrange & Act + List list; + list.push_front(10); + // Assert + EXPECT_EQ(list.get_size(), 1); + EXPECT_EQ(list.get_head(), list.get_tail()); +} +TEST(TestListLib, push_front_with_several_elements_list) { + // Arrange & Act + List list; + list.push_front(100); + list.push_front(200); + list.push_front(300); + list.push_front(400); + list.push_front(500); + // Assert + EXPECT_EQ(list.get_head()->value, 500); + EXPECT_EQ(list.get_size(), 5); +} +TEST(TestListLib, push_back_with_empty_list) { + // Arrange & Act + List list; + list.push_back(30); + // Assert + EXPECT_EQ(list.get_size(), 1); + EXPECT_EQ(list.get_head(), list.get_tail()); +} +TEST(TestListLib, push_back_with_several_elements_list) { + // Arrange & Act + List list; + list.push_back(300); + list.push_back(400); + list.push_back(500); + list.push_back(600); + list.push_back(700); + list.push_back(800); + list.push_back(900); + // Assert + EXPECT_EQ(list.get_tail()->value, 900); + EXPECT_EQ(list.get_size(), 7); +} +TEST(TestListLib, pop_back_with_empty_list_exception) { + // Arrange & Act + List list; + // Assert + ASSERT_THROW(list.pop_back(), std::logic_error); +} +TEST(TestListLib, pop_back_with_one_element_list) { + // Arrange & Act + List list; + list.push_back(10); + list.pop_back(); + // Assert + EXPECT_EQ(list.get_head(), nullptr); + EXPECT_EQ(list.get_tail(), nullptr); + EXPECT_EQ(list.get_size(), 0); +} +TEST(TestListLib, pop_back_with_several_elements_list) { + // Arrange & Act + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + list.push_back(50); + list.pop_back(); + list.pop_back(); + // Assert + EXPECT_EQ(list.get_tail()->value, 30); + EXPECT_EQ(list.get_size(), 3); +} +TEST(TestListLib, pop_front_with_empty_list_exception) { + // Arrange & Act + List list; + // Assert + ASSERT_THROW(list.pop_front(), std::logic_error); +} +TEST(TestListLib, pop_front_with_one_element_list) { + // Arrange & Act + List list; + list.push_back(10); + list.pop_front(); + // Assert + EXPECT_EQ(list.get_head(), nullptr); + EXPECT_EQ(list.get_tail(), nullptr); + EXPECT_EQ(list.get_size(), 0); +} +TEST(TestListLib, pop_front_with_several_elements_list) { + // Arrange & Act + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + list.push_back(50); + list.push_back(60); + list.push_back(70); + + list.pop_front(); + list.pop_front(); + list.pop_front(); + // Assert + EXPECT_EQ(list.get_head()->value, 40); + EXPECT_EQ(list.get_size(), 4); +} +TEST(TestListLib, list_operator_equal_true) { + // Arrange & Act + List list1; + List list2; + list1.push_back(10); + list1.push_back(20); + list1.push_back(30); + + list2.push_back(10); + list2.push_back(20); + list2.push_back(30); + // Assert + EXPECT_TRUE(list1 == list2); +} +TEST(TestListLib, list_operator_equal_false) { + // Arrange & Act + List list1; + List list2; + list1.push_back(30); + list1.push_back(40); + list1.push_back(50); + list1.push_back(100); + + list2.push_back(30); + list2.push_back(40); + list2.push_back(50); + // Assert + EXPECT_FALSE(list1 == list2); +} +TEST(TestListLib, list_operator_not_equal_true) { + // Arrange & Act + List list1; + List list2; + list1.push_back(70); + list1.push_back(80); + list1.push_back(90); + list1.push_back(100); + + list2.push_back(10); + list2.push_back(20); + list2.push_back(30); + // Assert + EXPECT_TRUE(list1 != list2); +} +TEST(TestListLib, list_operator_not_equal_false) { + // Arrange & Act + List list1; + List list2; + list1.push_back(80); + list1.push_back(80); + list1.push_back(80); + + list2.push_back(80); + list2.push_back(80); + list2.push_back(80); + // Assert + EXPECT_FALSE(list1 != list2); +} +TEST(TestListLib, list_operator_assign) { + // Arrange & Act + List list1; + List list2; + list1.push_back(100); + list1.push_back(800); + list1.push_back(900); + list1.push_back(600); + + list2.push_back(10); + list2.push_back(20); + list2.push_back(30); + list2 = list1; + // Assert + EXPECT_TRUE(list1 == list2); +} +TEST(TestListLib, list_node_insert) { + // Arrange + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + list.push_back(50); + // Act + Node* node = list.get_head()->next; + list.insert(node, 500); + // Assert + EXPECT_EQ(list.get_size(), 6); + EXPECT_EQ(list.get_head()->value, 10); + EXPECT_EQ(list.get_head()->next->value, 20); + EXPECT_EQ(list.get_head()->next->next->value, 500); + EXPECT_EQ(list.get_head()->next->next->next->value, 30); + EXPECT_EQ(list.get_head()->next->next->next->next->value, 40); + EXPECT_EQ(list.get_head()->next->next->next->next->next->value, 50); +} +TEST(TestListLib, list_node_insert_with_exception) { + // Arrange + List list; + Node* node = list.get_head(); + // Act & Assert + ASSERT_THROW(list.insert(node, 500), std::logic_error); +} +TEST(TestListLib, list_position_insert_in_begin) { + // Arrange + List list; + list.push_back(60); + list.push_back(70); + list.push_back(80); + list.push_back(90); + list.push_back(20); + size_t position = 0; + // Act + list.insert(position, 700); + // Assert + EXPECT_EQ(list.get_size(), 6); + EXPECT_EQ(list.get_head()->value, 700); + EXPECT_EQ(list.get_head()->next->value, 60); + EXPECT_EQ(list.get_head()->next->next->value, 70); + EXPECT_EQ(list.get_head()->next->next->next->value, 80); + EXPECT_EQ(list.get_head()->next->next->next->next->value, 90); + EXPECT_EQ(list.get_head()->next->next->next->next->next->value, 20); +} +TEST(TestListLib, list_position_insert_in_end) { + // Arrange + List list; + list.push_back(30); + list.push_back(30); + list.push_back(30); + list.push_back(40); + list.push_back(50); + size_t position = 4; + // Act + list.insert(position, 900); + // Assert + EXPECT_EQ(list.get_size(), 6); + EXPECT_EQ(list.get_head()->value, 30); + EXPECT_EQ(list.get_head()->next->value, 30); + EXPECT_EQ(list.get_head()->next->next->value, 30); + EXPECT_EQ(list.get_head()->next->next->next->value, 40); + EXPECT_EQ(list.get_head()->next->next->next->next->value, 50); + EXPECT_EQ(list.get_head()->next->next->next->next->next->value, 900); +} +TEST(TestListLib, list_position_insert) { + // Arrange + List list; + list.push_back(30); + list.push_back(80); + list.push_back(30); + list.push_back(40); + list.push_back(50); + size_t position = 2; + // Act + list.insert(position, 250); + // Assert + EXPECT_EQ(list.get_size(), 6); + EXPECT_EQ(list.get_head()->value, 30); + EXPECT_EQ(list.get_head()->next->value, 80); + EXPECT_EQ(list.get_head()->next->next->value, 250); + EXPECT_EQ(list.get_head()->next->next->next->value, 30); + EXPECT_EQ(list.get_head()->next->next->next->next->value, 40); + EXPECT_EQ(list.get_head()->next->next->next->next->next->value, 50); +} +TEST(TestListLib, list_position_insert_with_exception) { + // Arrange + List list; + list.push_back(300); + list.push_back(850); + list.push_back(320); + list.push_back(40); + list.push_back(90); + size_t position = 10; + // Act & Assert + ASSERT_THROW(list.insert(position, 500), std::invalid_argument); +} +TEST(TestListLib, list_position_erase_in_begin) { + // Arrange + List list; + list.push_back(60); + list.push_back(70); + list.push_back(80); + list.push_back(90); + list.push_back(20); + size_t position = 0; + // Act + list.erase(position); + // Assert + EXPECT_EQ(list.get_size(), 4); + EXPECT_EQ(list.get_head()->value, 70); + EXPECT_EQ(list.get_head()->next->value, 80); + EXPECT_EQ(list.get_head()->next->next->value, 90); + EXPECT_EQ(list.get_head()->next->next->next->value, 20); +} +TEST(TestListLib, list_position_erase_in_end) { + // Arrange + List list; + list.push_back(680); + list.push_back(70); + list.push_back(80); + list.push_back(920); + list.push_back(20); + size_t position = 4; + // Act + list.erase(position); + // Assert + EXPECT_EQ(list.get_size(), 4); + EXPECT_EQ(list.get_head()->value, 680); + EXPECT_EQ(list.get_head()->next->value, 70); + EXPECT_EQ(list.get_head()->next->next->value, 80); + EXPECT_EQ(list.get_head()->next->next->next->value, 920); +} +TEST(TestListLib, list_position_erase) { + // Arrange + List list; + list.push_back(320); + list.push_back(840); + list.push_back(30); + list.push_back(40); + list.push_back(550); + size_t position = 3; + // Act + list.erase(position); + // Assert + EXPECT_EQ(list.get_size(), 4); + EXPECT_EQ(list.get_head()->value, 320); + EXPECT_EQ(list.get_head()->next->value, 840); + EXPECT_EQ(list.get_head()->next->next->value, 30); + EXPECT_EQ(list.get_head()->next->next->next->value, 550); +} +TEST(TestListLib, list_position_erase_with_exception1) { + // Arrange + List list; + size_t position = 2; + // Act & Assert + ASSERT_THROW(list.erase(position), std::logic_error); +} +TEST(TestListLib, list_position_erase_with_exception2) { + // Arrange + List list; + list.push_back(32000); + list.push_back(8220); + list.push_back(320); + list.push_back(40); + list.push_back(50); + size_t position = 10; + // Act & Assert + ASSERT_THROW(list.erase(position), std::invalid_argument); +} +TEST(TestListLib, list_node_erase) { + // Arrange + List list; + list.push_back(3270); + list.push_back(840); + list.push_back(30); + list.push_back(40); + list.push_back(55770); + Node* node = list.get_head()->next; + // Act + list.erase(node); + // Assert + EXPECT_EQ(list.get_size(), 4); + EXPECT_EQ(list.get_head()->value, 3270); + EXPECT_EQ(list.get_head()->next->value, 30); + EXPECT_EQ(list.get_head()->next->next->value, 40); + EXPECT_EQ(list.get_head()->next->next->next->value, 55770); +} +TEST(TestListLib, list_node_erase_with_exception1) { + // Arrange + List list; + Node* node = list.get_head(); + // Act & Assert + ASSERT_THROW(list.erase(node), std::logic_error); +} +TEST(TestListLib, list_node_erase_with_exception2) { + // Arrange + List list; + list.push_back(32000); + list.push_back(8220); + list.push_back(32100); + list.push_back(10); + list.push_back(10); + Node* node = new Node(2300); + // Act & Assert + ASSERT_THROW(list.erase(node), std::invalid_argument); +} +TEST(TestListLib, list_iterator_read) { + // Arrange + List list; + list.push_back(80); + list.push_back(320); + list.push_back(107); + // Act + auto it = list.begin(); + it += 2; + // Assert + EXPECT_EQ(107, *it); +} +TEST(TestListLib, list_iterator_write) { + // Arrange + List list; + list.push_back(50); + list.push_back(20); + list.push_back(7); + list.push_back(1); + list.push_back(300); + // Act + auto it = list.begin(); + it += 3; + *it = 900; + // Assert + EXPECT_EQ(900, *it); +} +TEST(TestListLib, list_iterator_empty_list) { + // Arrange + List list; + // Act & Assert + EXPECT_EQ(list.begin(), list.end()); + + auto it = list.begin(); + ++it; + EXPECT_EQ(it, list.end()); + + auto end_it = list.end(); + ++end_it; + EXPECT_EQ(end_it, list.end()); + + auto it2 = list.begin(); + it2 += 5; + EXPECT_EQ(it2, list.end()); +} +TEST(TestListLib, list_iterator_prefix_increment) { + // Arrange + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + + // Act + auto it = list.begin(); + ++it; + + // Assert + EXPECT_EQ(20, *it); + ++it; + EXPECT_EQ(30, *it); +} + +TEST(TestListLib, list_iterator_postfix_increment) { + // Arrange + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + + // Act + auto it = list.begin(); + auto it_copy = it++; + + // Assert + EXPECT_EQ(10, *it_copy); + EXPECT_EQ(20, *it); +} + +TEST(TestListLib, list_iterator_compound_addition) { + // Arrange + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + list.push_back(50); + + // Act + auto it = list.begin(); + it += 2; + + // Assert + EXPECT_EQ(30, *it); + + it += 2; + EXPECT_EQ(50, *it); +} + +TEST(TestListLib, list_iterator_equality_operators) { + // Arrange + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + + // Act & Assert + auto it1 = list.begin(); + auto it2 = list.begin(); + EXPECT_TRUE(it1 == it2); + + ++it1; + EXPECT_FALSE(it1 == it2); + EXPECT_TRUE(it1 != it2); +} + +TEST(TestListLib, list_iterator_dereference_const) { + // Arrange + List list; + list.push_back(100); + list.push_back(200); + + // Act + const auto& const_list = list; + auto it = const_list.begin(); + + // Assert + EXPECT_EQ(100, *it); + ++it; + EXPECT_EQ(200, *it); +} +TEST(TestListLib, list_iterator_range_based_for_loop) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + list.push_back(4); + list.push_back(5); + // Act + std::vector values; + for (const auto& value : list) { + values.push_back(value); + } + // Assert + ASSERT_EQ(5, values.size()); + EXPECT_EQ(1, values[0]); + EXPECT_EQ(2, values[1]); + EXPECT_EQ(3, values[2]); + EXPECT_EQ(4, values[3]); + EXPECT_EQ(5, values[4]); +} +TEST(TestListLib, list_iterator_range_based_for_loop_modify) { + // Arrange + List list; + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Act + for (auto& value : list) { + value *= 2; + } + // Assert + auto it = list.begin(); + EXPECT_EQ(2, *it); + ++it; + EXPECT_EQ(4, *it); + ++it; + EXPECT_EQ(6, *it); +} +TEST(TestListLib, list_iterator_manual_for_loop) { + // Arrange + List list; + list.push_back(10); + list.push_back(20); + list.push_back(30); + list.push_back(40); + + // Act + std::vector values; + for (auto it = list.begin(); it != list.end(); ++it) { + values.push_back(*it); + } + // Assert + ASSERT_EQ(4, values.size()); + EXPECT_EQ(10, values[0]); + EXPECT_EQ(20, values[1]); + EXPECT_EQ(30, values[2]); + EXPECT_EQ(40, values[3]); +} +TEST(TestListLib, list_iterator_dereference_end_exception) { + // Arrange + List list; + list.push_back(10); + // Act & Assert + auto it = list.end(); + EXPECT_THROW(*it, std::runtime_error); + auto begin_it = list.begin(); + ++begin_it; + EXPECT_THROW(*begin_it, std::runtime_error); +} +TEST(TestListLib, list_iterator_copy_constructor) { + // Arrange + List list; + list.push_back(100); + list.push_back(200); + // Act + auto it1 = list.begin(); + auto it2 = it1; + // Assert + EXPECT_TRUE(it1 == it2); + EXPECT_EQ(100, *it1); + EXPECT_EQ(100, *it2); + ++it1; + EXPECT_FALSE(it1 == it2); + EXPECT_EQ(200, *it1); + EXPECT_EQ(100, *it2); +} +TEST(TestListLib, list_iterator_assignment_operator) { + // Arrange + List list; + list.push_back(100); + list.push_back(200); + list.push_back(300); + // Act + auto it1 = list.begin(); + auto it2 = list.begin(); + ++it2; + ++it2; + it1 = it2; + // Assert + EXPECT_TRUE(it1 == it2); + EXPECT_EQ(300, *it1); + EXPECT_EQ(300, *it2); +} diff --git a/tests/test_math_vector.cpp b/tests/test_math_vector.cpp new file mode 100644 index 00000000..bff4c8e9 --- /dev/null +++ b/tests/test_math_vector.cpp @@ -0,0 +1,350 @@ +// Copyright 2025 Julia Zabytina +#include +#include +#include "../lib_math_vector/math_vector.h" +TEST(TestMathVectorLib, mathvector_default_constructor) { + // Arrange & Act + MathVector vector; + // Assert + EXPECT_TRUE(vector.is_empty()); +} +TEST(TestMathVectorLib, mathvector_constructor_with_size) { + // Arrange & Act + size_t size = 10; + MathVector vector(size); + // Assert + EXPECT_LE(vector.get_size(), vector.get_capacity()); + EXPECT_EQ(vector.get_size(), size); +} +TEST(TestMathVectorLib, mathvector_constructor_with_size_and_start_index) { + // Arrange & Act + size_t size = 10; + size_t start_index = 1; + MathVector vector(size, start_index); + // Assert + EXPECT_LE(vector.get_size(), vector.get_capacity()); + EXPECT_EQ(vector.get_size(), size); + EXPECT_EQ(vector.get_start_index(), start_index); +} +TEST(TestMathVectorLib, mathvector_constructor_with_array_and_size) { + // Arrange & Act + int data[3] = { 1,2,3 }; + size_t size = 3; + MathVector vector(data, size); + // Assert + EXPECT_EQ(vector.get_size(), size); + EXPECT_EQ(vector[0], data[0]); + EXPECT_EQ(vector[1], data[1]); + EXPECT_EQ(vector[2], data[2]); + EXPECT_LE(vector.get_size(), vector.get_capacity()); +} +TEST(TestMathVectorLib, mathvector_constructor_with_array_and_size_and_start_index) { + // Arrange & Act + int data[3] = { 1,2,3 }; + size_t size = 3; + size_t start_index = 1; + MathVector vector(data, size, start_index); + // Assert + EXPECT_EQ(vector.get_start_index(), start_index); + EXPECT_EQ(vector.get_size(), size); + EXPECT_EQ(vector[1], data[0]); + EXPECT_EQ(vector[2], data[1]); + EXPECT_EQ(vector[3], data[2]); + EXPECT_LE(vector.get_size(), vector.get_capacity()); +} +TEST(TestMathVectorLib, mathvector_copy_constructor) { + // Arrange & Act + int data[3] = { 1,2,3 }; + size_t size = 3; + MathVector old_vector(data, size); + MathVector new_vector(old_vector); + // Assert + EXPECT_EQ(old_vector.get_start_index(), new_vector.get_start_index()); + EXPECT_EQ(old_vector, new_vector); +} +TEST(TestMathVectorLib, mathvector_mult_on_value) { + // Arrange & Act + int data[3] = { 1,2,3 }; + size_t size = 3; + int value = 5; + MathVector vector(data, size); + MathVector result; + result = vector * value; + // Assert + EXPECT_EQ(result[0], vector[0] * value); + EXPECT_EQ(result[1], vector[1] * value); + EXPECT_EQ(result[2], vector[2] * value); +} +TEST(TestMathVectorLib, mathvector_div_on_value) { + // Arrange & Act + int data[3] = { 4,8,28 }; + size_t size = 3; + int value = 2; + MathVector vector(data, size); + MathVector result; + result = vector / value; + // Assert + EXPECT_EQ(result[0], vector[0] / value); + EXPECT_EQ(result[1], vector[1] / value); + EXPECT_EQ(result[2], vector[2] / value); +} +TEST(TestMathVectorLib, mathvector_div_on_null_exception) { + // Arrange & Act + int data[3] = { 10, 27, 21 }; + size_t size = 3; + MathVector vector(data, size); + int value = 0; + // Assert + EXPECT_THROW(vector / value, std::logic_error); +} +TEST(TestMathVectorLib, mathvector_mult_assign_on_value) { + // Arrange & Act + int data[3] = { 3, 6, 0 }; + size_t size = 3; + int value = 3; + MathVector vector(data, size); + vector *= value; + // Assert + EXPECT_EQ(vector[0], data[0] * value); + EXPECT_EQ(vector[1], data[1] * value); + EXPECT_EQ(vector[2], data[2] * value); +} +TEST(TestMathVectorLib, mathvector_div_assign_on_value) { + // Arrange & Act + int data[3] = { 4,8,28 }; + size_t size = 3; + int value = 2; + MathVector vector(data, size); + vector /= value; + // Assert + EXPECT_EQ(vector[0], data[0] / value); + EXPECT_EQ(vector[1], data[1] / value); + EXPECT_EQ(vector[2], data[2] / value); +} +TEST(TestMathVectorLib, mathvector_div_assign_on_null_exception) { + // Arrange & Act + int data[3] = { 4,8,28 }; + size_t size = 3; + int value = 0; + MathVector vector(data, size); + // Assert + EXPECT_THROW(vector /= value, std::logic_error); +} +TEST(TestMathVectorLib, mathvector_add_vector) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[3] = { 5, 0, 100 }; + size_t size2 = 3; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + MathVector result; + result = vector1 + vector2; + // Assert + EXPECT_EQ(result[0], vector1[0] + vector2[0]); + EXPECT_EQ(result[1], vector1[1] + vector2[1]); + EXPECT_EQ(result[2], vector1[2] + vector2[2]); +} +TEST(TestMathVectorLib, mathvector_sub_vector) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[3] = { 5, 0, 100 }; + size_t size2 = 3; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + MathVector result; + result = vector1 - vector2; + // Assert + EXPECT_EQ(result[0], vector1[0] - vector2[0]); + EXPECT_EQ(result[1], vector1[1] - vector2[1]); + EXPECT_EQ(result[2], vector1[2] - vector2[2]); +} +TEST(TestMathVectorLib, mathvector_scalar_product) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[3] = { 5, 0, 100 }; + size_t size2 = 3; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + int result = 0; + int scalar_product = + vector1[0] * vector2[0] + + vector1[1] * vector2[1] + + vector1[2] * vector2[2]; + result = vector1 * vector2; + // Assert + EXPECT_EQ(result, scalar_product); +} +TEST(TestMathVectorLib, mathvector_add_for_vectors_with_different_dimension_exception) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[5] = { 5, 100, 1, 22, 7 }; + size_t size2 = 5; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + + // Assert + EXPECT_THROW(vector1 + vector2, std::logic_error); +} +TEST(TestMathVectorLib, mathvector_sub_for_vectors_with_different_dimension_exception) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[5] = { 5, 100, 1, 22, 7 }; + size_t size2 = 5; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + + // Assert + EXPECT_THROW(vector1 - vector2, std::logic_error); +} +TEST(TestMathVectorLib, mathvector_scalar_product_for_vectors_with_different_dimension_exception) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[5] = { 5, 100, 1, 22, 7 }; + size_t size2 = 5; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + + // Assert + EXPECT_THROW(vector1 * vector2, std::logic_error); +} +TEST(TestMathVectorLib, mathvector_add_assign_vector) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[3] = { 5, 0, 100 }; + size_t size2 = 3; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + vector1 += vector2; + // Assert + EXPECT_EQ(vector1[0], data1[0] + data2[0]); + EXPECT_EQ(vector1[1], data1[1] + data2[1]); + EXPECT_EQ(vector1[2], data1[2] + data2[2]); +} +TEST(TestMathVectorLib, mathvector_sub_assign_vector) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[3] = { 5, 0, 100 }; + size_t size2 = 3; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + vector1 -= vector2; + // Assert + EXPECT_EQ(vector1[0], data1[0] - data2[0]); + EXPECT_EQ(vector1[1], data1[1] - data2[1]); + EXPECT_EQ(vector1[2], data1[2] - data2[2]); +} +TEST(TestMathVectorLib, mathvector_add_assign_for_vectors_with_different_dimension_exception) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[5] = { 5, 100, 1, 22, 7 }; + size_t size2 = 5; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + + // Assert + EXPECT_THROW(vector1 += vector2, std::logic_error); +} +TEST(TestMathVectorLib, mathvector_sub_assign_for_vectors_with_different_dimension_exception) { + // Arrange & Act + int data1[3] = { 4, 7 ,28 }; + size_t size1 = 3; + + int data2[5] = { 5, 100, 1, 22, 7 }; + size_t size2 = 5; + + MathVector vector1(data1, size1); + MathVector vector2(data2, size2); + + // Assert + EXPECT_THROW(vector1 -= vector2, std::logic_error); +} +TEST(TestMathVectorLib, mathvector_simple_assignment) { + // Arrange + MathVector vector1(2); + MathVector vector2(2); + vector1[0] = 1; + vector1[1] = 2; + vector2[0] = 3; + vector2[1] = 4; + //Act + vector1 = vector2; + // Assert + EXPECT_EQ(vector1[0], 3); + EXPECT_EQ(vector1[1], 4); +} +TEST(TestMathVectorLib, mathvector_operator_square_brackets) { + // Arrange + size_t size = 5; + size_t start_index = 1; + MathVector vector1(size, start_index); + vector1[1] = 2; + vector1[2] = 3; + vector1[3] = 4; + vector1[4] = 5; + vector1[5] = 6; + //Act & Assert + EXPECT_EQ(vector1[1], 2); + EXPECT_EQ(vector1[2], 3); + EXPECT_EQ(vector1[3], 4); + EXPECT_EQ(vector1[4], 5); + EXPECT_EQ(vector1[5], 6); +} +TEST(TestMathVectorLib, mathvector_at) { + // Arrange + size_t size = 5; + size_t start_index = 2; + MathVector vector1(size, start_index); + vector1[2] = 3; + vector1[3] = 4; + vector1[4] = 5; + vector1[5] = 6; + vector1[6] = 7; + //Act & Assert + EXPECT_EQ(vector1.at(2), 3); + EXPECT_EQ(vector1.at(3), 4); + EXPECT_EQ(vector1.at(4), 5); + EXPECT_EQ(vector1.at(5), 6); + EXPECT_EQ(vector1.at(6), 7); +} +TEST(TestMathVectorLib, mathvector_at_with_exception) { + // Arrange + size_t size = 5; + size_t start_index = 2; + MathVector vector1(size, start_index); + vector1[2] = 3; + vector1[3] = 4; + vector1[4] = 5; + vector1[5] = 6; + vector1[6] = 7; + //Act & Assert + EXPECT_THROW(vector1.at(0), std::logic_error); + EXPECT_THROW(vector1.at(1), std::logic_error); + EXPECT_THROW(vector1.at(7), std::logic_error); +} diff --git a/tests/test_matrix.cpp b/tests/test_matrix.cpp new file mode 100644 index 00000000..a0482516 --- /dev/null +++ b/tests/test_matrix.cpp @@ -0,0 +1,389 @@ +// Copyright 2025 Julia Zabytina +#include +#include +#include "../lib_matrix/matrix.h" +TEST(TestMatrixLib, matrix_default_constructor) { + // Arrange & Act + Matrix matrix; + // Assert + EXPECT_EQ(0, matrix.getM()); + EXPECT_EQ(0, matrix.getN()); + EXPECT_TRUE(matrix.is_empty()); +} +TEST(TestMatrixLib, matrix_constructor_with_size) { + // Arrange & Act + size_t M = 100; + size_t N = 100; + Matrix matrix(M, N); + // Assert + EXPECT_EQ(M, matrix.getM()); + EXPECT_EQ(N, matrix.getN()); +} +TEST(TestMatrixLib, matrix_constructor_with_array_and_size) { + // Arrange & Act + size_t M = 2; + size_t N = 2; + int data[4] = { 1, 2, 3, 4 }; + Matrix matrix(data, M, N); + // Assert + EXPECT_EQ(M, matrix.getM()); + EXPECT_EQ(N, matrix.getN()); + EXPECT_EQ(matrix[0][0], data[0]); + EXPECT_EQ(matrix[0][1], data[1]); + EXPECT_EQ(matrix[1][0], data[2]); + EXPECT_EQ(matrix[1][1], data[3]); +} +TEST(TestMatrixLib, matrix_copy_constructor) { + // Arrange & Act + size_t M = 2; + size_t N = 2; + int data[4] = { 1, 2, 3, 4}; + Matrix old_matrix(data, M, N); + Matrix new_matrix(old_matrix); + // Assert + EXPECT_EQ(old_matrix, new_matrix); +} +TEST(TestMatrixLib, matrix_assignment_operator) { + // Arrange + size_t M = 2, N = 2; + int data1[4] = { 1, 2, 3, 4 }; + int data2[4] = { 5, 6, 7, 8 }; + Matrix matrix1(data1, M, N); + Matrix matrix2(data2, M, N); + // Act + matrix1 = matrix2; + // Assert + EXPECT_EQ(matrix1, matrix2); +} +TEST(TestMatrixLib, matrix_add_value) { + // Arrange + size_t M = 2, N = 2; + int data[4] = { 1, 2, 3, 4 }; + int value = 10; + Matrix matrix(data, M, N); + Matrix result(M, N); + // Act + result = matrix + value; + // Assert + EXPECT_EQ(result[0][0], data[0] + value); + EXPECT_EQ(result[0][1], data[1] + value); + EXPECT_EQ(result[1][0], data[2] + value); + EXPECT_EQ(result[1][1], data[3] + value); +} +TEST(TestMatrixLib, matrix_sub_value) { + // Arrange + size_t M = 2, N = 2; + int data[4] = { 1, 2, 3, 4 }; + int value = 10; + Matrix matrix(data, M, N); + Matrix result(M, N); + // Act + result = matrix - value; + // Assert + EXPECT_EQ(result[0][0], data[0] - value); + EXPECT_EQ(result[0][1], data[1] - value); + EXPECT_EQ(result[1][0], data[2] - value); + EXPECT_EQ(result[1][1], data[3] - value); +} +TEST(TestMatrixLib, matrix_mult_value) { + // Arrange + size_t M = 2, N = 2; + int data[4] = { 1, 2, 3, 4 }; + int value = 10; + Matrix matrix(data, M, N); + Matrix result(M, N); + // Act + result = matrix * value; + // Assert + EXPECT_EQ(result[0][0], data[0] * value); + EXPECT_EQ(result[0][1], data[1] * value); + EXPECT_EQ(result[1][0], data[2] * value); + EXPECT_EQ(result[1][1], data[3] * value); +} +TEST(TestMatrixLib, matrix_div_value) { + // Arrange + size_t M = 2, N = 2; + int data[4] = { 2, 2, 10, 4 }; + int value = 2; + Matrix matrix(data, M, N); + Matrix result(M, N); + // Act + result = matrix / value; + // Assert + EXPECT_EQ(result[0][0], data[0] / value); + EXPECT_EQ(result[0][1], data[1] / value); + EXPECT_EQ(result[1][0], data[2] / value); + EXPECT_EQ(result[1][1], data[3] / value); +} +TEST(TestMatrixLib, matrix_div_value_with_exception) { + // Arrange & Act + size_t M = 2, N = 2; + int data[4] = { 1, 2, 3, 4 }; + int value = 0; + Matrix matrix(data, M, N); + // Assert + EXPECT_THROW(matrix / value;, std::logic_error); +} +TEST(TestMatrixLib, matrix_add_assign_value) { + // Arrange + size_t M = 2, N = 2; + int data[4] = { 2, 2, 10, 4 }; + int value = 2; + Matrix matrix(data, M, N); + // Act + matrix += value; + // Assert + EXPECT_EQ(matrix[0][0], data[0] + value); + EXPECT_EQ(matrix[0][1], data[1] + value); + EXPECT_EQ(matrix[1][0], data[2] + value); + EXPECT_EQ(matrix[1][1], data[3] + value); +} +TEST(TestMatrixLib, matrix_sub_assign_value) { + // Arrange + size_t M = 2, N = 2; + int data[4] = { 2, 2, 10, 4 }; + int value = 2; + Matrix matrix(data, M, N); + // Act + matrix -= value; + // Assert + EXPECT_EQ(matrix[0][0], data[0] - value); + EXPECT_EQ(matrix[0][1], data[1] - value); + EXPECT_EQ(matrix[1][0], data[2] - value); + EXPECT_EQ(matrix[1][1], data[3] - value); +} +TEST(TestMatrixLib, matrix_mult_assign_value) { + // Arrange + size_t M = 2, N = 2; + int data[4] = { 2, 2, 10, 4 }; + int value = 2; + Matrix matrix(data, M, N); + // Act + matrix *= value; + // Assert + EXPECT_EQ(matrix[0][0], data[0] * value); + EXPECT_EQ(matrix[0][1], data[1] * value); + EXPECT_EQ(matrix[1][0], data[2] * value); + EXPECT_EQ(matrix[1][1], data[3] * value); +} +TEST(TestMatrixLib, matrix_div_assign_value) { + // Arrange + size_t M = 2, N = 2; + int data[4] = { 2, 2, 10, 4 }; + int value = 2; + Matrix matrix(data, M, N); + // Act + matrix /= value; + // Assert + EXPECT_EQ(matrix[0][0], data[0] / value); + EXPECT_EQ(matrix[0][1], data[1] / value); + EXPECT_EQ(matrix[1][0], data[2] / value); + EXPECT_EQ(matrix[1][1], data[3] / value); +} +TEST(TestMatrixLib, matrix_div_assign_value_with_exception) { + // Arrange & Act + size_t M = 2, N = 2; + int data[4] = { 1, 2, 3, 4 }; + int value = 0; + Matrix matrix(data, M, N); + // Assert + EXPECT_THROW(matrix /= value; , std::logic_error); +} +TEST(TestMatrixLib, matrix_add_matrix) { + // Arrange + size_t M = 2, N = 3; + int data1[6] = { 2, 2, 10, 4, 5, 7 }; + int data2[6] = { 8, 2, 3, 0, 5, 7}; + + Matrix matrix1(data1, M, N); + Matrix matrix2(data2, M, N); + Matrix result(M, N); + // Act + result = matrix1 + matrix2; + // Assert + EXPECT_EQ(result[0][0], data1[0] + data2[0]); + EXPECT_EQ(result[0][1], data1[1] + data2[1]); + EXPECT_EQ(result[0][2], data1[2] + data2[2]); + EXPECT_EQ(result[1][0], data1[3] + data2[3]); + EXPECT_EQ(result[1][1], data1[4] + data2[4]); + EXPECT_EQ(result[1][2], data1[5] + data2[5]); +} +TEST(TestMatrixLib, matrix_sub_matrix) { + // Arrange + size_t M = 2, N = 3; + int data1[6] = { 2, 2, 10, 4, 5, 7 }; + int data2[6] = { 8, 2, 3, 0, 5, 7 }; + + Matrix matrix1(data1, M, N); + Matrix matrix2(data2, M, N); + Matrix result(M, N); + // Act + result = matrix1 - matrix2; + // Assert + EXPECT_EQ(result[0][0], data1[0] - data2[0]); + EXPECT_EQ(result[0][1], data1[1] - data2[1]); + EXPECT_EQ(result[0][2], data1[2] - data2[2]); + EXPECT_EQ(result[1][0], data1[3] - data2[3]); + EXPECT_EQ(result[1][1], data1[4] - data2[4]); + EXPECT_EQ(result[1][2], data1[5] - data2[5]); +} +TEST(TestMatrixLib, matrix_add_matrix_with_exception) { + // Arrange & Act + size_t M1 = 2, N1 = 3; + size_t M2 = 2, N2 = 2; + + int data1[6] = { 2, 2, 10, 4, 5, 7 }; + int data2[4] = { 8, 2, 3, 0 }; + + Matrix matrix1(data1, M1, N1); + Matrix matrix2(data2, M2, N2); + + // Assert + EXPECT_THROW(matrix1 + matrix2, std::logic_error); +} +TEST(TestMatrixLib, matrix_sub_matrix_with_exception) { + // Arrange & Act + size_t M1 = 2, N1 = 3; + size_t M2 = 2, N2 = 2; + + int data1[6] = { 2, 2, 10, 4, 5, 7 }; + int data2[4] = { 8, 2, 3, 0 }; + + Matrix matrix1(data1, M1, N1); + Matrix matrix2(data2, M2, N2); + + // Assert + EXPECT_THROW(matrix1 - matrix2, std::logic_error); +} +TEST(TestMatrixLib, matrix_add_assign_matrix) { + // Arrange + size_t M = 2, N = 3; + int data1[6] = { 2, 2, 10, 4, 5, 7 }; + int data2[6] = { 8, 2, 3, 0, 5, 7 }; + + Matrix matrix1(data1, M, N); + Matrix matrix2(data2, M, N); + // Act + matrix1 += matrix2; + // Assert + EXPECT_EQ(matrix1[0][0], data1[0] + data2[0]); + EXPECT_EQ(matrix1[0][1], data1[1] + data2[1]); + EXPECT_EQ(matrix1[0][2], data1[2] + data2[2]); + EXPECT_EQ(matrix1[1][0], data1[3] + data2[3]); + EXPECT_EQ(matrix1[1][1], data1[4] + data2[4]); + EXPECT_EQ(matrix1[1][2], data1[5] + data2[5]); +} +TEST(TestMatrixLib, matrix_add_assign_matrix_with_exception) { + // Arrange & Act + size_t M1 = 2, N1 = 3; + size_t M2 = 2, N2 = 2; + int data1[6] = { 2, 2, 10, 4, 5, 7 }; + int data2[4] = { 8, 2, 3, 0 }; + Matrix matrix1(data1, M1, N1); + Matrix matrix2(data2, M2, N2); + // Assert + EXPECT_THROW(matrix1 += matrix2, std::logic_error); +} +TEST(TestMatrixLib, matrix_sub_assign_matrix) { + // Arrange + size_t M = 2, N = 3; + int data1[6] = { 2, 2, 10, 4, 5, 7 }; + int data2[6] = { 8, 2, 3, 0, 5, 7 }; + + Matrix matrix1(data1, M, N); + Matrix matrix2(data2, M, N); + // Act + matrix1 -= matrix2; + // Assert + EXPECT_EQ(matrix1[0][0], data1[0] - data2[0]); + EXPECT_EQ(matrix1[0][1], data1[1] - data2[1]); + EXPECT_EQ(matrix1[0][2], data1[2] - data2[2]); + EXPECT_EQ(matrix1[1][0], data1[3] - data2[3]); + EXPECT_EQ(matrix1[1][1], data1[4] - data2[4]); + EXPECT_EQ(matrix1[1][2], data1[5] - data2[5]); +} +TEST(TestMatrixLib, matrix_sub_assign_matrix_with_exception) { + // Arrange & Act + size_t M1 = 2, N1 = 3; + size_t M2 = 2, N2 = 2; + int data1[6] = { 2, 2, 10, 4, 5, 7 }; + int data2[4] = { 8, 2, 3, 0 }; + Matrix matrix1(data1, M1, N1); + Matrix matrix2(data2, M2, N2); + // Assert + EXPECT_THROW(matrix1 -= matrix2, std::logic_error); +} +TEST(TestMatrixLib, matrix_mult_matrix) { + // Arrange + size_t M1 = 2, N1 = 3, M2 = 3, N2 = 2; + + int data1[6] = { 2, 2, 1, 2, 1, 2 }; + int data2[6] = { 3, 2, 2, 1, 3, 2 }; + + Matrix matrix1(data1, M1, N1); + Matrix matrix2(data2, M2, N2); + Matrix result(M1, N2); + // Act + result = matrix1 * matrix2; + // Assert + EXPECT_EQ(result[0][0], 13); + EXPECT_EQ(result[0][1], 8); + EXPECT_EQ(result[1][0], 14); + EXPECT_EQ(result[1][1], 9); +} +TEST(TestMatrixLib, matrix_mult_matrix_with_throw) { + //Arrange & Act + size_t M1 = 2, N1 = 3, M2 = 2, N2 = 2; + + int data1[6] = { 2, 2, 1, 2, 1, 2 }; + int data2[6] = { 3, 2, 2, 1 }; + + Matrix matrix1(data1, M1, N1); + Matrix matrix2(data2, M2, N2); + //Assert + EXPECT_THROW(matrix1 * matrix2, std::logic_error); +} +TEST(TestMatrixLib, matrix_mult_vector) { + // Arrange + size_t M = 2, N = 3, size = 3; + int data1[6] = { 2, 3, 1, 4, 1, 2 }; + int data2[3] = { 2, 2, 2 }; + Matrix matrix(data1, M, N); + MathVector vector(data2, size); + MathVector result(M); + // Act + result = matrix * vector; + // Assert + EXPECT_EQ(result[0], 12); + EXPECT_EQ(result[1], 14); +} +TEST(TestMatrixLib, matrix_mult_vector_with_exception) { + // Arrange & Act + size_t M = 2, N = 3, size = 5; + int data1[6] = { 2, 3, 1, 4, 1, 2 }; + int data2[5] = { 2, 2, 2, 6, 7 }; + Matrix matrix(data1, M, N); + MathVector vector(data2, size); + // Assert + EXPECT_THROW(matrix * vector, std::logic_error); +} +TEST(TestMatrixLib, matrix_simple_assignment) { + // Arrange + Matrix matrix1(2, 2); + Matrix matrix2(2, 2); + matrix1[0][0] = 1; + matrix1[0][1] = 2; + matrix1[1][0] = 3; + matrix1[1][1] = 4; + matrix2[0][0] = 5; + matrix2[0][1] = 6; + matrix2[1][0] = 7; + matrix2[1][1] = 8; + //Act + matrix1 = matrix2; + // + EXPECT_EQ(matrix1[0][0], 5); + EXPECT_EQ(matrix1[0][1], 6); + EXPECT_EQ(matrix1[1][0], 7); + EXPECT_EQ(matrix1[1][1], 8); +} diff --git a/tests/test_monom.cpp b/tests/test_monom.cpp new file mode 100644 index 00000000..d7b553e8 --- /dev/null +++ b/tests/test_monom.cpp @@ -0,0 +1,308 @@ +// Copyright 2025 Julia Zabytina +#include +#include +#include "../lib_monom/monom.h" +const double TEST_EPSILON = 1e-10; +TEST(TestMonomLib, monom_default_constructor) { + // Arrange & Act + Monom monom; + // Assert + EXPECT_TRUE(std::abs(monom.get_coefficient()) < TEST_EPSILON); + EXPECT_EQ(monom.powerX(), 0); + EXPECT_EQ(monom.powerY(), 0); + EXPECT_EQ(monom.powerZ(), 0); +} +TEST(TestMonomLib, monom_constructor_with_arguments) { + // Arrange & Act + double coefficient = 1.5; + int power_x = 2; + int power_y = 3; + int power_z = 5; + Monom monom(coefficient, power_x, power_y, power_z); + // Assert + EXPECT_EQ(monom.get_coefficient(), coefficient); + EXPECT_EQ(monom.powerX(), power_x); + EXPECT_EQ(monom.powerY(), power_y); + EXPECT_EQ(monom.powerZ(), power_z); +} +TEST(TestMonomLib, constructor_with_arguments_throws_on_negative_power_x) { + ASSERT_THROW(Monom(1.0, -99, 1, 0), std::invalid_argument); +} +TEST(TestMonomLib, constructor_with_arguments_throws_on_negative_power_y) { + ASSERT_THROW(Monom(10.0, 22, -301, 50), std::invalid_argument); +} +TEST(TestMonomLib, constructor_with_arguments_throws_on_negative_power_z) { + ASSERT_THROW(Monom(100.5, 33, 67, -100), std::invalid_argument); +} +TEST(TestMonomLib, constructor_with_arguments_throws_on_all_negative_powers) { + ASSERT_THROW(Monom(39.78, -12, -20, -33), std::invalid_argument); +} +TEST(TestMonomLib, is_monoms_similar_true) { + // Arrange & Act + Monom monom1(10, 2, 3, 4); + Monom monom2(34, 2, 3, 4); + // Assert + EXPECT_TRUE(monom1 == monom2); +} +TEST(TestMonomLib, is_monoms_not_similar_true) { + // Arrange & Act + Monom monom1(10, 2, 29, 4); + Monom monom2(34, 2, 3, 4); + // Assert + EXPECT_TRUE(monom1 != monom2); +} +TEST(TestMonomLib, is_monoms_similar_false) { + // Arrange & Act + Monom monom1(10, 2, 3, 77); + Monom monom2(34, 2, 25, 4); + // Assert + EXPECT_FALSE(monom1 == monom2); +} +TEST(TestMonomLib, is_monoms_not_similar_false) { + // Arrange & Act + Monom monom1(10, 2, 3, 4); + Monom monom2(34, 2, 3, 4); + // Assert + EXPECT_FALSE(monom1 != monom2); +} +TEST(TestMonomLib, monom1_greater_monom2_true) { + // Arrange & Act + Monom monom1(130, 10, 3, 4); + Monom monom2(35, 2, 3, 4); + // Assert + EXPECT_TRUE(monom1 > monom2); +} +TEST(TestMonomLib, monom1_less_monom2_true) { + // Arrange & Act + Monom monom1(10, 1, 1, 2); + Monom monom2(34, 2, 3, 4); + // Assert + EXPECT_TRUE(monom1 < monom2); +} +TEST(TestMonomLib, monom1_greater_monom2_false) { + // Arrange & Act + Monom monom1(130, 10, 3, 4); + Monom monom2(35, 2, 3, 389); + // Assert + EXPECT_FALSE(monom1 > monom2); +} +TEST(TestMonomLib, monom1_less_monom2_false) { + // Arrange & Act + Monom monom1(10.1, 1, 39, 2); + Monom monom2(34, 2, 3, 4); + // Assert + EXPECT_FALSE(monom1 < monom2); +} +TEST(TestMonomLib, add_monoms) { + // Arrange & Act + Monom monom1(23, 1, 5, 2); + Monom monom2(44, 1, 5, 2); + Monom result = monom1 + monom2; + // Assert + EXPECT_EQ(result.get_coefficient(), monom1.get_coefficient() + monom2.get_coefficient()); +} +TEST(TestMonomLib, add_monoms_with_exception) { + // Arrange & Act + Monom monom1(23, 1, 5, 2); + Monom monom2(44, 1, 55, 2); + // Assert + ASSERT_THROW(monom1 + monom2, std::invalid_argument); +} +TEST(TestMonomLib, sub_monoms) { + // Arrange & Act + Monom monom1(33.9, 1, 5, 2); + Monom monom2(44, 1, 5, 2); + Monom result = monom1 - monom2; + // Assert + EXPECT_EQ(result.get_coefficient(), monom1.get_coefficient() - monom2.get_coefficient()); +} +TEST(TestMonomLib, sub_monoms_with_exception) { + // Arrange & Act + Monom monom1(23, 1, 5, 2); + Monom monom2(4.4, 1, 5, 772); + // Assert + ASSERT_THROW(monom1 - monom2, std::invalid_argument); +} +TEST(TestMonomLib,mult_monoms) { + // Arrange & Act + Monom monom1(23.8, 33, 5, 2); + Monom monom2(44, 2, 4555, 7); + Monom result = monom1 * monom2; + // Assert + EXPECT_EQ(result.get_coefficient(), monom1.get_coefficient() * monom2.get_coefficient()); + EXPECT_EQ(result.powerX(), monom1.powerX() + monom2.powerX()); + EXPECT_EQ(result.powerY(), monom1.powerY() + monom2.powerY()); + EXPECT_EQ(result.powerZ(), monom1.powerZ() + monom2.powerZ()); +} +TEST(TestMonomLib, div_monoms) { + // Arrange & Act + Monom monom1(23.9, 33, 4555, 22); + Monom monom2(33.3, 2, 5, 7); + Monom result = monom1 / monom2; + // Assert + EXPECT_EQ(result.get_coefficient(), monom1.get_coefficient() / monom2.get_coefficient()); + EXPECT_EQ(result.powerX(), monom1.powerX() - monom2.powerX()); + EXPECT_EQ(result.powerY(), monom1.powerY() - monom2.powerY()); + EXPECT_EQ(result.powerZ(), monom1.powerZ() - monom2.powerZ()); +} +TEST(TestMonomLib, div_monoms_with_exception) { + // Arrange & Act + Monom monom1(25.9, 2, 3, 1); + Monom monom2(3.3, 3, 2, 1); + // Assert + ASSERT_THROW(monom1 / monom2, std::invalid_argument); +} +TEST(TestMonomLib, monom_mult_value) { + // Arrange & Act + Monom monom(223.39, 33, 4555, 22); + double value = 22.5; + Monom result = monom * value; + // Assert + EXPECT_EQ(result.get_coefficient(), monom.get_coefficient() * value); +} +TEST(TestMonomLib, monom_div_value) { + // Arrange & Act + Monom monom(223.39, 33, 4555, 22); + double value = 223.5; + Monom result = monom / value; + // Assert + EXPECT_EQ(result.get_coefficient(), monom.get_coefficient() / value); +} +TEST(TestMonomLib, monom_div_value_with_exception) { + // Arrange & Act + Monom monom(223.39, 333, 4, 2); + double value = 0.0; + // Assert + ASSERT_THROW(monom / value, std::invalid_argument); +} +TEST(TestMonomLib, plus_equals_operator) { + // Arrange & Act + Monom monom1(23, 1, 5, 2); + Monom monom2(44, 1, 5, 2); + monom1 += monom2; + // Assert + EXPECT_EQ(monom1.get_coefficient(), 67); + EXPECT_EQ(monom1.powerX(), 1); + EXPECT_EQ(monom1.powerY(), 5); + EXPECT_EQ(monom1.powerZ(), 2); +} +TEST(TestMonomLib, plus_equals_operator_with_exception) { + // Arrange & Act + Monom monom1(23, 1, 5, 2); + Monom monom2(44, 1, 55, 2); + // Assert + ASSERT_THROW(monom1 += monom2, std::invalid_argument); +} +TEST(TestMonomLib, minus_equals_operator) { + // Arrange & Act + Monom monom1(50, 3, 2, 1); + Monom monom2(30, 3, 2, 1); + monom1 -= monom2; + // Assert + EXPECT_EQ(monom1.get_coefficient(), 20); + EXPECT_EQ(monom1.powerX(), 3); + EXPECT_EQ(monom1.powerY(), 2); + EXPECT_EQ(monom1.powerZ(), 1); +} +TEST(TestMonomLib, minus_equals_operator_with_exception) { + // Arrange & Act + Monom monom1(50, 3, 2, 1); + Monom monom2(30, 3, 2, 11); + // Assert + ASSERT_THROW(monom1 -= monom2, std::invalid_argument); +} +TEST(TestMonomLib, multiply_equals_monom_operator) { + // Arrange & Act + Monom monom1(2, 3, 2, 1); + Monom monom2(3, 1, 2, 3); + monom1 *= monom2; + // Assert + EXPECT_EQ(monom1.get_coefficient(), 6); + EXPECT_EQ(monom1.powerX(), 4); + EXPECT_EQ(monom1.powerY(), 4); + EXPECT_EQ(monom1.powerZ(), 4); +} +TEST(TestMonomLib, multiply_equals_scalar_operator) { + // Arrange & Act + Monom monom(5, 2, 3, 1); + double value = 3.5; + monom *= value; + // Assert + EXPECT_EQ(monom.get_coefficient(), 17.5); + EXPECT_EQ(monom.powerX(), 2); + EXPECT_EQ(monom.powerY(), 3); + EXPECT_EQ(monom.powerZ(), 1); +} +TEST(TestMonomLib, divide_equals_monom_operator) { + // Arrange & Act + Monom monom1(12, 4, 3, 2); + Monom monom2(3, 1, 1, 1); + monom1 /= monom2; + // Assert + EXPECT_EQ(monom1.get_coefficient(), 4); + EXPECT_EQ(monom1.powerX(), 3); + EXPECT_EQ(monom1.powerY(), 2); + EXPECT_EQ(monom1.powerZ(), 1); +} +TEST(TestMonomLib, divide_equals_monom_operator_with_exception_division_by_zero) { + // Arrange & Act + Monom monom1(12, 4, 3, 2); + Monom monom2(0, 1, 1, 1); + // Assert + ASSERT_THROW(monom1 /= monom2, std::invalid_argument); +} +TEST(TestMonomLib, divide_equals_monom_operator_with_exception_negative_power) { + // Arrange & Act + Monom monom1(12, 1, 2, 3); + Monom monom2(3, 2, 1, 1); + // Assert + ASSERT_THROW(monom1 /= monom2, std::invalid_argument); +} +TEST(TestMonomLib, divide_equals_scalar_operator) { + // Arrange & Act + Monom monom(15, 2, 3, 1); + double value = 3.0; + monom /= value; + // Assert + EXPECT_EQ(monom.get_coefficient(), 5); + EXPECT_EQ(monom.powerX(), 2); + EXPECT_EQ(monom.powerY(), 3); + EXPECT_EQ(monom.powerZ(), 1); +} +TEST(TestMonomLib, divide_equals_scalar_operator_with_exception) { + // Arrange & Act + Monom monom(15, 2, 3, 1); + double value = 0.0; + // Assert + ASSERT_THROW(monom /= value, std::invalid_argument); +} +TEST(TestMonomLib, calculate_method) { + // Arrange & Act + Monom monom(2, 2, 1, 3); + double x = 3.0; + double y = 2.0; + double z = 1.0; + double result = monom.calculate(x, y, z); + // Assert + EXPECT_EQ(result, 36); +} +TEST(TestMonomLib, calculate_method_with_zero_powers) { + // Arrange & Act + Monom monom(5, 0, 0, 0); + double x = 10.0; + double y = 20.0; + double z = 30.0; + double result = monom.calculate(x, y, z); + // Assert + EXPECT_EQ(result, 5); +} +TEST(TestMonomLib, calculate_method_with_negative_coefficient) { + // Arrange & Act + Monom monom(-3, 1, 2, 0); + double x = 2.0; + double y = 3.0; + double z = 1.0; + double result = monom.calculate(x, y, z); + // Assert + EXPECT_EQ(result, -54); +} diff --git a/tests/test_polynom.cpp b/tests/test_polynom.cpp new file mode 100644 index 00000000..56c3a57b --- /dev/null +++ b/tests/test_polynom.cpp @@ -0,0 +1,302 @@ +// Copyright 2025 Julia Zabytina +#include +#include +#include "../lib_polynom/polynom.h" +const double TEST_EPSILON = 1e-10; +TEST(TestPolynomLib, polynom_default_constructor) { + // Arrange & Act + Polynom polynom; + // Assert + EXPECT_EQ(polynom.size(), 0); + EXPECT_TRUE(polynom.is_zero()); +} +TEST(TestPolynomLib, polynom_constructor_from_monom) { + // Arrange + Monom monom(22.3); + // Act + Polynom polynom(monom); + // Assert + EXPECT_EQ(polynom.size(), 1); + std::ostringstream oss; + oss << polynom; + EXPECT_EQ(oss.str(), "22.3"); +} +TEST(TestPolynomLib, polynom_constructor_from_monom_with_powers) { + // Arrange + Monom monom(2.5, 2, 1, 0); + // Act + Polynom polynom(monom); + // Assert + EXPECT_EQ(polynom.size(), 1); + std::ostringstream oss; + oss << polynom; + EXPECT_EQ(oss.str(), "2.5x^2y"); +} +TEST(TestPolynomLib, polynom_copy_constructor) { + // Arrange + Monom monom(3.14, 1, 1, 0); + Polynom original(monom); + // Act + Polynom copy(original); + // Assert + EXPECT_EQ(original.size(), copy.size()); + std::ostringstream oss_original, oss_copy; + oss_original << original; + oss_copy << copy; + EXPECT_EQ(oss_original.str(), oss_copy.str()); +} +TEST(TestPolynomLib, polynom_assignment_operator) { + // Arrange + Monom monom1(10.2, 1, 3, 8); + Monom monom2(5.5, 2, 1, 0); + Polynom original(monom1); + Polynom other(monom2); + // Act + other = original; + // Assert + EXPECT_EQ(original.size(), other.size()); + std::ostringstream oss_original, oss_other; + oss_original << original; + oss_other << other; + EXPECT_EQ(oss_original.str(), oss_other.str()); +} +TEST(TestPolynomLib, polynom_self_assignment) { + // Arrange + Monom monom(10.2, 1, 3, 8); + Polynom polynom(monom); + std::ostringstream before; + before << polynom; + // Act + polynom = polynom; + // Assert + std::ostringstream after; + after << polynom; + EXPECT_EQ(before.str(), after.str()); +} +TEST(TestPolynomLib, polynom_add_polynom) { + // Arrange + Monom monom1(1.2, 1, 3, 8); + Polynom polynom1(monom1); + Monom monom2(102.12, 1, 4, 2); + Polynom polynom2(monom2); + // Act + Polynom result; + result = polynom1 + polynom2; + // Assert + EXPECT_EQ(result.size(), 2); + std::ostringstream oss; + oss << result; + EXPECT_EQ(oss.str(), "1.2xy^3z^8 + 102.12xy^4z^2"); +} +TEST(TestPolynomLib, polynom_sub_polynom) { + // Arrange + Monom monom1(211.2, 1, 3, 8); + Polynom polynom1(monom1); + Monom monom2(33.33, 1, 4, 2); + Polynom polynom2(monom2); + // Act + Polynom result; + result = polynom1 - polynom2; + // Assert + EXPECT_EQ(result.size(), 2); + std::ostringstream oss; + oss << result; + EXPECT_EQ(oss.str(), "211.2xy^3z^8 - 33.33xy^4z^2"); +} +TEST(TestPolynomLib, polynom_mult_polynom) { + // Arrange + Monom monom1(77.2, 22, 3, 8); + Polynom polynom1(monom1); + Monom monom2(10, 1, 49, 2); + Polynom polynom2(monom2); + // Act + Polynom result; + result = polynom1 * polynom2; + // Assert + EXPECT_EQ(result.size(), 1); + std::ostringstream oss; + oss << result; + EXPECT_EQ(oss.str(), "772x^23y^52z^10"); +} +TEST(TestPolynomLib, polynom_add_assign_polynom) { + // Arrange + Monom monom1(1.2, 1, 3, 8); + Polynom polynom1(monom1); + Monom monom2(102.12, 1, 4, 2); + Polynom polynom2(monom2); + // Act + polynom1 += polynom2; + // Assert + EXPECT_EQ(polynom1.size(), 2); + std::ostringstream oss; + oss << polynom1; + EXPECT_EQ(oss.str(), "1.2xy^3z^8 + 102.12xy^4z^2"); +} +TEST(TestPolynomLib, polynom_sub_assign_polynom) { + // Arrange + Monom monom1(211.2, 1, 3, 8); + Polynom polynom1(monom1); + Monom monom2(33.33, 1, 4, 2); + Polynom polynom2(monom2); + // Act + polynom1 -= polynom2; + // Assert + EXPECT_EQ(polynom1.size(), 2); + std::ostringstream oss; + oss << polynom1; + EXPECT_EQ(oss.str(), "211.2xy^3z^8 - 33.33xy^4z^2"); +} +TEST(TestPolynomLib, polynom_mult_assign_polynom) { + // Arrange + Monom monom1(77.2, 22, 3, 8); + Polynom polynom1(monom1); + Monom monom2(10, 1, 49, 2); + Polynom polynom2(monom2); + // Act + polynom1 *= polynom2; + // Assert + EXPECT_EQ(polynom1.size(), 1); + std::ostringstream oss; + oss << polynom1; + EXPECT_EQ(oss.str(), "772x^23y^52z^10"); +} +TEST(TestPolynomLib, polynom_add_monom) { + // Arrange + Monom monom1(1.2, 4, 4, 8); + Polynom polynom(monom1); + Monom monom2(66.8, 1, 4, 4); + // Act + Polynom result; + result = polynom + monom2; + // Assert + EXPECT_EQ(result.size(), 2); + std::ostringstream oss; + oss << result; + EXPECT_EQ(oss.str(), "1.2x^4y^4z^8 + 66.8xy^4z^4"); +} +TEST(TestPolynomLib, polynom_sub_monom) { + // Arrange + Monom monom1(2233.4, 1, 2, 8); + Polynom polynom(monom1); + Monom monom2(99.9, 2, 2, 2); + // Act + Polynom result; + result = polynom - monom2; + // Assert + EXPECT_EQ(result.size(), 2); + std::ostringstream oss; + oss << result; + EXPECT_EQ(oss.str(), "2233.4xy^2z^8 - 99.9x^2y^2z^2"); +} +TEST(TestPolynomLib, polynom_mult_monom) { + // Arrange + Polynom polynom("2x^2 + 3y"); + Monom monom(4, 1, 0, 0); + // Act + Polynom result = polynom * monom; + // Assert + std::ostringstream oss; + oss << result; + EXPECT_EQ(oss.str(), "8x^3 + 12xy"); + EXPECT_EQ(result.size(), 2); +} +TEST(TestPolynomLib, polynom_mult_monom_with_zero_power) { + // Arrange + Polynom polynom("5x^2 + 2y^3 + 7"); + Monom monom(3, 0, 0, 0); + // Act + Polynom result = polynom * monom; + // Assert + std::ostringstream oss; + oss << result; + EXPECT_EQ(oss.str(), "15x^2 + 6y^3 + 21"); + EXPECT_EQ(result.size(), 3); +} +TEST(TestPolynomLib, polynom_mult_monom_negative_coefficient) { + // Arrange + Polynom polynom("4x^2 - 2y"); + Monom monom(-3, 1, 0, 0); + // Act + Polynom result = polynom * monom; + // Assert + std::ostringstream oss; + oss << result; + EXPECT_EQ(oss.str(), "-12x^3 + 6xy"); + EXPECT_EQ(result.size(), 2); +} +TEST(TestPolynomLib, polynom_add_assign_monom) { + // Arrange + Monom monom1(1.2, 4, 4, 8); + Polynom polynom(monom1); + Monom monom2(66.8, 1, 4, 4); + // Act + polynom += monom2; + // Assert + EXPECT_EQ(polynom.size(), 2); + std::ostringstream oss; + oss << polynom; + EXPECT_EQ(oss.str(), "1.2x^4y^4z^8 + 66.8xy^4z^4"); +} +TEST(TestPolynomLib, polynom_sub_assign_monom) { + // Arrange + Monom monom1(2233.4, 1, 2, 8); + Polynom polynom(monom1); + Monom monom2(99.9, 2, 2, 2); + // Act + polynom -= monom2; + // Assert + EXPECT_EQ(polynom.size(), 2); + std::ostringstream oss; + oss << polynom; + EXPECT_EQ(oss.str(), "2233.4xy^2z^8 - 99.9x^2y^2z^2"); +} +TEST(TestPolynomLib, polynom_mult_assign_monom) { + // Arrange + Polynom polynom("2x^2 + 3y"); + Monom monom(4, 1, 0, 0); + // Act + polynom *= monom; + // Assert + std::ostringstream oss; + oss << polynom; + EXPECT_EQ(oss.str(), "8x^3 + 12xy"); +} +TEST(TestPolynomLib, polynom_unary_minus) { + // Arrange + Polynom polynom("22.4xy^2z^8 - 99.9x^2y^2z^2 + 33.7y^3z"); + // Act + polynom = -polynom; + // Assert + EXPECT_EQ(polynom.size(), 3); + std::ostringstream oss; + oss << polynom; + EXPECT_EQ(oss.str(), "-22.4xy^2z^8 + 99.9x^2y^2z^2 - 33.7y^3z"); +} +TEST(TestPolynomLib, polynom_calculate) { + // Arrange + Polynom polynom("2x + 3y - 4z"); + // Act + double result = polynom.calculate(5, 7, 2); + // Assert + EXPECT_EQ(result, 23); +} +TEST(TestPolynomLib, polynom_calculate_very_large) { + // Arrange + Polynom polynom("10x^5y^3 - 7x^2y^4z + 3yz^5"); + // Act + double result = polynom.calculate(5, 4, 3); + // Assert + EXPECT_EQ(result, 1868516); +} +TEST(TestPolynomLib, polynom_is_zero_expect_true) { + // Arrange + Polynom polynom; + // Act & Assert + EXPECT_TRUE(polynom.is_zero()); +} +TEST(TestPolynomLib, polynom_is_zero_expect_false) { + // Arrange + Polynom polynom("2x + 32.3y - 4z^5"); + // Act & Assert + EXPECT_FALSE(polynom.is_zero()); +} diff --git a/tests/test_queue.cpp b/tests/test_queue.cpp new file mode 100644 index 00000000..0254f45b --- /dev/null +++ b/tests/test_queue.cpp @@ -0,0 +1,173 @@ +// Copyright 2025 Zabytina Julia +#include +#include "../lib_queue/queue.h" +TEST(TestQueueLib, queue_constructor_with_size) { + // Arrange & Act + size_t size = 10; + Queue queue(size); + // Assert + EXPECT_EQ(queue.size(), size); + EXPECT_EQ(queue.count(), 0); + EXPECT_TRUE(queue.is_empty()); +} +TEST(TestQueueLib, queue_copy_constructor) { + // Arrange + size_t size = 5; + Queue queue1(size); + queue1.push(10); + queue1.push(20); + queue1.push(30); + // Act + Queue queue2(queue1); + // Assert + EXPECT_EQ(queue1.size(), queue2.size()); + EXPECT_EQ(queue1.count(), queue2.count()); + while (!queue1.is_empty()) { + EXPECT_EQ(queue1.head(), queue2.head()); + queue1.pop(); + queue2.pop(); + } +} +TEST(TestQueueLib, queue_is_empty_true) { + // Arrange & Act + Queue queue(10); + // Assert + EXPECT_TRUE(queue.is_empty()); +} +TEST(TestQueueLib, queue_is_empty_false) { + // Arrange + size_t size = 3; + Queue queue(size); + // Act + queue.push(10); + // Assert + EXPECT_FALSE(queue.is_empty()); +} +TEST(TestQueueLib, queue_is_full_true) { + // Arrange + size_t size = 3; + Queue queue(size); + // Act + queue.push(30); + queue.push(240); + queue.push(190); + // Assert + EXPECT_TRUE(queue.is_full()); +} +TEST(TestQueueLib, queue_is_full_false) { + // Arrange + size_t size = 5; + Queue queue(size); + // Act + queue.push(10); + queue.push(30); + // Assert + EXPECT_FALSE(queue.is_full()); +} +TEST(TestQueueLib, queue_get_head) { + // Arrange + size_t size = 6; + Queue queue(size); + // Act + queue.push(10); + queue.push(20); + queue.push(30); + // Assert + EXPECT_EQ(queue.head(), 10); +} +TEST(TestQueueLib, queue_get_tail) { + // Arrange + size_t size = 6; + Queue queue(size); + // Act + queue.push(70); + queue.push(230); + queue.push(50); + // Assert + EXPECT_EQ(queue.tail(), 50); +} +TEST(TestQueueLib, queue_empty_get_head_exception) { + // Arrange & Act + size_t size = 5; + Queue queue(size); + // Assert + ASSERT_THROW(queue.head(), std::runtime_error); +} +TEST(TestQueueLib, queue_empty_get_tail_exception) { + // Arrange & Act + size_t size = 9; + Queue queue(size); + // Assert + ASSERT_THROW(queue.tail(), std::runtime_error); +} +TEST(TestQueueLib, queue_circular_behavior) { + // Arrange + Queue queue(3); + // Act + queue.push(1); + queue.push(2); + queue.push(3); + queue.pop(); + queue.push(4); + // Assert + EXPECT_EQ(queue.head(), 2); + EXPECT_EQ(queue.tail(), 4); +} +TEST(TestQueueLib, queue_push) { + // Arrange + Queue queue(5); + // Act + queue.push(22); + queue.push(44); + queue.push(77); + // Assert + EXPECT_EQ(queue.head(), 22); + EXPECT_EQ(queue.tail(), 77); + EXPECT_EQ(queue.count(), 3); +} +TEST(TestQueueLib, queue_pop) { + // Arrange + Queue queue(8); + // Act + queue.push(88); + queue.push(54); + queue.push(27); + queue.pop(); + queue.pop(); + // Assert + EXPECT_EQ(queue.head(), queue.tail()); + EXPECT_EQ(queue.head(), 27); + EXPECT_EQ(queue.count(), 1); +} +TEST(TestQueueLib, queue_push_exception) { + // Arrange + Queue queue(3); + // Act + queue.push(20); + queue.push(11); + queue.push(37); + // Assert + ASSERT_THROW(queue.push(10), std::logic_error); +} +TEST(TestQueueLib, queue_pop_exception) { + // Arrange & Act + Queue queue(10); + // Assert + ASSERT_THROW(queue.pop(), std::logic_error); +} +TEST(TestQueueLib, queue_clear) { + // Arrange + Queue queue(10); + queue.push(88); + queue.push(44); + queue.push(57); + queue.push(25); + queue.push(41); + queue.push(20); + queue.push(3); + queue.push(9); + // Act + queue.clear(); + // Assert + EXPECT_EQ(queue.count(), 0); +} diff --git a/tests/test_queue_on_list.cpp b/tests/test_queue_on_list.cpp new file mode 100644 index 00000000..34d10bbc --- /dev/null +++ b/tests/test_queue_on_list.cpp @@ -0,0 +1,236 @@ +// Copyright 2025 Julia Zabytina +#include +#include +#include "../lib_queue_on_list/queue_on_list.h" + +TEST(TestQueueOnListLib, queue_constructor_with_size) { + // Arrange & Act + size_t max_size = 10; + QueueOnList queue(max_size); + // Assert + EXPECT_EQ(queue.max_size(), max_size); + EXPECT_EQ(queue.size(), 0); + EXPECT_TRUE(queue.is_empty()); +} +TEST(TestQueueOnListLib, queue_constructor_with_size_default) { + // Arrange & Act + QueueOnList queue; + // Assert + EXPECT_EQ(queue.size(), 0); + EXPECT_FALSE(queue.has_max_size()); + EXPECT_TRUE(queue.is_empty()); +} +TEST(TestQueueOnListLib, queue_copy_constructor) { + // Arrange + size_t max_size = 5; + QueueOnList queue1(max_size); + queue1.push(5); + queue1.push(6); + queue1.push(7); + // Act + QueueOnList queue2(queue1); + // Assert + EXPECT_EQ(queue1.max_size(), queue2.max_size()); + EXPECT_EQ(queue1.size(), queue2.size()); + while (!queue1.is_empty()) { + EXPECT_EQ(queue1.head(), queue2.head()); + queue1.pop(); + queue2.pop(); + } +} +TEST(TestQueueOnListLib, queue_is_empty_true) { + // Arrange & Act + QueueOnList queue; + // Assert + EXPECT_TRUE(queue.is_empty()); +} +TEST(TestQueueOnListLib, queue_is_empty_false) { + // Arrange + size_t max_size = 3; + QueueOnList queue(max_size); + // Act + queue.push(5); + // Assert + EXPECT_FALSE(queue.is_empty()); +} +TEST(TestQueueOnListLib, queue_is_full_true) { + // Arrange + size_t max_size = 3; + QueueOnList queue(max_size); + // Act + queue.push(30); + queue.push(22); + queue.push(12); + // Assert + EXPECT_TRUE(queue.is_full()); +} +TEST(TestQueueOnListLib, queue_is_full_false) { + // Arrange + size_t max_size = 5; + QueueOnList queue(max_size); + // Act + queue.push(1); + queue.push(3); + // Assert + EXPECT_FALSE(queue.is_full()); +} +TEST(TestQueueOnListLib, queue_get_head) { + // Arrange + size_t max_size = 6; + QueueOnList queue(max_size); + // Act + queue.push(10); + queue.push(23); + queue.push(30); + // Assert + EXPECT_EQ(queue.head(), 10); +} +TEST(TestQueueOnListLib, queue_get_tail) { + // Arrange + size_t max_size = 6; + QueueOnList queue(max_size); + // Act + queue.push(70); + queue.push(5); + queue.push(50); + // Assert + EXPECT_EQ(queue.tail(), 50); +} +TEST(TestQueueOnListLib, queue_empty_get_head_exception) { + // Arrange & Act + QueueOnList queue; + // Assert + ASSERT_THROW(queue.head(), std::runtime_error); +} +TEST(TestQueueOnListLib, queue_empty_get_tail_exception) { + // Arrange & Act + size_t max_size = 10; + QueueOnList queue(max_size); + // Assert + ASSERT_THROW(queue.tail(), std::runtime_error); +} +TEST(TestQueueOnListLib, queue_push) { + // Arrange + QueueOnList queue(5); + // Act + queue.push(22); + queue.push(55); + queue.push(77); + // Assert + EXPECT_EQ(queue.head(), 22); + EXPECT_EQ(queue.tail(), 77); + EXPECT_EQ(queue.size(), 3); +} +TEST(TestQueueOnListLib, queue_pop) { + // Arrange + QueueOnList queue(8); + // Act + queue.push(22); + queue.push(34); + queue.push(27); + queue.pop(); + queue.pop(); + // Assert + EXPECT_EQ(queue.head(), queue.tail()); + EXPECT_EQ(queue.head(), 27); + EXPECT_EQ(queue.size(), 1); +} +TEST(TestQueueOnListLib, queue_push_exception) { + // Arrange + QueueOnList queue(3); + // Act + queue.push(20); + queue.push(10); + queue.push(30); + // Assert + ASSERT_THROW(queue.push(9), std::logic_error); +} +TEST(TestQueueOnListLib, queue_pop_exception) { + // Arrange & Act + QueueOnList queue(10); + // Assert + ASSERT_THROW(queue.pop(), std::logic_error); +} +TEST(TestQueueOnListLib, queue_clear) { + // Arrange + QueueOnList queue(10); + queue.push(2); + queue.push(76); + queue.push(34); + queue.push(25); + queue.push(1); + queue.push(3); + queue.push(4); + queue.push(5); + // Act + queue.clear(); + // Assert + EXPECT_TRUE(queue.is_empty()); + EXPECT_EQ(queue.max_size(), 10); +} +TEST(TestQueueOnListLib, queue_operator_assign) { + // Arrange + QueueOnList queue1(10); + queue1.push(2); + queue1.push(3); + queue1.push(4); + QueueOnList queue2(5); + queue2.push(10); + queue2.push(20); + // Act + queue1 = queue2; + // Assert + EXPECT_EQ(queue1.max_size(), 5); + EXPECT_EQ(queue1.size(), queue2.size()); + EXPECT_TRUE(queue1 == queue2); +} +TEST(TestQueueOnListLib, queue_operator_equal_true) { + // Arrange & Act + QueueOnList queue1; + queue1.push(2); + queue1.push(3); + queue1.push(4); + QueueOnList queue2; + queue2.push(2); + queue2.push(3); + queue2.push(4); + // Assert + EXPECT_TRUE(queue1 == queue2); +} +TEST(TestQueueOnListLib, queue_operator_equal_false) { + // Arrange & Act + QueueOnList queue1; + queue1.push(2); + queue1.push(3); + queue1.push(4); + QueueOnList queue2; + queue2.push(2); + queue2.push(4); + queue2.push(4); + // Assert + EXPECT_FALSE(queue1 == queue2); +} +TEST(TestQueueOnListLib, queue_operator_not_equal_true) { + // Arrange & Act + QueueOnList queue1; + queue1.push(2); + queue1.push(3); + queue1.push(4); + QueueOnList queue2; + queue2.push(10); + // Assert + EXPECT_TRUE(queue1 != queue2); +} +TEST(TestQueueOnListLib, queue_operator_not_equal_false) { + // Arrange & Act + QueueOnList queue1; + queue1.push(2); + queue1.push(2); + queue1.push(2); + QueueOnList queue2; + queue2.push(2); + queue2.push(2); + queue2.push(2); + // Assert + EXPECT_FALSE(queue1 != queue2); +} diff --git a/tests/test_stack.cpp b/tests/test_stack.cpp new file mode 100644 index 00000000..f67cbdde --- /dev/null +++ b/tests/test_stack.cpp @@ -0,0 +1,167 @@ +// Copyright 2025 Julia Zabytina +#include +#include +#include "../lib_stack/stack.h" + +TEST(TestStackLib, stack_constructor_with_size) { + // Arrange & Act + size_t size = 10; + Stack stack(size); + // Assert + EXPECT_EQ(stack.getData().get_size(), size); + EXPECT_EQ(stack.getData().get_capacity(), size+15); +} +TEST(TestStackLib, stack_copy_constructor) { + // Arrange & Act + size_t size = 10; + Stack stack1(size); + Stack stack2(stack1); + // Assert + EXPECT_TRUE(stack1 == stack2); +} +TEST(TestStackLib, stack_push_element) { + // Arrange + size_t size = 10; + int element = 100; + Stack stack(size); + // Act + stack.push(element); + // Assert + EXPECT_EQ(stack.top(), element); +} +TEST(TestStackLib, stack_push_element_with_exception) { + // Arrange + size_t size = 0; + int element = 100; + Stack stack(size); + // Act + for (size_t i = 0; i < 15; ++i) { + stack.push(element); + } + // Assert + EXPECT_THROW(stack.push(element), std::logic_error); +} +TEST(TestStackLib, stack_pop_element_with_exception) { + // Arrange & Act + size_t size = 0; + Stack stack(size); + // Assert + EXPECT_THROW(stack.pop(), std::logic_error); +} +TEST(TestStackLib, stack_pop_element) { + // Arrange + size_t size = 10; + int element1 = 100; + int element2 = 200; + int element3 = 300; + Stack stack(size); + // Act + stack.push(element1); + stack.push(element2); + stack.push(element3); + stack.pop(); + // Assert + EXPECT_EQ(stack.top(), element2); +} +TEST(TestStackLib, stack_is_full) { + // Arrange + size_t size = 0; + int element = 300; + Stack stack(size); + // Act + for (size_t i = 0; i < 15; ++i) { + stack.push(element); + } + // Assert + EXPECT_TRUE(stack.is_full()); +} +TEST(TestStackLib, stack_is_empty) { + // Arrange + size_t size = 0; + Stack stack(size); + // Assert & Act + EXPECT_TRUE(stack.is_empty()); +} +TEST(TestStackLib, stack_clear) { + // Arrange + size_t size = 0; + int element = 300; + + Stack stack(size); + // Act + for (size_t i = 0; i < 15; ++i) { + stack.push(element); + } + stack.clear(); + // Assert + EXPECT_TRUE(stack.is_empty()); +} +TEST(TestStackLib, stack_top) { + // Arrange + size_t size = 0; + int common_element = 100; + int last_element = 999; + Stack stack(size); + // Act + for (size_t i = 0; i < 14; ++i) { + stack.push(common_element); + } + stack.push(last_element); + // Assert + EXPECT_EQ(stack.top(), last_element); +} +TEST(TestStackLib, stack_top_with_exception) { + // Arrange & Act + size_t size = 0; + Stack stack(size); + // Assert + EXPECT_THROW(stack.top(), std::logic_error); +} +TEST(TestStackLib, stack_operator_compare_expect_true) { + // Arrange & Act + size_t size = 10; + Stack stack(size); + Stack stack_other(size); + // Assert + EXPECT_TRUE(stack == stack_other); +} +TEST(TestStackLib, stack_operator_compare_expect_false) { + // Arrange & Act + size_t size1 = 10; + size_t size2 = 20; + Stack stack(size1); + Stack stack_other(size2); + // Assert + EXPECT_FALSE(stack == stack_other); +} +TEST(TestStackLib, stack_operator_assign) { + //Arrange + size_t size1 = 10; + size_t size2 = 20; + Stack stack(size1); + Stack stack_other(size2); + //Act + stack_other.push(100); + stack_other.push(200); + stack = stack_other; + //Assert + EXPECT_TRUE(stack == stack_other); + EXPECT_EQ(stack.top(), 200); +} +TEST(TestStackLib, stack_operator_not_compare_expect_true) { + // Arrange & Act + size_t size = 10; + Stack stack(size); + Stack stack_other(size); + // Assert + EXPECT_FALSE(stack != stack_other); +} +TEST(TestStackLib, stack_operator_not_compare_expect_false) { + // Arrange & Act + size_t size1 = 10; + size_t size2 = 20; + Stack stack(size1); + Stack stack_other(size2); + // Assert + EXPECT_TRUE(stack != stack_other); +} diff --git a/tests/test_stack_on_list.cpp b/tests/test_stack_on_list.cpp new file mode 100644 index 00000000..d7c4ed4d --- /dev/null +++ b/tests/test_stack_on_list.cpp @@ -0,0 +1,174 @@ +// Copyright 2025 Julia Zabytina +#include +#include "../lib_stack_on_list/stack_on_list.h" + +TEST(TestStackOnListLib, stack_constructor_with_size_default) { + // Arrange & Act + StackOnList stack; + // Assert + EXPECT_EQ(stack.size(), 0); + EXPECT_FALSE(stack.has_max_size()); + EXPECT_TRUE(stack.is_empty()); +} +TEST(TestStackOnListLib, stack_constructor_with_size) { + // Arrange & Act + size_t max_size = 10; + StackOnList stack(max_size); + // Assert + EXPECT_EQ(stack.max_size(), max_size); + EXPECT_EQ(stack.size(), 0); + EXPECT_TRUE(stack.is_empty()); +} +TEST(TestStackOnListLib, stack_copy_constructor) { + // Arrange + size_t max_size = 5; + StackOnList stack1(max_size); + stack1.push(5); + stack1.push(6); + stack1.push(7); + // Act + StackOnList stack2(stack1); + // Assert + EXPECT_EQ(stack1.max_size(), stack2.max_size()); + EXPECT_EQ(stack1.size(), stack2.size()); + while (!stack1.is_empty()) { + EXPECT_EQ(stack1.top(), stack2.top()); + stack1.pop(); + stack2.pop(); + } +} +TEST(TestStackOnListLib, stack_is_empty_true) { + // Arrange & Act + StackOnList stack; + // Assert + EXPECT_TRUE(stack.is_empty()); +} +TEST(TestStackOnListLib, stack_is_empty_false) { + // Arrange + size_t max_size = 5; + StackOnList stack(max_size); + // Act + stack.push(10); + // Assert + EXPECT_FALSE(stack.is_empty()); +} +TEST(TestStackOnListLib, stack_is_full_true) { + // Arrange + size_t max_size = 3; + StackOnList stack(max_size); + // Act + stack.push(4); + stack.push(3); + stack.push(7); + // Assert + EXPECT_TRUE(stack.is_full()); +} +TEST(TestStackOnListLib, stack_is_full_false) { + // Arrange + size_t max_size = 7; + StackOnList stack(max_size); + // Act + stack.push(1); + stack.push(9); + // Assert + EXPECT_FALSE(stack.is_full()); +} +TEST(TestStackOnListLib, stack_push_element) { + // Arrange + int element = 55; + StackOnList stack; + // Act + stack.push(element); + // Assert + EXPECT_EQ(stack.top(), element); +} +TEST(TestStackOnListLib, stack_push_element_with_exception) { + // Arrange + size_t max_size = 1; + int element = 100; + StackOnList stack(max_size); + // Act + stack.push(element); + // Assert + EXPECT_THROW(stack.push(200), std::logic_error); +} +TEST(TestStackOnListLib, stack_pop_element_with_exception) { + // Arrange & Act + StackOnList stack; + // Assert + EXPECT_THROW(stack.pop(), std::logic_error); +} +TEST(TestStackOnListLib, stack_pop_element) { + // Arrange + int element1 = 100; + int element2 = 200; + int element3 = 300; + StackOnList stack; + // Act + stack.push(element1); + stack.push(element2); + stack.push(element3); + stack.pop(); + // Assert + EXPECT_EQ(stack.size(), 2); + EXPECT_EQ(stack.top(), element2); +} +TEST(TestStackOnListLib, stack_clear) { + // Arrange + int element = 300; + StackOnList stack; + // Act + for (size_t i = 0; i < 15; ++i) { + stack.push(element); + } + stack.clear(); + // Assert + EXPECT_TRUE(stack.is_empty()); +} +TEST(TestStackOnListLib, stack_operator_equall_expect_true) { + // Arrange & Act + StackOnList stack; + StackOnList stack_other; + // Assert + EXPECT_TRUE(stack == stack_other); +} +TEST(TestStackOnListLib, stack_operator_equall_expect_false) { + // Arrange & Act + StackOnList stack; + stack.push(10); + StackOnList stack_other; + stack_other.push(20); + stack_other.push(25); + // Assert + EXPECT_FALSE(stack == stack_other); +} +TEST(TestStackOnListLib, stack_operator_assign) { + //Arrange + StackOnList stack; + StackOnList stack_other; + //Act + stack_other.push(100); + stack_other.push(200); + stack = stack_other; + //Assert + EXPECT_TRUE(stack == stack_other); +} +TEST(TestStackOnListLib, stack_operator_not_equal_expect_true) { + // Arrange & Act + StackOnList stack; + stack.push(100); + StackOnList stack_other; + stack_other.push(20); + stack_other.push(35); + // Assert + EXPECT_TRUE(stack != stack_other); +} +TEST(TestStackOnListLib, stack_operator_not_equal_expect_false) { + // Arrange & Act + StackOnList stack; + stack.push(20); + StackOnList stack_other; + stack_other.push(20); + // Assert + EXPECT_FALSE(stack != stack_other); +} diff --git a/tests/test_triangle_matrix.cpp b/tests/test_triangle_matrix.cpp new file mode 100644 index 00000000..560a8c4b --- /dev/null +++ b/tests/test_triangle_matrix.cpp @@ -0,0 +1,364 @@ +//Copyright 2025 Julia Zabytina +#include +#include +#include "../lib_triangle_matrix/triangle_matrix.h" +TEST(TestTriangleMatrixLib, tr_matrix_default_constructor) { + // Arrange & Act + TriangleMatrix matrix; + // Assert + EXPECT_EQ(0, matrix.getSize()); + EXPECT_TRUE(matrix.is_empty()); +} +TEST(TestTriangleMatrixLib, tr_matrix_constructor_with_size) { + // Arrange & Act + size_t size = 4; + TriangleMatrix matrix(size); + // Assert + EXPECT_EQ(size, matrix.getSize()); +} +TEST(TestTriangleMatrixLib, tr_matrix_constructor_with_array_and_size) { + // Arrange & Act + size_t size = 3; + int data[6] = { 1, 2, 3, 4, 5, 6 }; + TriangleMatrix matrix(data, size); + // Assert + EXPECT_EQ(size, matrix.getSize()); + EXPECT_EQ(matrix.at(0).at(0), 1); + EXPECT_EQ(matrix.at(0).at(1), 2); + EXPECT_EQ(matrix.at(0).at(2), 3); + EXPECT_EQ(matrix.at(1).at(1), 4); + EXPECT_EQ(matrix.at(1).at(2), 5); + EXPECT_EQ(matrix.at(2).at(2), 6); + EXPECT_THROW(matrix.at(1).at(0), std::logic_error); + EXPECT_THROW(matrix.at(2).at(0), std::logic_error); + EXPECT_THROW(matrix.at(2).at(1), std::logic_error); +} +TEST(TestTriangleMatrixLib, tr_matrix_copy_constructor) { + // Arrange & Act + size_t size = 3; + int data[6] = { 1, 2, 3, 4, 5, 6 }; + TriangleMatrix matrix1(data, size); + TriangleMatrix matrix2(matrix1); + // Assert + EXPECT_EQ(matrix1, matrix2); +} +TEST(TestTriangleMatrixLib, tr_matrix_operator_assignment) { + // Arrange & Act + size_t size = 3; + int data[6] = { 1, 2, 3, 4, 5, 6 }; + TriangleMatrix matrix1(data, size); + TriangleMatrix matrix2; + matrix2 = matrix1; + // Assert + EXPECT_EQ(matrix1, matrix2); +} +TEST(TestTriangleMatrixLib, tr_matrix_add_value) { + // Arrange + size_t size = 3; + int data[6] = { 1, 2, 3, 4, 5, 6 }; + int value = 10; + TriangleMatrix matrix(data, size); + TriangleMatrix result(size); + //Act + result = matrix + value; + // Assert + EXPECT_EQ(result.at(0).at(0), 11); + EXPECT_EQ(result.at(0).at(1), 12); + EXPECT_EQ(result.at(0).at(2), 13); + EXPECT_EQ(result.at(1).at(1), 14); + EXPECT_EQ(result.at(1).at(2), 15); + EXPECT_EQ(result.at(2).at(2), 16); +} +TEST(TestTriangleMatrixLib, tr_matrix_sub_value) { + // Arrange + size_t size = 3; + int data[6] = { 1, 2, 3, 4, 5, 6 }; + int value = 1; + TriangleMatrix matrix(data, size); + TriangleMatrix result(size); + //Act + result = matrix - value; + // Assert + EXPECT_EQ(result.at(0).at(0), 0); + EXPECT_EQ(result.at(0).at(1), 1); + EXPECT_EQ(result.at(0).at(2), 2); + EXPECT_EQ(result.at(1).at(1), 3); + EXPECT_EQ(result.at(1).at(2), 4); + EXPECT_EQ(result.at(2).at(2), 5); +} +TEST(TestTriangleMatrixLib, tr_matrix_mult_value) { + // Arrange + size_t size = 3; + int data[6] = { 1, 2, 3, 4, 5, 6 }; + int value = 10; + TriangleMatrix matrix(data, size); + TriangleMatrix result(size); + //Act + result = matrix * value; + // Assert + EXPECT_EQ(result.at(0).at(0), 10); + EXPECT_EQ(result.at(0).at(1), 20); + EXPECT_EQ(result.at(0).at(2), 30); + EXPECT_EQ(result.at(1).at(1), 40); + EXPECT_EQ(result.at(1).at(2), 50); + EXPECT_EQ(result.at(2).at(2), 60); +} +TEST(TestTriangleMatrixLib, tr_matrix_div_value) { + // Arrange + size_t size = 3; + int data[6] = { 2, 2, 4, 4, 8, 6 }; + int value = 2; + TriangleMatrix matrix(data, size); + TriangleMatrix result(size); + //Act + result = matrix / value; + // Assert + EXPECT_EQ(result.at(0).at(0), 1); + EXPECT_EQ(result.at(0).at(1), 1); + EXPECT_EQ(result.at(0).at(2), 2); + EXPECT_EQ(result.at(1).at(1), 2); + EXPECT_EQ(result.at(1).at(2), 4); + EXPECT_EQ(result.at(2).at(2), 3); +} +TEST(TestTriangleMatrixLib, tr_matrix_div_value_with_exception) { + // Arrange & Act + size_t size = 3; + int data[6] = { 2, 2, 4, 4, 8, 6 }; + size_t value = 0; + TriangleMatrix matrix(data, size); + // Assert + EXPECT_THROW(matrix / value, std::logic_error); +} +TEST(TestTriangleMatrixLib, tr_matrix_add_assign_value) { + // Arrange & Act + int size = 3; + int data[6] = { 2, 2, 4, 4, 8, 6 }; + int value = 2; + TriangleMatrix matrix(data, size); + matrix += value; + // Assert + EXPECT_EQ(matrix.at(0).at(0), 4); + EXPECT_EQ(matrix.at(0).at(1), 4); + EXPECT_EQ(matrix.at(0).at(2), 6); + EXPECT_EQ(matrix.at(1).at(1), 6); + EXPECT_EQ(matrix.at(1).at(2), 10); + EXPECT_EQ(matrix.at(2).at(2), 8); +} +TEST(TestTriangleMatrixLib, tr_matrix_sub_assign_value) { + // Arrange & Act + size_t size = 3; + int data[6] = { 2, 2, 4, 4, 8, 6 }; + int value = 2; + TriangleMatrix matrix(data, size); + matrix -= value; + // Assert + EXPECT_EQ(matrix.at(0).at(0), 0); + EXPECT_EQ(matrix.at(0).at(1), 0); + EXPECT_EQ(matrix.at(0).at(2), 2); + EXPECT_EQ(matrix.at(1).at(1), 2); + EXPECT_EQ(matrix.at(1).at(2), 6); + EXPECT_EQ(matrix.at(2).at(2), 4); +} +TEST(TestTriangleMatrixLib, tr_matrix_mult_assign_value) { + // Arrange & Act + size_t size = 3; + int data[6] = { 1, 2, 3, 4, 5, 6 }; + int value = 10; + TriangleMatrix matrix(data, size); + matrix *= value; + // Assert + EXPECT_EQ(matrix.at(0).at(0), 10); + EXPECT_EQ(matrix.at(0).at(1), 20); + EXPECT_EQ(matrix.at(0).at(2), 30); + EXPECT_EQ(matrix.at(1).at(1), 40); + EXPECT_EQ(matrix.at(1).at(2), 50); + EXPECT_EQ(matrix.at(2).at(2), 60); +} +TEST(TestTriangleMatrixLib, tr_matrix_div_assign_value) { + // Arrange & Act + size_t size = 3; + int data[6] = { 2, 2, 4, 4, 8, 6 }; + int value = 2; + TriangleMatrix matrix(data, size); + matrix /= value; + // Assert + EXPECT_EQ(matrix.at(0).at(0), 1); + EXPECT_EQ(matrix.at(0).at(1), 1); + EXPECT_EQ(matrix.at(0).at(2), 2); + EXPECT_EQ(matrix.at(1).at(1), 2); + EXPECT_EQ(matrix.at(1).at(2), 4); + EXPECT_EQ(matrix.at(2).at(2), 3); +} +TEST(TestTriangleMatrixLib, tr_matrix_add_tr_matrix) { + // Arrange + size_t size = 3; + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[6] = { 1, 1, 1, 1, 1, 1 }; + + TriangleMatrix matrix1(data1, size); + TriangleMatrix matrix2(data2, size); + TriangleMatrix result(size); + //Act + result = matrix1 + matrix2; + // Assert + EXPECT_EQ(result.at(0).at(0), 3); + EXPECT_EQ(result.at(0).at(1), 3); + EXPECT_EQ(result.at(0).at(2), 5); + EXPECT_EQ(result.at(1).at(1), 5); + EXPECT_EQ(result.at(1).at(2), 9); + EXPECT_EQ(result.at(2).at(2), 7); +} +TEST(TestTriangleMatrixLib, tr_matrix_sub_tr_matrix) { + // Arrange + size_t size = 3; + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[6] = { 1, 1, 1, 1, 1, 1 }; + + TriangleMatrix matrix1(data1, size); + TriangleMatrix matrix2(data2, size); + TriangleMatrix result(size); + //Act + result = matrix1 - matrix2; + // Assert + EXPECT_EQ(result.at(0).at(0), 1); + EXPECT_EQ(result.at(0).at(1), 1); + EXPECT_EQ(result.at(0).at(2), 3); + EXPECT_EQ(result.at(1).at(1), 3); + EXPECT_EQ(result.at(1).at(2), 7); + EXPECT_EQ(result.at(2).at(2), 5); +} +TEST(TestTriangleMatrixLib, tr_matrix_add_assig_tr_matrix) { + // Arrange & Act + size_t size = 3; + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[6] = { 1, 1, 1, 1, 1, 1 }; + + TriangleMatrix matrix1(data1, size); + TriangleMatrix matrix2(data2, size); + matrix1 += matrix2; + // Assert + EXPECT_EQ(matrix1.at(0).at(0), 3); + EXPECT_EQ(matrix1.at(0).at(1), 3); + EXPECT_EQ(matrix1.at(0).at(2), 5); + EXPECT_EQ(matrix1.at(1).at(1), 5); + EXPECT_EQ(matrix1.at(1).at(2), 9); + EXPECT_EQ(matrix1.at(2).at(2), 7); +} +TEST(TestTriangleMatrixLib, tr_matrix_sub_assig_tr_matrix) { + // Arrange & Act + size_t size = 3; + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[6] = { 1, 1, 1, 1, 1, 1 }; + + TriangleMatrix matrix1(data1, size); + TriangleMatrix matrix2(data2, size); + matrix1 -= matrix2; + // Assert + EXPECT_EQ(matrix1.at(0).at(0), 1); + EXPECT_EQ(matrix1.at(0).at(1), 1); + EXPECT_EQ(matrix1.at(0).at(2), 3); + EXPECT_EQ(matrix1.at(1).at(1), 3); + EXPECT_EQ(matrix1.at(1).at(2), 7); + EXPECT_EQ(matrix1.at(2).at(2), 5); +} +TEST(TestTriangleMatrixLib, tr_matrix_add_tr_matrix_with_exception) { + // Arrange & Act + + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[4] = { 1, 1, 1, 1 }; + + TriangleMatrix matrix1(data1, 3); + TriangleMatrix matrix2(data2, 2); + + // Assert + EXPECT_THROW(matrix1 + matrix2, std::logic_error); +} +TEST(TestTriangleMatrixLib, tr_matrix_sub_tr_matrix_with_exception) { + // Arrange & Act + + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[4] = { 1, 1, 1, 1 }; + + TriangleMatrix matrix1(data1, 3); + TriangleMatrix matrix2(data2, 2); + + // Assert + EXPECT_THROW(matrix1 - matrix2, std::logic_error); +} +TEST(TestTriangleMatrixLib, tr_matrix_add_assign_tr_matrix_with_exception) { + // Arrange & Act + + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[4] = { 1, 1, 1, 1 }; + + TriangleMatrix matrix1(data1, 3); + TriangleMatrix matrix2(data2, 2); + + // Assert + EXPECT_THROW(matrix1 += matrix2, std::logic_error); +} +TEST(TestTriangleMatrixLib, tr_matrix_sub_assign_tr_matrix_with_exception) { + // Arrange & Act + + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[4] = { 1, 1, 1, 1 }; + + TriangleMatrix matrix1(data1, 3); + TriangleMatrix matrix2(data2, 2); + + // Assert + EXPECT_THROW(matrix1 -= matrix2, std::logic_error); +} +TEST(TestTriangleMatrixLib, tr_matrix_mult_vector) { + // Arrange + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[3] = { 1, 1, 1 }; + + TriangleMatrix matrix(data1, 3); + MathVector vector(data2, 3); + MathVector result(3); + //Act + result = matrix * vector; + // Assert + EXPECT_EQ(result.at(0), 8); + EXPECT_EQ(result.at(1), 12); + EXPECT_EQ(result.at(2), 6); +} +TEST(TestTriangleMatrixLib, tr_matrix_mult_vector_with_exception) { + // Arrange & Act + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[10] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + TriangleMatrix matrix(data1, 3); + MathVector vector(data2, 10); + MathVector result(3); + // Assert + EXPECT_THROW(matrix * vector, std::logic_error); +} +TEST(TestTriangleMatrixLib, tr_matrix_mult_tr_matrix) { + // Arrange + size_t size = 3; + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[6] = { 1, 1, 1, 1, 1, 1 }; + TriangleMatrix matrix1(data1, size); + TriangleMatrix matrix2(data2, size); + TriangleMatrix result(size); + //Act + result = matrix1 * matrix2; + // Assert + EXPECT_EQ(result.at(0).at(0), 2); + EXPECT_EQ(result.at(0).at(1), 4); + EXPECT_EQ(result.at(0).at(2), 8); + EXPECT_EQ(result.at(1).at(1), 4); + EXPECT_EQ(result.at(1).at(2), 12); + EXPECT_EQ(result.at(2).at(2), 6); +} +TEST(TestTriangleMatrixLib, tr_matrix_mult_tr_matrix_with_exception) { + // Arrange & Act + int data1[6] = { 2, 2, 4, 4, 8, 6 }; + int data2[8] = { 1, 1, 1, 1, 1, 1, 1, 1 }; + TriangleMatrix matrix1(data1, 3); + TriangleMatrix matrix2(data2, 4); + TriangleMatrix result(3); + // Assert + EXPECT_THROW(matrix1 * matrix2, std::logic_error); +} diff --git a/tests/test_vector.cpp b/tests/test_vector.cpp new file mode 100644 index 00000000..c27ad9fb --- /dev/null +++ b/tests/test_vector.cpp @@ -0,0 +1,877 @@ +// Copyright 2025 Julia Zabytina +#include +#include "../lib_vector/vector.h" +TEST(TestVectorLib, vector_default_constructor) { + // Arrange & Act + Tvector vector; + // Assert + EXPECT_TRUE(vector.is_empty()); +} +TEST(TestVectorLib, vector_constructor_with_size) { + // Arrange & Act + size_t size = 10; + Tvector vector(size); + // Assert + EXPECT_LE(vector.get_size(), vector.get_capacity()); + EXPECT_EQ(vector.get_size(), size); +} +TEST(TestVectorLib, vector_constructor_with_array_and_size) { + // Arrange & Act + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + // Assert + EXPECT_EQ(vector.get_size(), size); + EXPECT_EQ(vector[0], data[0]); + EXPECT_EQ(vector[1], data[1]); + EXPECT_EQ(vector[2], data[2]); + EXPECT_LE(vector.get_size(), vector.get_capacity()); +} +TEST(TestVectorLib, vector_copy_constructor) { + // Arrange & Act + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector old_vector(data, size); + Tvector new_vector(old_vector); + // Assert + EXPECT_EQ(old_vector, new_vector); +} +TEST(TestVectorLib, is_empty) { + // Arrange + Tvector vector; + // Act + bool actual_result = vector.is_empty(); + // Assert + bool expected_result = true; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, get_data) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + int* data_ptr = data; + bool different_pointers = data_ptr != vector.get_data(); + bool same_data = + data[0] == vector.get_data()[0] + && data[1] == vector.get_data()[1] + && data[2] == vector.get_data()[2]; + // Act + bool actual_result = different_pointers && same_data; + // Assert + bool expected_result = true; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, front) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + // Act + int actual_result = vector.front(); + // Assert + int expected_result = vector.get_data()[0]; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, back) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + // Act + int actual_result = vector.back(); + // Assert + int expected_result = vector.get_data()[vector.get_size() - 1]; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, get_size) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + // Act + size_t actual_result = vector.get_size(); + // Assert + size_t expected_result = size; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, get_deleted) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + size_t deleted = 0; + Tvector vector(data, size); + // Act + size_t actual_result = vector.get_deleted(); + // Assert + size_t expected_result = deleted; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, get_capacity) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + size_t capacity = 18; + Tvector vector(data, size); + // Act + size_t actual_result = vector.get_capacity(); + // Assert + size_t expected_result = capacity; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, comparison_operator_true) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector1(data, size); + Tvector vector2(data, size); + // Act + bool actual_result = vector1 == vector2; + // Assert + bool expected_result = true; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, comparison_operator_false) { + // Arrange + int data1[3] = { 1,2,3 }; + size_t size1 = 3; + int data2[4] = { 1,2,3,4 }; + size_t size2 = 4; + Tvector vector1(data1, size1); + Tvector vector2(data2, size2); + // Act + bool actual_result = vector1 == vector2; + // Assert + bool expected_result = false; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, not_comparison_operator_true) { + // Arrange + int data1[3] = { 1,2,3 }; + size_t size1 = 3; + int data2[4] = { 1,2,3,4 }; + size_t size2 = 4; + Tvector vector1(data1, size1); + Tvector vector2(data2, size2); + // Act + bool actual_result = vector1 != vector2; + // Assert + bool expected_result = true; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, not_comparison_operator_false) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector1(data, size); + Tvector vector2(data, size); + // Act + bool actual_result = vector1 != vector2; + // Assert + bool expected_result = false; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, operator_assign) { + // Arrange + int data1[3] = { 1,2,3 }; + size_t size1 = 3; + int data2[4] = { 1,2,3,4 }; + size_t size2 = 4; + Tvector vector1(data1, size1); + Tvector vector2(data2, size2); + vector1 = vector2; + // Act + bool actual_result = vector1 == vector2; + // Assert + bool expected_result = true; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, operator_staples) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + // Act + int actual_result = vector[1]; + // Assert + int expected_result = data[1]; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, at) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + // Act + int actual_result = vector.at(1); + // Assert + int expected_result = data[1]; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, assign) { + // Arrange + int data[3] = { 1,1,1 }; + size_t size = 3; + Tvector vector1; + Tvector vector2(data, size); + vector1.assign(vector2); + // Act + Tvector actual_result = vector1; + // Assert + Tvector expected_result = vector2; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, clear) { + // Arrange + int data[3] = { 1, 2, 3 }; + Tvector vector(data, 3); + + // Act + vector.clear(); + + // Assert + EXPECT_EQ(0, vector.get_size()); + EXPECT_EQ(0, vector.get_deleted()); +} +TEST(TestVectorLib, emplace) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + vector.emplace(2, 100); + // Act + int actual_result = vector[2]; + // Assert + int expected_result = 100; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, push_front1) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + vector.push_front(200); + // Act + int actual_result = vector[0]; + // Assert + int expected_result = 200; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, push_front2) { + // Arrange + int data[1] = { 1 }; + size_t size = 1; + Tvector vector(data, size); + for (size_t i = 1; i < 17; ++i) { + vector.push_front(1); + } + // Act + bool actual_result = vector.get_capacity() == 31 + && vector.get_size() == 17; + // Assert + bool expected_result = true; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, insert1) { + // Arrange + int data[6] = { 1, 2, 3, 4, 5, 6 }; + size_t size = 6; + Tvector vector(data, size); + vector.insert(225, 5); + // Act + int actual_result = vector[5]; + // Assert + int expected_result = 225; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, insert2) { + // Arrange + size_t size = 10; + Tvector vector(size); + vector.insert(225, 5); + // Act + int actual_result = vector[5]; + // Assert + int expected_result = 225; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, insert3) { + // Arrange + Tvector vector; + vector.insert(225, 5); + // Act + int actual_result = vector[5]; + // Assert + int expected_result = 225; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, insert4) { + // Arrange + bool actual_result = true; + int data[5] = { 1, 2, 3, 4, 5 }; + size_t size = 5; + Tvector vector(data, size); + try { + vector.insert(225, 5); + } + catch (...) { + actual_result = false; + } + // Assert + bool expected_result = false; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, push_back1) { + // Arrange + int data[1] = { 1 }; + size_t size = 1; + Tvector vector(data, size); + for (size_t i = 1; i < 17; ++i) { + vector.push_back(400); + } + // Act + int actual_result = vector[5]; + // Assert + int expected_result = 400; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, push_back2) { + // Arrange + int data[3] = { 1, 2, 3 }; + size_t size = 3; + Tvector vector(data, size); + vector.push_back(9); + // Act + int actual_result = vector[3]; + // Assert + int expected_result = 9; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, pop_back1) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + vector.pop_back(); + // Act + bool actual_result = vector.get_size() == 2 + && vector[0] == 1 + && vector[1] == 2; + // Assert + bool expected_result = true; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, pop_back2) { + // Arrange + bool actual_result = true; + Tvector vector; + try { + vector.pop_back(); + } + catch (...) { + actual_result = false; + } + // Assert + bool expected_result = false; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, erase1) { + // Arrange + int data[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + size_t size = 15; + Tvector vector(data, size); + vector.erase(1); + vector.erase(1); + // Act + size_t actual_result = vector.get_deleted(); + // Assert + size_t expected_result = 2; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, erase2) { + // Arrange + bool actual_result = true; + int data[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + size_t size = 15; + Tvector vector(data, size); + try { + vector.erase(20); + } + catch (...) { + actual_result = false; + } + // Assert + bool expected_result = false; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, pop_front1) { + // Arrange + int data[3] = { 1,2,3 }; + size_t size = 3; + Tvector vector(data, size); + vector.pop_front(); + // Act + bool actual_result = vector.get_size() == 2 + && vector[0] == 2 + && vector[1] == 3; + // Assert + bool expected_result = true; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, pop_front2) { + // Arrange + bool actual_result = true; + Tvector vector; + try { + vector.pop_front(); + } + catch (...) { + actual_result = false; + } + // Assert + bool expected_result = false; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, sort_of_shell) { + // Arrange + int data[10] = { 1223343, 1546, 8777, 1000, 2, 3, 7, 9, 888, 99 }; + size_t size = 10; + Tvector vector(data, size); + int sorted_data[10] = { 2, 3, 7, 9, 99, 888, 1000, 1546, 8777, 1223343 }; + Tvector sorted_vector(sorted_data, size); + shell_sort(vector); + // Act + Tvector actual_result = vector; + // Assert + Tvector expected_result = sorted_vector; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, find_first) { + // Arrange + int data[6] = { 1 ,3, 3, 4, 5, 3 }; + size_t size = 6; + Tvector vector(data, size); + // Act + size_t actual_result = find_first_element(vector, 3); + // Assert + size_t expected_result = 2; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, find_last) { + // Arrange + int data[6] = { 1 ,3, 3, 4, 5, 3 }; + size_t size = 6; + Tvector vector(data, size); + // Act + size_t actual_result = find_last_element(vector, 3); + // Assert + size_t expected_result = 6; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, find_count_of_suitable_elements) { + // Arrange + int data[8] = { 1 ,3, 3, 4, 5, 3, 3, 7 }; + size_t size = 8; + Tvector vector(data, size); + // Act + size_t actual_result = find_count_of_all_suitable_elements(vector, 3); + // Assert + size_t expected_result = 4; + EXPECT_EQ(expected_result, actual_result); +} +TEST(TestVectorLib, vector_iterator_read) { + // Arrange + Tvector vector; + vector.push_back(3); + vector.push_back(400); + vector.push_back(109); + vector.push_back(1); + vector.push_back(2); + // Act + auto it = vector.begin(); + it += 3; + // Assert + EXPECT_EQ(1, *it); +} +TEST(TestVectorLib, vector_iterator_write) { + // Arrange + Tvector vector; + vector.push_back(1); + vector.push_back(34); + vector.push_back(17); + vector.push_back(12); + vector.push_back(3); + // Act + auto it = vector.begin(); + it += 3; + // Assert + EXPECT_EQ(12, *it); + *it = 900; + EXPECT_EQ(900, *it); +} +TEST(TestVectorLib, vector_iterator_empty_list) { + // Arrange + Tvector vector; + // Act & Assert + EXPECT_EQ(vector.begin(), vector.end()); + + auto it = vector.begin(); + ++it; + EXPECT_EQ(it, vector.end()); + + auto end_it = vector.end(); + ++end_it; + EXPECT_EQ(end_it, vector.end()); + + auto it2 = vector.begin(); + it2 += 7; + EXPECT_EQ(it2, vector.end()); +} +TEST(TestVectorLib, vector_iterator_prefix_increment) { + Tvector vector; + vector.push_back(10); + vector.push_back(20); + vector.push_back(30); + + auto it = vector.begin(); + ++it; + EXPECT_EQ(20, *it); + ++it; + EXPECT_EQ(30, *it); +} + +TEST(TestVectorLib, vector_iterator_postfix_increment) { + Tvector vector; + vector.push_back(10); + vector.push_back(20); + vector.push_back(30); + + auto it = vector.begin(); + auto it_copy = it++; + + EXPECT_EQ(10, *it_copy); + EXPECT_EQ(20, *it); +} + +TEST(TestVectorLib, vector_iterator_prefix_decrement) { + Tvector vector; + vector.push_back(10); + vector.push_back(20); + vector.push_back(30); + + auto it = vector.begin(); + ++it; + ++it; + --it; + + EXPECT_EQ(20, *it); +} + +TEST(TestVectorLib, vector_iterator_postfix_decrement) { + Tvector vector; + vector.push_back(10); + vector.push_back(20); + vector.push_back(30); + + auto it = vector.begin(); + ++it; + ++it; + auto it_copy = it--; + + EXPECT_EQ(30, *it_copy); + EXPECT_EQ(20, *it); +} + +TEST(TestVectorLib, vector_iterator_compound_addition) { + Tvector vector; + vector.push_back(10); + vector.push_back(20); + vector.push_back(30); + vector.push_back(40); + vector.push_back(50); + + auto it = vector.begin(); + it += 3; + EXPECT_EQ(40, *it); + + it += 1; + EXPECT_EQ(50, *it); +} + +TEST(TestVectorLib, vector_iterator_compound_subtraction) { + Tvector vector; + vector.push_back(10); + vector.push_back(20); + vector.push_back(30); + vector.push_back(40); + vector.push_back(50); + + auto it = vector.begin(); + it += 4; + it -= 2; + + EXPECT_EQ(30, *it); + + it -= 2; + EXPECT_EQ(10, *it); +} + +TEST(TestVectorLib, vector_iterator_equality_operators) { + Tvector vector; + vector.push_back(10); + vector.push_back(20); + vector.push_back(30); + + auto it1 = vector.begin(); + auto it2 = vector.begin(); + EXPECT_TRUE(it1 == it2); + + ++it1; + EXPECT_FALSE(it1 == it2); + EXPECT_TRUE(it1 != it2); +} + +TEST(TestVectorLib, vector_iterator_dereference) { + Tvector vector; + vector.push_back(100); + vector.push_back(200); + + auto it = vector.begin(); + EXPECT_EQ(100, *it); + + ++it; + EXPECT_EQ(200, *it); +} + +TEST(TestVectorLib, vector_iterator_dereference_const) { + Tvector vector; + vector.push_back(100); + vector.push_back(200); + + const Tvector& const_vector = vector; + auto it = const_vector.begin(); + + EXPECT_EQ(100, *it); + ++it; + EXPECT_EQ(200, *it); +} + +TEST(TestVectorLib, vector_iterator_dereference_modify) { + Tvector vector; + vector.push_back(100); + vector.push_back(200); + + auto it = vector.begin(); + *it = 500; + + EXPECT_EQ(500, vector[0]); +} + +TEST(TestVectorLib, vector_iterator_copy_constructor) { + Tvector vector; + vector.push_back(100); + vector.push_back(200); + + auto it1 = vector.begin(); + auto it2 = it1; + + EXPECT_TRUE(it1 == it2); + EXPECT_EQ(100, *it1); + EXPECT_EQ(100, *it2); + + ++it1; + EXPECT_FALSE(it1 == it2); + EXPECT_EQ(200, *it1); + EXPECT_EQ(100, *it2); +} + +TEST(TestVectorLib, vector_iterator_assignment_operator) { + Tvector vector; + vector.push_back(100); + vector.push_back(200); + vector.push_back(300); + + auto it1 = vector.begin(); + auto it2 = vector.begin(); + ++it2; + ++it2; + + it1 = it2; + + EXPECT_TRUE(it1 == it2); + EXPECT_EQ(300, *it1); + EXPECT_EQ(300, *it2); +} + +TEST(TestVectorLib, vector_iterator_default_constructor) { + Tvector::Iterator it; + + Tvector vector; + vector.push_back(10); + + auto it2 = vector.begin(); + it = it2; + + EXPECT_EQ(10, *it); +} +TEST(TestVectorLib, vector_iterator_dereference_nullptr_exception) { + Tvector::Iterator it; + EXPECT_THROW(*it, std::runtime_error); +} + +TEST(TestVectorLib, vector_iterator_range_based_for_loop) { + Tvector vector; + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + vector.push_back(5); + + int sum = 0; + for (const auto& value : vector) { + sum += value; + } + + EXPECT_EQ(15, sum); +} + +TEST(TestVectorLib, vector_iterator_range_based_for_loop_modify) { + Tvector vector; + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + + for (auto& value : vector) { + value *= 2; + } + + auto it = vector.begin(); + EXPECT_EQ(2, *it); + ++it; + EXPECT_EQ(4, *it); + ++it; + EXPECT_EQ(6, *it); +} + +TEST(TestVectorLib, vector_iterator_manual_for_loop) { + Tvector vector; + vector.push_back(10); + vector.push_back(20); + vector.push_back(30); + vector.push_back(40); + + std::vector values; + for (auto it = vector.begin(); it != vector.end(); ++it) { + values.push_back(*it); + } + + ASSERT_EQ(4, values.size()); + EXPECT_EQ(10, values[0]); + EXPECT_EQ(20, values[1]); + EXPECT_EQ(30, values[2]); + EXPECT_EQ(40, values[3]); +} + +TEST(TestVectorLib, vector_iterator_begin_end_empty) { + Tvector vector; + + EXPECT_EQ(vector.begin(), vector.end()); + + auto it = vector.begin(); + ++it; + EXPECT_EQ(it, vector.end()); +} + +TEST(TestVectorLib, vector_iterator_begin_end_non_empty) { + Tvector vector; + vector.push_back(10); + vector.push_back(20); + + auto begin = vector.begin(); + auto end = vector.end(); + + EXPECT_NE(begin, end); + + auto it = begin; + ++it; + ++it; + EXPECT_EQ(it, end); +} + +TEST(TestVectorLib, vector_iterator_reverse_iteration) { + Tvector vector; + vector.push_back(1); + vector.push_back(2); + vector.push_back(3); + vector.push_back(4); + vector.push_back(5); + + std::vector reversed; + + auto it = vector.end(); + --it; + + while (true) { + reversed.push_back(*it); + if (it == vector.begin()) { + break; + } + --it; + } + + ASSERT_EQ(5, reversed.size()); + EXPECT_EQ(5, reversed[0]); + EXPECT_EQ(4, reversed[1]); + EXPECT_EQ(3, reversed[2]); + EXPECT_EQ(2, reversed[3]); + EXPECT_EQ(1, reversed[4]); +} + +TEST(TestVectorLib, vector_iterator_arithmetic_mixed) { + Tvector vector; + for (int i = 0; i < 10; ++i) { + vector.push_back(i * 10); + } + + auto it = vector.begin(); + it += 5; + EXPECT_EQ(50, *it); + + --it; + EXPECT_EQ(40, *it); + + it -= 2; + EXPECT_EQ(20, *it); + + it++; + EXPECT_EQ(30, *it); + + ++it; + EXPECT_EQ(40, *it); +} + +TEST(TestVectorLib, vector_iterator_self_assignment) { + Tvector vector; + vector.push_back(100); + vector.push_back(200); + + auto it = vector.begin(); + it = it; + + EXPECT_EQ(100, *it); +} + +TEST(TestVectorLib, vector_iterator_comparison_with_different_vectors) { + Tvector vector1; + vector1.push_back(10); + + Tvector vector2; + vector2.push_back(10); + + auto it1 = vector1.begin(); + auto it2 = vector2.begin(); + + + EXPECT_FALSE(it1 == it2); + EXPECT_TRUE(it1 != it2); +}