From 9f9fa2fb37abdef2e2becc2aeec448e77adbfdce Mon Sep 17 00:00:00 2001 From: Andrey <88825623+Andrey23525@users.noreply.github.com> Date: Thu, 27 Nov 2025 22:28:06 +0500 Subject: [PATCH 1/8] add tasks --- 01_week/tasks/addition/addition.cpp | 5 +- 01_week/tasks/check_flags/check_flags.cpp | 5 +- 01_week/tasks/length_lit/length_lit.cpp | 68 +++++++++++++++++++++++ 01_week/tasks/print_bits/print_bits.cpp | 29 +++++++++- 01_week/tasks/quadratic/quadratic.cpp | 36 +++++++++++- 01_week/tasks/rms/rms.cpp | 17 ++++-- 6 files changed, 148 insertions(+), 12 deletions(-) diff --git a/01_week/tasks/addition/addition.cpp b/01_week/tasks/addition/addition.cpp index 92872802..efc93080 100644 --- a/01_week/tasks/addition/addition.cpp +++ b/01_week/tasks/addition/addition.cpp @@ -3,5 +3,6 @@ int64_t Addition(int a, int b) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + + return static_cast(a) + static_cast(b); +} diff --git a/01_week/tasks/check_flags/check_flags.cpp b/01_week/tasks/check_flags/check_flags.cpp index 75e7c652..eefe38d4 100644 --- a/01_week/tasks/check_flags/check_flags.cpp +++ b/01_week/tasks/check_flags/check_flags.cpp @@ -14,5 +14,8 @@ enum class CheckFlags : uint8_t { }; void PrintCheckFlags(CheckFlags flags) { - throw std::runtime_error{"Not implemented"}; + using std::cout; + if((uint8_t)flags == 0) { + cout << "[]"; + } } diff --git a/01_week/tasks/length_lit/length_lit.cpp b/01_week/tasks/length_lit/length_lit.cpp index e69de29b..de9f1a2d 100644 --- a/01_week/tasks/length_lit/length_lit.cpp +++ b/01_week/tasks/length_lit/length_lit.cpp @@ -0,0 +1,68 @@ +constexpr long double FT_TO_M = 0.3048L; +constexpr long double M_TO_FT = 1.0L / FT_TO_M; +constexpr long double FT_TO_IN = 12.0L; +constexpr long double IN_TO_FT = 1.0L / FT_TO_IN; +constexpr long double FT_TO_CM = FT_TO_M * 100.0L; +constexpr long double CM_TO_FT = 1.0L / FT_TO_CM; + +constexpr long double IN_TO_M = 0.0254L; +constexpr long double M_TO_IN = 1.0L / IN_TO_M; +constexpr long double IN_TO_CM = IN_TO_M * 100.0L; +constexpr long double CM_TO_IN = 1.0L / IN_TO_CM; + + +constexpr long double CM_TO_M = 0.01L; +constexpr long double M_TO_CM = 1.0L / CM_TO_M; + + +// ft -> +constexpr double operator"" _ft_to_m(long double value) { + return static_cast(value * FT_TO_M); +} + +constexpr double operator"" _ft_to_in(long double value) { + return static_cast(value * FT_TO_IN); +} + +constexpr double operator"" _ft_to_cm(long double value) { + return static_cast(value * FT_TO_CM); +} + +// in -> +constexpr double operator"" _in_to_m(long double value) { + return static_cast(value * IN_TO_M); +} + +constexpr double operator"" _in_to_ft(long double value) { + return static_cast(value * IN_TO_FT); +} + +constexpr double operator"" _in_to_cm(long double value) { + return static_cast(value * IN_TO_CM); +} + +// cm -> +constexpr double operator"" _cm_to_m(long double value) { + return static_cast(value * CM_TO_M); +} + +constexpr double operator"" _cm_to_ft(long double value) { + return static_cast(value * CM_TO_FT); +} + +constexpr double operator"" _cm_to_in(long double value) { + return static_cast(value * CM_TO_IN); +} + +// m -> +constexpr double operator"" _m_to_ft(long double value) { + return static_cast(value * M_TO_FT); +} + +constexpr double operator"" _m_to_in(long double value) { + return static_cast(value * M_TO_IN); +} + +constexpr double operator"" _m_to_cm(long double value) { + return static_cast(value * M_TO_CM); +} diff --git a/01_week/tasks/print_bits/print_bits.cpp b/01_week/tasks/print_bits/print_bits.cpp index a48a43c1..454e6f2a 100644 --- a/01_week/tasks/print_bits/print_bits.cpp +++ b/01_week/tasks/print_bits/print_bits.cpp @@ -2,6 +2,31 @@ #include -void PrintBits(long long value, size_t bytes) { - throw std::runtime_error{"Not implemented"}; + void PrintBits(long long value, size_t bytes) { + using std::cout; + using ULL = unsigned long long; + constexpr char BITS_IN_BYTE = 8; + constexpr char BYTES_IN_LONG_LONG = sizeof(long long); + + size_t bits = bytes * BITS_IN_BYTE; + + // Сдвиг, чтобы напечатать младшие байты + ULL mask = (bytes == BYTES_IN_LONG_LONG) + ? ~0ULL + : ((1ULL << (bits)) - 1); + + ULL valueWithMask = static_cast(value) & mask; + cout << "0b"; + + for(size_t i = 0; i < bits; ++i) { + size_t bitIndex = bits - i - 1; + bool bit = (valueWithMask >> bitIndex) & 1; // определение бита на позиции bitIndex + cout << (bit ? '1' : '0'); + + if(bitIndex % 4 == 0 && bitIndex != 0) { + cout << '\''; + } + } + + cout << '\n'; } diff --git a/01_week/tasks/quadratic/quadratic.cpp b/01_week/tasks/quadratic/quadratic.cpp index abf7d632..892d52c6 100644 --- a/01_week/tasks/quadratic/quadratic.cpp +++ b/01_week/tasks/quadratic/quadratic.cpp @@ -1,6 +1,36 @@ #include - +#include +#include +#include void SolveQuadratic(int a, int b, int c) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + using std::cout, std::setprecision; + if(a == 0 && b == 0 && c == 0) { + cout << "infinite solutions"; + return; + } + if(a == 0 && b == 0 && c != 0) { + cout << "no solutions"; + return; + } + + if(a != 0) { // two roots + int discriminant = b * b - 4 * a * c; + + cout << setprecision(6); + if(discriminant > 0) { + double discriminantRoot = sqrt(discriminant); + double x1 = (-b - discriminantRoot) / (2.0*a); + double x2 = (-b + discriminantRoot) / (2.0*a); + cout << x1 << ' ' << x2; + } else if(discriminant == 0){ + double x1 = (-b) / (2.0*a); + cout << x1; + } else { + cout << "no solutions"; + } + } else { // only one root + double x1 = static_cast(-c) / b; + cout << x1; + } +} diff --git a/01_week/tasks/rms/rms.cpp b/01_week/tasks/rms/rms.cpp index 6882f0a9..c1234590 100644 --- a/01_week/tasks/rms/rms.cpp +++ b/01_week/tasks/rms/rms.cpp @@ -1,7 +1,16 @@ -#include -#include +#include double CalculateRMS(double values[], size_t size) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + if(size == 0) return 0.0; + if(values == nullptr) return 0.0; + + long double sumOfSquares = 0; + + for(size_t i = 0; i < size; ++i) { + double &value = values[i]; + sumOfSquares += value * value; + } + + return sqrt(sumOfSquares / size); +} From 156abcf20e6760f4a5f5e801720c61ba0b160cc5 Mon Sep 17 00:00:00 2001 From: Andrey <88825623+Andrey23525@users.noreply.github.com> Date: Fri, 28 Nov 2025 23:26:48 +0500 Subject: [PATCH 2/8] add char_changer and check_flags tasks --- 01_week/tasks/char_changer/char_changer.cpp | 59 +++++++++++++++++++-- 01_week/tasks/check_flags/check_flags.cpp | 39 ++++++++++++-- 2 files changed, 91 insertions(+), 7 deletions(-) diff --git a/01_week/tasks/char_changer/char_changer.cpp b/01_week/tasks/char_changer/char_changer.cpp index 3a7344d9..ac85f5c8 100644 --- a/01_week/tasks/char_changer/char_changer.cpp +++ b/01_week/tasks/char_changer/char_changer.cpp @@ -1,7 +1,60 @@ #include #include +size_t CharChanger(char* array, size_t size, char delimiter) { + if (size == 0) return 0; -size_t CharChanger(char array[], size_t size, char delimiter = ' ') { - throw std::runtime_error{"Not implemented"}; -} + size_t writePos = 0; // куда пишем результат + size_t readPos = 0; // откуда читаем исходные символы + + while (readPos < size - 1) { // последний символ — '\0' + char currentChar = array[readPos]; + + // Приведения текущего символа к определенным типам: пробел, число или ASCII символ + bool isSpace = std::isspace(static_cast(currentChar)) != 0; + bool isDigit = std::isdigit(static_cast(currentChar)) != 0; + bool isAlpha = std::isalpha(static_cast(currentChar)) != 0; + + // Подсчёт длины последовательности одинаковых символов + size_t nextPos = readPos + 1; + while (nextPos < size - 1 && array[nextPos] == currentChar) { + nextPos++; + } + size_t runLength = nextPos - readPos; + + // Обработка пробелов + if (isSpace) { + array[writePos++] = delimiter; + } else { + char outChar; + + if (isDigit) { + outChar = '*'; + } else if (isAlpha) { + if (std::islower(static_cast(currentChar))) { + outChar = std::toupper(static_cast(currentChar)); + } else { + outChar = currentChar; // буква и так прописная + } + } else { + outChar = '_'; + } + + array[writePos++] = outChar; + + // Добавление количества повторений + if (runLength > 1) { + if (runLength >= 10) { + array[writePos++] = '0'; + } else { + array[writePos++] = char('0' + runLength); + } + } + } + + readPos = nextPos; + } + + array[writePos] = '\0'; + return writePos; +} \ No newline at end of file diff --git a/01_week/tasks/check_flags/check_flags.cpp b/01_week/tasks/check_flags/check_flags.cpp index eefe38d4..ef3bda88 100644 --- a/01_week/tasks/check_flags/check_flags.cpp +++ b/01_week/tasks/check_flags/check_flags.cpp @@ -14,8 +14,39 @@ enum class CheckFlags : uint8_t { }; void PrintCheckFlags(CheckFlags flags) { - using std::cout; - if((uint8_t)flags == 0) { - cout << "[]"; + uint8_t value = static_cast(flags); + uint8_t all_bits = static_cast(CheckFlags::ALL); + + // выход за пределы возможных значений + if (value & ~all_bits) { + return; + } + + // не установлено никаких флагов + if (value == 0) { + std::cout << "[]"; + return; + } + + const std::pair flag_names[] = { + {CheckFlags::TIME, "TIME"}, + {CheckFlags::DATE, "DATE"}, + {CheckFlags::USER, "USER"}, + {CheckFlags::CERT, "CERT"}, + {CheckFlags::KEYS, "KEYS"}, + {CheckFlags::DEST, "DEST"} + }; + + bool first = true; + std::cout << "["; + for (const auto& flag : flag_names) { + if (value & static_cast(flag.first)) { + if (!first) { + std::cout << ","; + } + std::cout << flag.second; + first = false; + } } -} + std::cout << "]"; +} \ No newline at end of file From ad02168be4f072a4be28aa5ee3c6d43aadcccc29 Mon Sep 17 00:00:00 2001 From: Andrey <88825623+Andrey23525@users.noreply.github.com> Date: Sun, 7 Dec 2025 01:35:27 +0500 Subject: [PATCH 3/8] add swap_ptr and last_of_us tasks --- 02_week/tasks/last_of_us/last_of_us.cpp | 14 +++++++++++--- 02_week/tasks/swap_ptr/swap_ptr.cpp | 8 +++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/02_week/tasks/last_of_us/last_of_us.cpp b/02_week/tasks/last_of_us/last_of_us.cpp index c7bf1a25..acbb6589 100644 --- a/02_week/tasks/last_of_us/last_of_us.cpp +++ b/02_week/tasks/last_of_us/last_of_us.cpp @@ -1,6 +1,14 @@ #include - -/* return_type */ FindLastElement(/* ptr_type */ begin, /* ptr_type */ end, /* func_type */ predicate) { - throw std::runtime_error{"Not implemented"}; +template +const int* FindLastElement(const int* begin, const int* end, Predicate pred) { + if (begin == nullptr || end == nullptr || begin > end) { + return end; + } + for (const int* ptr = end - 1; ptr >= begin; --ptr) { + if (pred(*ptr)) { + return ptr; + } + } + return end; } \ No newline at end of file diff --git a/02_week/tasks/swap_ptr/swap_ptr.cpp b/02_week/tasks/swap_ptr/swap_ptr.cpp index 93db625d..8bb06434 100644 --- a/02_week/tasks/swap_ptr/swap_ptr.cpp +++ b/02_week/tasks/swap_ptr/swap_ptr.cpp @@ -1,6 +1,8 @@ #include - -void SwapPtr(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +template +void SwapPtr(T*& ptr1, T*& ptr2) { + T* tempPtr = ptr1; + ptr1 = ptr2; + ptr2 = tempPtr; } \ No newline at end of file From 2c633b8206d3e8ddc1da93e71ce2ff0a27438ca8 Mon Sep 17 00:00:00 2001 From: Andrey <88825623+Andrey23525@users.noreply.github.com> Date: Tue, 9 Dec 2025 02:15:33 +0500 Subject: [PATCH 4/8] add other tasks --- 02_week/tasks/func_array/func_array.cpp | 16 +++++- 02_week/tasks/last_of_us/last_of_us.cpp | 7 +-- 02_week/tasks/little_big/little_big.cpp | 50 ++++++++++++++-- 02_week/tasks/longest/longest.cpp | 46 ++++++++++++++- 02_week/tasks/pretty_array/pretty_array.cpp | 63 ++++++++++++++++++++- 02_week/tasks/swap_ptr/swap_ptr.cpp | 2 - 6 files changed, 162 insertions(+), 22 deletions(-) diff --git a/02_week/tasks/func_array/func_array.cpp b/02_week/tasks/func_array/func_array.cpp index b327e68d..4eefe146 100644 --- a/02_week/tasks/func_array/func_array.cpp +++ b/02_week/tasks/func_array/func_array.cpp @@ -1,6 +1,16 @@ #include -double ApplyOperations(double a, double b /* other arguments */) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file +double ApplyOperations(double a, double b, double (**ops)(double, double), size_t size) { + if (ops == nullptr || size == 0) return 0.0; + + double sum = 0.0; + for (size_t i = 0; i < size; ++i) { + if (ops[i] == nullptr) { + continue; // , nullptr + } + sum += ops[i](a, b); + } + + return sum; +} diff --git a/02_week/tasks/last_of_us/last_of_us.cpp b/02_week/tasks/last_of_us/last_of_us.cpp index acbb6589..a02b98e3 100644 --- a/02_week/tasks/last_of_us/last_of_us.cpp +++ b/02_week/tasks/last_of_us/last_of_us.cpp @@ -1,10 +1,7 @@ -#include - template const int* FindLastElement(const int* begin, const int* end, Predicate pred) { - if (begin == nullptr || end == nullptr || begin > end) { - return end; - } + if (begin == nullptr || end == nullptr || begin > end) return end; + for (const int* ptr = end - 1; ptr >= begin; --ptr) { if (pred(*ptr)) { return ptr; diff --git a/02_week/tasks/little_big/little_big.cpp b/02_week/tasks/little_big/little_big.cpp index abe24379..e0e66469 100644 --- a/02_week/tasks/little_big/little_big.cpp +++ b/02_week/tasks/little_big/little_big.cpp @@ -1,10 +1,48 @@ -#include +#include +void PrintMemory(int value, bool reverse = false) { + using std::cout, std::hex, std::uppercase, std::setw, std::setfill; + // Представляем как массив байт + const uint8_t* bytes = reinterpret_cast(&value); -void PrintMemory(int /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; + cout << "0x"; + cout << uppercase << hex; + if (reverse) { + // Печатаем от старших к младшим + for (int i = sizeof(int) - 1; i >= 0; --i) { + cout << setw(2) + << setfill('0') << static_cast(bytes[i]); + } + } + else { + // Печатаем от младших к старшим + for (size_t i = 0; i < sizeof(int); ++i) { + cout << setw(2) + << setfill('0') << static_cast(bytes[i]); + } + } + cout << "\n"; } -void PrintMemory(double /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file +void PrintMemory(double value, bool reverse = false) { + using std::cout, std::hex, std::uppercase, std::setw, std::setfill; + const uint8_t* bytes = reinterpret_cast(&value); + + cout << "0x"; + cout << uppercase << hex; + if (reverse) { + // Печатаем от старших к младшим + for (int i = sizeof(double) - 1; i >= 0; --i) { + cout << setw(2) + << setfill('0') << static_cast(bytes[i]); + } + } + else { + // Печатаем от младших к старшим + for (size_t i = 0; i < sizeof(double); ++i) { + cout << setw(2) + << setfill('0') << static_cast(bytes[i]); + } + } + cout << "\n"; +} diff --git a/02_week/tasks/longest/longest.cpp b/02_week/tasks/longest/longest.cpp index 04b3c354..998f35cc 100644 --- a/02_week/tasks/longest/longest.cpp +++ b/02_week/tasks/longest/longest.cpp @@ -1,6 +1,46 @@ -#include +const char* FindLongestSubsequence(const char* begin, const char* end, size_t& count) { + if (!begin || !end || begin >= end) { + count = 0; + return nullptr; + } + const char* longestStringStart = begin; + size_t longestStringLength = 1; + const char* currentStart = begin; + size_t currentLength = 1; + const char* previousCharacter = begin; + const char* currentCharacter = begin + 1; -/* return_type */ FindLongestSubsequence(/* ptr_type */ begin, /* ptr_type */ end, /* type */ count) { - throw std::runtime_error{"Not implemented"}; + for (; currentCharacter < end; ++currentCharacter) { + if (*currentCharacter == *previousCharacter) { + currentLength++; + } + else { + if (currentLength > longestStringLength) { + longestStringLength = currentLength; + longestStringStart = currentStart; + } + currentStart = currentCharacter; + currentLength = 1; + } + previousCharacter = currentCharacter; + } + + // + if (currentLength > longestStringLength) { + longestStringLength = currentLength; + longestStringStart = currentStart; + } + + count = longestStringLength; + return longestStringStart; } + +char* FindLongestSubsequence(char* begin, char* end, size_t& count) { + return const_cast( + FindLongestSubsequence(static_cast(begin), + static_cast(end), + count) + ); +} + diff --git a/02_week/tasks/pretty_array/pretty_array.cpp b/02_week/tasks/pretty_array/pretty_array.cpp index 48eab341..3b026dfa 100644 --- a/02_week/tasks/pretty_array/pretty_array.cpp +++ b/02_week/tasks/pretty_array/pretty_array.cpp @@ -1,6 +1,63 @@ -#include +void PrintArray(nullptr_t, nullptr_t, size_t = 0) { + std::cout << "[]\n"; +} +template +void PrintArray(const T* begin, const T* end, size_t limit = 0) { + using std::cout; + if (begin == nullptr || end == nullptr || begin == end) { + cout << "[]\n"; + return; + } -void PrintArray(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; + bool reversed = end < begin; + const T* first = begin; + const T* last = end; + + + size_t count = abs(static_cast(last - first)); // + + // + cout << "["; + if (limit == 0 || limit >= count) { + if (reversed == false) { + for (const T* ptr = first; ptr != last; ++ptr) { + if (ptr != first) cout << ", "; + cout << *ptr; + } + } + else { + for (const T* ptr = first; ptr != last; --ptr) { + if (ptr != first) cout << ", "; + cout << *ptr; + } + } + cout << "]\n"; + return; + } + + + // + size_t printed = 0; + const T* ptr = first; + + while (printed < count) { + size_t onLine = 0; + + while (onLine < limit && printed < count) { + if (onLine > 0) cout << ", "; + cout << *ptr; + ++onLine; + ++printed; + ptr += reversed ? -1 : 1; + } + + // , + if (printed < count) { + cout << ", ...\n"; + cout << " "; + } + } + + cout << "]\n"; } \ No newline at end of file diff --git a/02_week/tasks/swap_ptr/swap_ptr.cpp b/02_week/tasks/swap_ptr/swap_ptr.cpp index 8bb06434..782c7a14 100644 --- a/02_week/tasks/swap_ptr/swap_ptr.cpp +++ b/02_week/tasks/swap_ptr/swap_ptr.cpp @@ -1,5 +1,3 @@ -#include - template void SwapPtr(T*& ptr1, T*& ptr2) { T* tempPtr = ptr1; From 96c980fa41231d170964a392e68506c8cf51173c Mon Sep 17 00:00:00 2001 From: Sergei Dekhtiar <102069117+18thday@users.noreply.github.com> Date: Thu, 18 Dec 2025 12:53:18 +0500 Subject: [PATCH 5/8] Update CMakeLists.txt Temporary Update --- 04_week/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/04_week/CMakeLists.txt b/04_week/CMakeLists.txt index 0531237e..fcfe9625 100644 --- a/04_week/CMakeLists.txt +++ b/04_week/CMakeLists.txt @@ -7,9 +7,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # Гарантирует использов set(EXAMPLES_DIR examples) # Определим переменную с именем директории set(TASKS_DIR tasks) -add_subdirectory(tasks) +#add_subdirectory(tasks) # Создать исполняемый файл для каждого примера if (BUILD_EXAMPLES_04_WEEK) # add_example(struct_examples ${EXAMPLES_DIR}/struct_examples.cpp) -endif() \ No newline at end of file +endif() From 12d3bc26f16f3ad039695d572c943d302ec8e7ba Mon Sep 17 00:00:00 2001 From: Andrey <88825623+Andrey23525@users.noreply.github.com> Date: Fri, 19 Dec 2025 22:31:42 +0500 Subject: [PATCH 6/8] add 03_week tasks --- 03_week/tasks/data_stats/data_stats.cpp | 26 +++++- 03_week/tasks/easy_compare/easy_compare.cpp | 68 ++++++++++++++- .../tasks/enum_operators/enum_operators.cpp | 85 ++++++++++++++++--- 03_week/tasks/filter/filter.cpp | 18 +++- 03_week/tasks/find_all/find_all.cpp | 19 ++++- 03_week/tasks/minmax/minmax.cpp | 58 ++++++++++++- 03_week/tasks/os_overload/os_overload.cpp | 52 ++++++++++-- 03_week/tasks/range/range.cpp | 29 ++++++- 03_week/tasks/unique/unique.cpp | 27 +++++- 9 files changed, 344 insertions(+), 38 deletions(-) diff --git a/03_week/tasks/data_stats/data_stats.cpp b/03_week/tasks/data_stats/data_stats.cpp index b941c211..67bad12b 100644 --- a/03_week/tasks/data_stats/data_stats.cpp +++ b/03_week/tasks/data_stats/data_stats.cpp @@ -1,11 +1,29 @@ #include - +#include +#include struct DataStats { double avg = 0.0; double sd = 0.0; }; -/* return_type */ CalculateDataStats(/* args */) { - throw std::runtime_error{"Not implemented"}; -} +DataStats CalculateDataStats(const std::vector& data) { + DataStats stats; + + if (data.empty()) { + return stats; + } + + double sum = 0.0; + double sum_of_squares = 0.0; + for (const int& value : data) { + sum += value; + sum_of_squares += static_cast(value) * value; + } + + stats.avg = sum / data.size(); + double variance = (sum_of_squares / data.size()) - (stats.avg * stats.avg); + variance = variance >= 0.0 ? variance : 0.0; + stats.sd = std::sqrt(variance); + return stats; +} \ No newline at end of file diff --git a/03_week/tasks/easy_compare/easy_compare.cpp b/03_week/tasks/easy_compare/easy_compare.cpp index dd5cb7f6..2ebd4206 100644 --- a/03_week/tasks/easy_compare/easy_compare.cpp +++ b/03_week/tasks/easy_compare/easy_compare.cpp @@ -1,10 +1,12 @@ #include - struct Date { unsigned year; unsigned month; unsigned day; + + Date() : year(0), month(0), day(0) {} + Date(unsigned y, unsigned m, unsigned d) : year(y), month(m), day(d) {} }; struct StudentInfo { @@ -13,4 +15,66 @@ struct StudentInfo { int score; unsigned course; Date birth_date; -}; \ No newline at end of file +}; + +bool operator==(const Date& lhs, const Date& rhs) { + return std::tie(lhs.year, lhs.month, lhs.day) == + std::tie(rhs.year, rhs.month, rhs.day); +} + +bool operator!=(const Date& lhs, const Date& rhs) { + return !(lhs == rhs); +} + +bool operator<(const Date& lhs, const Date& rhs) { + return std::tie(lhs.year, lhs.month, lhs.day) < + std::tie(rhs.year, rhs.month, rhs.day); +} + +bool operator<=(const Date& lhs, const Date& rhs) { + return !(rhs < lhs); +} + +bool operator>(const Date& lhs, const Date& rhs) { + return rhs < lhs; +} + +bool operator>=(const Date& lhs, const Date& rhs) { + return !(lhs < rhs); +} + +bool operator==(const StudentInfo& lhs, const StudentInfo& rhs) { + return lhs.mark == rhs.mark && lhs.score == rhs.score; +} + +bool operator!=(const StudentInfo& lhs, const StudentInfo& rhs) { + return !(lhs == rhs); +} + +bool operator<(const StudentInfo& lhs, const StudentInfo& rhs) { + if (lhs.mark != rhs.mark) { + return lhs.mark > rhs.mark; + } + + if (lhs.score != rhs.score) { + return lhs.score < rhs.score; + } + + if (lhs.course != rhs.course) { + return lhs.course > rhs.course; + } + + return lhs.birth_date < rhs.birth_date; +} + +bool operator<=(const StudentInfo& lhs, const StudentInfo& rhs) { + return !(rhs < lhs); +} + +bool operator>(const StudentInfo& lhs, const StudentInfo& rhs) { + return rhs < lhs; +} + +bool operator>=(const StudentInfo& lhs, const StudentInfo& rhs) { + return !(lhs < rhs); +} \ No newline at end of file diff --git a/03_week/tasks/enum_operators/enum_operators.cpp b/03_week/tasks/enum_operators/enum_operators.cpp index a539be38..0762da8a 100644 --- a/03_week/tasks/enum_operators/enum_operators.cpp +++ b/03_week/tasks/enum_operators/enum_operators.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include enum class CheckFlags : uint8_t { NONE = 0, @@ -12,22 +14,85 @@ enum class CheckFlags : uint8_t { ALL = TIME | DATE | USER | CERT | KEYS | DEST }; -/* return_type */ operator|(/* args */) { - throw std::runtime_error{"Not implemented"}; +// разрешены только младшие 6 бит +inline CheckFlags sanitize(CheckFlags flags) { + uint8_t value = static_cast(flags); + uint8_t all_value = static_cast(CheckFlags::ALL); + return static_cast(value & all_value); } -/* return_type */ operator&(/* args */) { - throw std::runtime_error{"Not implemented"}; +CheckFlags operator|(CheckFlags lhs, CheckFlags rhs) { + uint8_t result = static_cast(lhs) | static_cast(rhs); + return sanitize(static_cast(result)); } -/* return_type */ operator^(/* args */) { - throw std::runtime_error{"Not implemented"}; +bool operator&(CheckFlags lhs, CheckFlags rhs) { + lhs = sanitize(lhs); + rhs = sanitize(rhs); + + uint8_t lhs_val = static_cast(lhs); + uint8_t rhs_val = static_cast(rhs); + if (lhs_val == 0 || rhs_val == 0) { + return false; + } + + uint8_t common = lhs_val & rhs_val; + return common == lhs_val || common == rhs_val; } -/* return_type */ operator~(/* args */) { - throw std::runtime_error{"Not implemented"}; +CheckFlags operator^(CheckFlags lhs, CheckFlags rhs) { + uint8_t result = static_cast(lhs) ^ static_cast(rhs); + return sanitize(static_cast(result)); } -/* return_type */ operator<<(/* args */) { - throw std::runtime_error{"Not implemented"}; +CheckFlags operator~(CheckFlags flags) { + uint8_t all_value = static_cast(CheckFlags::ALL); + uint8_t value = static_cast(flags); + + uint8_t result = (~value) & all_value; + return static_cast(result); } + +std::ostream& operator<<(std::ostream& os, CheckFlags flags) { + flags = sanitize(flags); + + uint8_t value = static_cast(flags); + if (value == 0) { + os << "NONE"; + return os; + } + + bool first = true; + if (value & static_cast(CheckFlags::TIME)) { + if (!first) os << ", "; + os << "TIME"; + first = false; + } + if (value & static_cast(CheckFlags::DATE)) { + if (!first) os << ", "; + os << "DATE"; + first = false; + } + if (value & static_cast(CheckFlags::USER)) { + if (!first) os << ", "; + os << "USER"; + first = false; + } + if (value & static_cast(CheckFlags::CERT)) { + if (!first) os << ", "; + os << "CERT"; + first = false; + } + if (value & static_cast(CheckFlags::KEYS)) { + if (!first) os << ", "; + os << "KEYS"; + first = false; + } + if (value & static_cast(CheckFlags::DEST)) { + if (!first) os << ", "; + os << "DEST"; + first = false; + } + + return os; +} \ No newline at end of file diff --git a/03_week/tasks/filter/filter.cpp b/03_week/tasks/filter/filter.cpp index 6648cb39..65b62934 100644 --- a/03_week/tasks/filter/filter.cpp +++ b/03_week/tasks/filter/filter.cpp @@ -1,6 +1,20 @@ #include +#include +void Filter(std::vector& vec, bool (*predicate)(int)) { + if (predicate == nullptr) { + return; + } -/* return_type */ Filter(/* args */) { - throw std::runtime_error{"Not implemented"}; + size_t write_position = 0; + for (size_t read_position = 0; read_position < vec.size(); ++read_position) { + if (predicate(vec[read_position])) { + if (write_position != read_position) { + vec[write_position] = vec[read_position]; + } + ++write_position; + } + } + + vec.resize(write_position); } \ No newline at end of file diff --git a/03_week/tasks/find_all/find_all.cpp b/03_week/tasks/find_all/find_all.cpp index 74f393b2..65cf5938 100644 --- a/03_week/tasks/find_all/find_all.cpp +++ b/03_week/tasks/find_all/find_all.cpp @@ -1,6 +1,19 @@ -#include +#include +#include +std::vector FindAll(const std::vector& vec, bool (*predicate)(int)) { + if (predicate == nullptr) { + return std::vector(); + } -/* return_type */ FindAll(/* args */) { - throw std::runtime_error{"Not implemented"}; + std::vector result; + for (size_t i = 0; i < vec.size(); ++i) { + if (predicate(vec[i])) { + result.push_back(i); + } + } + + result.shrink_to_fit(); + + return result; } \ No newline at end of file diff --git a/03_week/tasks/minmax/minmax.cpp b/03_week/tasks/minmax/minmax.cpp index c2869799..fc8a913d 100644 --- a/03_week/tasks/minmax/minmax.cpp +++ b/03_week/tasks/minmax/minmax.cpp @@ -1,6 +1,58 @@ #include +#include +#include +std::pair::const_iterator, std::vector::const_iterator> MinMax(const std::vector& vec) { + if (vec.empty()) { + return {vec.end(), vec.end()}; + } -/* return_type */ MinMax(/* args */) { - throw std::runtime_error{"Not implemented"}; -} + if (vec.size() == 1) { + return {vec.begin(), vec.begin()}; + } + + auto min_it = vec.begin(); + auto max_it = vec.begin(); + auto it = vec.begin() + 1; + if (vec.size() % 2 == 0) { + if (*it < *min_it) { + min_it = it; + } else if (*it >= *max_it) { + max_it = it; + } + ++it; + } + + while ((it + 1) < vec.end()) { + auto it1 = it; + auto it2 = it + 1; + + if (*it1 <= *it2) { + if (*it1 < *min_it) { + min_it = it1; + } + if (*it2 >= *max_it) { + max_it = it2; + } + } else { + if (*it2 < *min_it) { + min_it = it2; + } + if (*it1 >= *max_it) { + max_it = it1; + } + } + + it += 2; + } + + if (it != vec.end()) { + if (*it < *min_it) { + min_it = it; + } else if (*it >= *max_it) { + max_it = it; + } + } + + return {min_it, max_it}; +} \ No newline at end of file diff --git a/03_week/tasks/os_overload/os_overload.cpp b/03_week/tasks/os_overload/os_overload.cpp index e473418d..3006ead7 100644 --- a/03_week/tasks/os_overload/os_overload.cpp +++ b/03_week/tasks/os_overload/os_overload.cpp @@ -1,21 +1,59 @@ +#include #include #include #include - struct Coord2D { - int x; - int y; + int x = 0; + int y = 0; + + Coord2D() = default; + Coord2D(int x_val, int y_val) : x(x_val), y(y_val) {} }; struct Circle { - Coord2D coord; - unsigned radius; + Coord2D coord = {0, 0}; + unsigned radius = 1; + + Circle() = default; + Circle(Coord2D c, unsigned r = 1) : coord(c), radius(r) {} }; using CircleRegion = std::pair; using CircleRegionList = std::vector; -/* return_type */ operator<<(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::ostream& operator<<(std::ostream& os, const Coord2D& coord) { + os << "(" << coord.x << ", " << coord.y << ")"; + return os; +} + +std::ostream& operator<<(std::ostream& os, const Circle& circle) { + if (circle.radius == 0) { + os << "circle[]"; + } else { + os << "circle[" << circle.coord << ", r = " << circle.radius << "]"; + } + return os; +} + +std::ostream& operator<<(std::ostream& os, const CircleRegion& region) { + os << (region.second ? "+" : "-") << region.first; + return os; } + +std::ostream& operator<<(std::ostream& os, const CircleRegionList& list) { + if (list.empty()) { + os << "{}"; + } else { + os << "{\n"; + for (size_t i = 0; i < list.size(); ++i) { + os << "\t" << list[i]; + if (i < list.size() - 1) { + os << ","; + } + os << "\n"; + } + os << "}"; + } + return os; +} \ No newline at end of file diff --git a/03_week/tasks/range/range.cpp b/03_week/tasks/range/range.cpp index d2085495..e46e4f1a 100644 --- a/03_week/tasks/range/range.cpp +++ b/03_week/tasks/range/range.cpp @@ -1,7 +1,28 @@ -#include #include +std::vector Range(int from, int to, int step = 1) { + if (step == 0) { + return std::vector(); + } -std::vector Range(int from, int to, int step) { - throw std::runtime_error{"Not implemented"}; -} + if ((step > 0 && from >= to) || (step < 0 && from <= to)) { + return std::vector(); + } + + int count; + if (step > 0) { + count = (to - from + step - 1) / step; + } else { + count = (to - from + step + 1) / step; + } + + std::vector result; + result.reserve(count); + + bool isForward = step > 0; + for (int i = from; isForward ? (i < to) : (i > to); i += step) { + result.push_back(i); + } + + return result; +} \ No newline at end of file diff --git a/03_week/tasks/unique/unique.cpp b/03_week/tasks/unique/unique.cpp index 9d2545bb..aa039aba 100644 --- a/03_week/tasks/unique/unique.cpp +++ b/03_week/tasks/unique/unique.cpp @@ -1,6 +1,27 @@ #include #include -/* return_type */ Unique(/* args */) { - throw std::runtime_error{"Not implemented"}; -} +std::vector Unique(const std::vector& vec) { + if (vec.empty()) { + return std::vector(); + } + + size_t unique_count = 1; + for (size_t i = 1; i < vec.size(); ++i) { + if (vec[i] != vec[i - 1]) { + ++unique_count; + } + } + + std::vector result; + result.reserve(unique_count); + result.push_back(vec[0]); + + for (size_t i = 1; i < vec.size(); ++i) { + if (vec[i] != vec[i - 1]) { + result.push_back(vec[i]); + } + } + + return result; +} \ No newline at end of file From 2e930147c7be90d61ae8d943fbdaef8d6c7a1366 Mon Sep 17 00:00:00 2001 From: Andrey <88825623+Andrey23525@users.noreply.github.com> Date: Fri, 26 Dec 2025 23:49:25 +0500 Subject: [PATCH 7/8] add 04_week tasks --- 04_week/CMakeLists.txt | 6 +- 04_week/tasks/CMakeLists.txt | 4 + 04_week/tasks/phasor/CMakeLists.txt | 1 + 04_week/tasks/phasor/README.md | 90 +++ 04_week/tasks/phasor/phasor.cpp | 206 +++++++ 04_week/tasks/phasor/phasor.hpp | 72 +++ 04_week/tasks/phasor/test.cpp | 661 ++++++++++++++++++++++ 04_week/tasks/queue/CMakeLists.txt | 1 + 04_week/tasks/queue/README.md | 46 ++ 04_week/tasks/queue/queue.cpp | 122 ++++ 04_week/tasks/queue/queue.hpp | 38 ++ 04_week/tasks/queue/test.cpp | 446 +++++++++++++++ 04_week/tasks/ring_buffer/CMakeLists.txt | 1 + 04_week/tasks/ring_buffer/README.md | 49 ++ 04_week/tasks/ring_buffer/a.out | Bin 0 -> 287288 bytes 04_week/tasks/ring_buffer/ring_buffer.cpp | 176 ++++++ 04_week/tasks/ring_buffer/ring_buffer.hpp | 47 ++ 04_week/tasks/ring_buffer/test.cpp | 549 ++++++++++++++++++ 04_week/tasks/stack/CMakeLists.txt | 1 + 04_week/tasks/stack/README.md | 31 + 04_week/tasks/stack/stack.cpp | 53 ++ 04_week/tasks/stack/stack.hpp | 25 + 04_week/tasks/stack/test.cpp | 353 ++++++++++++ 23 files changed, 2975 insertions(+), 3 deletions(-) create mode 100644 04_week/tasks/CMakeLists.txt create mode 100644 04_week/tasks/phasor/CMakeLists.txt create mode 100644 04_week/tasks/phasor/README.md create mode 100644 04_week/tasks/phasor/phasor.cpp create mode 100644 04_week/tasks/phasor/phasor.hpp create mode 100644 04_week/tasks/phasor/test.cpp create mode 100644 04_week/tasks/queue/CMakeLists.txt create mode 100644 04_week/tasks/queue/README.md create mode 100644 04_week/tasks/queue/queue.cpp create mode 100644 04_week/tasks/queue/queue.hpp create mode 100644 04_week/tasks/queue/test.cpp create mode 100644 04_week/tasks/ring_buffer/CMakeLists.txt create mode 100644 04_week/tasks/ring_buffer/README.md create mode 100644 04_week/tasks/ring_buffer/a.out create mode 100644 04_week/tasks/ring_buffer/ring_buffer.cpp create mode 100644 04_week/tasks/ring_buffer/ring_buffer.hpp create mode 100644 04_week/tasks/ring_buffer/test.cpp create mode 100644 04_week/tasks/stack/CMakeLists.txt create mode 100644 04_week/tasks/stack/README.md create mode 100644 04_week/tasks/stack/stack.cpp create mode 100644 04_week/tasks/stack/stack.hpp create mode 100644 04_week/tasks/stack/test.cpp diff --git a/04_week/CMakeLists.txt b/04_week/CMakeLists.txt index fcfe9625..b15ca37c 100644 --- a/04_week/CMakeLists.txt +++ b/04_week/CMakeLists.txt @@ -7,9 +7,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # Гарантирует использов set(EXAMPLES_DIR examples) # Определим переменную с именем директории set(TASKS_DIR tasks) -#add_subdirectory(tasks) +add_subdirectory(tasks) # Создать исполняемый файл для каждого примера if (BUILD_EXAMPLES_04_WEEK) -# add_example(struct_examples ${EXAMPLES_DIR}/struct_examples.cpp) -endif() +# add_example(class_examples ${EXAMPLES_DIR}/class_examples.cpp) +endif() \ No newline at end of file diff --git a/04_week/tasks/CMakeLists.txt b/04_week/tasks/CMakeLists.txt new file mode 100644 index 00000000..6ddf92b4 --- /dev/null +++ b/04_week/tasks/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(stack) +add_subdirectory(queue) +add_subdirectory(ring_buffer) +add_subdirectory(phasor) \ No newline at end of file diff --git a/04_week/tasks/phasor/CMakeLists.txt b/04_week/tasks/phasor/CMakeLists.txt new file mode 100644 index 00000000..933d4fae --- /dev/null +++ b/04_week/tasks/phasor/CMakeLists.txt @@ -0,0 +1 @@ +add_gtest(test_phasor test.cpp) \ No newline at end of file diff --git a/04_week/tasks/phasor/README.md b/04_week/tasks/phasor/README.md new file mode 100644 index 00000000..cd6f4453 --- /dev/null +++ b/04_week/tasks/phasor/README.md @@ -0,0 +1,90 @@ +[Комплексная амплитуда]: https://en.wikipedia.org/wiki/Phasor + +# Комплексная амплитуда + +Необходимо реализовать класс `Phasor`, представляющий комплексную амплитуду. +[Комплексная амплитуда] это комплексное число, представляющее синусоидальную +функцию фиксированной частоты с определенной амплитудой и начальной фазой, +не меняющимися во времени. + +Класс предоставляет следующие конструкторы: + +- Конструктор по умолчанию создает нулевой фазор. +- Конструктор, принимающий амплитуду и фазу в радианах. + +Конструкторы с тегами `ExpTag`, `DegTag`, `AlgTag` в качестве третьего параметра: + +- Конструктор с тегом `ExpTag` - делегирует работу основному конструктору +- Конструктор с тегом `DegTag` - из амплитуды и фазы в градусах +- Конструктор с тегом `AlgTag` - из алгебраической формы записи (_real_, _imag_) + +Методы доступа и модификации: + +- Метод `SetPolar` - задать через полярные координаты +- Метод `SetCartesian` - задать через декартовы координаты +- Метод `Magnitude` - получить амплитуды (модуль) +- Метод `Phase` - получить фазу в радианах в диапазоне $(-\pi, \pi]$ +- Метод `PhaseDeg` - получить фазу в градусах в диапазоне $(-180, 180]$ +- Метод `Real` - получить действительную часть +- Метод `Imag` - получить мнимую часть + +Также предоставляются синонимы: + +- Метод `Abs` - синоним метода `Magnitude` +- Метод `Angle` - синоним метода `Phase` +- Метод `AngleDeg` - синоним метода `PhaseDeg` + +Арифметические операторы: + +- Оператор `+` - сложение +- Оператор `-` - вычитание +- Оператор `*` - умножение +- Оператор `/` - деление +- Унарный оператор `-` - разворачивает фазор на 180 градусов ($\pi$ радиан) + +Необходимо перегрузить соответствующие операторы составного присваивания: + +- Оператор `+=` +- Оператор `-=` +- Оператор `*=` +- Оператор `/=` + +Бинарные операторы должны работать как для двух объектов `Phasor`, так и +в операциях с `Phasor` и вещественным числом. + +Операторы сравнения: + +- Оператор `==` +- Оператор `!=` + +Методы специального назначения: + +- Метод `Conj` - возвращает комплексно-сопряженный фазор +- Метод `Inv` - возвращает обратный фазор (1/_phasor_) + +Для удобства необходимо написать функции, создающие объекты `Phasor` от +различных входных параметров: + +- Функция `MakePhasorCartesian` для создания фазора из декартовых координат +- Функция `MakePhasorPolar` для создания фазора из полярных координат +- Функция `MakePhasorPolarDeg` для создания фазора из полярных координат + с углом в градусах + +Реализовать перегрузку оператора `<<` для вывода комплексной амплитуды в +поток в формате: + +`{mag}*e(j*{arg}) [{real} + j*{imag}]`, где + +- `{mag}` - амплитуда +- `{arg}` - аргумент в градусах +- `{real}` - действительная часть +- `{imag}` - мнимая часть + +## Примечание + +- Запрещено использовать класс `std::complex` +- При реализации пригодится заголовочный файл `` +- Рекомендуется определять методы вне класса +- Амплитуда всегда имеет неотрицательное значение +- Операторы `+` и `-` удобно реализовывать в декартовых координатах +- Операторы `*` и `/` удобно реализовывать в полярных координатах diff --git a/04_week/tasks/phasor/phasor.cpp b/04_week/tasks/phasor/phasor.cpp new file mode 100644 index 00000000..dcc0a7bd --- /dev/null +++ b/04_week/tasks/phasor/phasor.cpp @@ -0,0 +1,206 @@ +#include "phasor.hpp" + +double Phasor::NormalizePhase(double phase) { + // Используем std::remainder для нормализации в диапазон (-pi, pi] + constexpr double TWO_PI = 2.0 * M_PI; + double normalized = std::remainder(phase, TWO_PI); + // std::remainder возвращает значение [-pi, pi] + if (normalized <= -M_PI) { + normalized += TWO_PI; + } + return normalized; +} + +Phasor::Phasor() : real_(0.0), imag_(0.0) {} + +Phasor::Phasor(double magnitude, double phase) { + // Если амплитуда отрицательная, делаем её положительной и сдвигаем фазу на pi + if (magnitude < 0) { + magnitude = -magnitude; + phase += M_PI; + } + phase = NormalizePhase(phase); + real_ = magnitude * std::cos(phase); + imag_ = magnitude * std::sin(phase); +} + +Phasor::Phasor(double magnitude, double phase, ExpTag) : Phasor(magnitude, phase) {} + +Phasor::Phasor(double magnitude, double phase_deg, DegTag) + : Phasor(magnitude, phase_deg * M_PI / 180.0) {} + +Phasor::Phasor(double real, double imag, AlgTag) : real_(real), imag_(imag) {} + +void Phasor::SetPolar(double magnitude, double phase) { + if (magnitude < 0) { + magnitude = -magnitude; + phase += M_PI; + } + phase = NormalizePhase(phase); + real_ = magnitude * std::cos(phase); + imag_ = magnitude * std::sin(phase); +} + +void Phasor::SetCartesian(double real, double imag) { + real_ = real; + imag_ = imag; +} + +double Phasor::Magnitude() const { + return std::hypot(real_, imag_); +} + +double Phasor::Phase() const { + return std::atan2(imag_, real_); +} + +double Phasor::PhaseDeg() const { + return Phase() * 180.0 / M_PI; +} + +double Phasor::Real() const { + return real_; +} + +double Phasor::Imag() const { + return imag_; +} + +double Phasor::Abs() const { + return Magnitude(); +} + +double Phasor::Angle() const { + return Phase(); +} + +double Phasor::AngleDeg() const { + return PhaseDeg(); +} + +Phasor Phasor::Conj() const { + return Phasor(real_, -imag_, AlgTag{}); +} + +Phasor Phasor::Inv() const { + double mag_sq = real_ * real_ + imag_ * imag_; + return Phasor(real_ / mag_sq, -imag_ / mag_sq, AlgTag{}); +} + +Phasor Phasor::operator-() const { + return Phasor(-real_, -imag_, AlgTag{}); +} + +Phasor& Phasor::operator+=(const Phasor& other) { + real_ += other.real_; + imag_ += other.imag_; + return *this; +} + +Phasor& Phasor::operator-=(const Phasor& other) { + real_ -= other.real_; + imag_ -= other.imag_; + return *this; +} + +Phasor& Phasor::operator*=(const Phasor& other) { + double new_real = real_ * other.real_ - imag_ * other.imag_; + double new_imag = real_ * other.imag_ + imag_ * other.real_; + real_ = new_real; + imag_ = new_imag; + return *this; +} + +Phasor& Phasor::operator/=(const Phasor& other) { + double denom = other.real_ * other.real_ + other.imag_ * other.imag_; + double new_real = (real_ * other.real_ + imag_ * other.imag_) / denom; + double new_imag = (imag_ * other.real_ - real_ * other.imag_) / denom; + real_ = new_real; + imag_ = new_imag; + return *this; +} + +bool Phasor::operator==(const Phasor& other) const { + constexpr double EPSILON = 1e-9; + return std::abs(real_ - other.real_) < EPSILON && + std::abs(imag_ - other.imag_) < EPSILON; +} + +bool Phasor::operator!=(const Phasor& other) const { + return !(*this == other); +} + +Phasor operator+(const Phasor& lhs, const Phasor& rhs) { + return Phasor(lhs.Real() + rhs.Real(), lhs.Imag() + rhs.Imag(), AlgTag{}); +} + +Phasor operator-(const Phasor& lhs, const Phasor& rhs) { + return Phasor(lhs.Real() - rhs.Real(), lhs.Imag() - rhs.Imag(), AlgTag{}); +} + +Phasor operator*(const Phasor& lhs, const Phasor& rhs) { + double real = lhs.Real() * rhs.Real() - lhs.Imag() * rhs.Imag(); + double imag = lhs.Real() * rhs.Imag() + lhs.Imag() * rhs.Real(); + return Phasor(real, imag, AlgTag{}); +} + +Phasor operator/(const Phasor& lhs, const Phasor& rhs) { + double denom = rhs.Real() * rhs.Real() + rhs.Imag() * rhs.Imag(); + double real = (lhs.Real() * rhs.Real() + lhs.Imag() * rhs.Imag()) / denom; + double imag = (lhs.Imag() * rhs.Real() - lhs.Real() * rhs.Imag()) / denom; + return Phasor(real, imag, AlgTag{}); +} + +Phasor operator+(const Phasor& phasor, double scalar) { + return Phasor(phasor.Real() + scalar, phasor.Imag(), AlgTag{}); +} + +Phasor operator+(double scalar, const Phasor& phasor) { + return phasor + scalar; +} + +Phasor operator-(const Phasor& phasor, double scalar) { + return Phasor(phasor.Real() - scalar, phasor.Imag(), AlgTag{}); +} + +Phasor operator-(double scalar, const Phasor& phasor) { + return Phasor(scalar - phasor.Real(), -phasor.Imag(), AlgTag{}); +} + +Phasor operator*(const Phasor& phasor, double scalar) { + return Phasor(phasor.Real() * scalar, phasor.Imag() * scalar, AlgTag{}); +} + +Phasor operator*(double scalar, const Phasor& phasor) { + return phasor * scalar; +} + +Phasor operator/(const Phasor& phasor, double scalar) { + return Phasor(phasor.Real() / scalar, phasor.Imag() / scalar, AlgTag{}); +} + +Phasor operator/(double scalar, const Phasor& phasor) { + double denom = phasor.Real() * phasor.Real() + phasor.Imag() * phasor.Imag(); + double real = (scalar * phasor.Real()) / denom; + double imag = (-scalar * phasor.Imag()) / denom; + return Phasor(real, imag, AlgTag{}); +} + +Phasor MakePhasorCartesian(double real, double imag) { + return Phasor(real, imag, AlgTag{}); +} + +Phasor MakePhasorPolar(double magnitude, double phase) { + return Phasor(magnitude, phase); +} + +Phasor MakePhasorPolarDeg(double magnitude, double phase_deg) { + return Phasor(magnitude, phase_deg, DegTag{}); +} + +std::ostream& operator<<(std::ostream& os, const Phasor& p) { + os << std::fixed << std::setprecision(3); + os << p.Magnitude() << "*e(j*" << p.PhaseDeg() << ") ["; + os << p.Real() << " + j*" << p.Imag() << "]"; + return os; +} \ No newline at end of file diff --git a/04_week/tasks/phasor/phasor.hpp b/04_week/tasks/phasor/phasor.hpp new file mode 100644 index 00000000..16d20326 --- /dev/null +++ b/04_week/tasks/phasor/phasor.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include +#include + +struct ExpTag {}; +struct DegTag {}; +struct AlgTag {}; + +class Phasor { +private: + double real_ = 0.0; + double imag_ = 0.0; + + // Нормализация фазы + static double NormalizePhase(double phase); + +public: + Phasor(); + Phasor(double magnitude, double phase); + Phasor(double magnitude, double phase, ExpTag); + Phasor(double magnitude, double phase_deg, DegTag); + Phasor(double real, double imag, AlgTag); + + void SetPolar(double magnitude, double phase); + void SetCartesian(double real, double imag); + + double Magnitude() const; + double Phase() const; + double PhaseDeg() const; + + double Real() const; + double Imag() const; + + double Abs() const; + double Angle() const; + double AngleDeg() const; + + Phasor Conj() const; + Phasor Inv() const; + + Phasor operator-() const; + Phasor& operator+=(const Phasor& other); + Phasor& operator-=(const Phasor& other); + Phasor& operator*=(const Phasor& other); + Phasor& operator/=(const Phasor& other); + + bool operator==(const Phasor& other) const; + bool operator!=(const Phasor& other) const; +}; + +Phasor operator+(const Phasor& lhs, const Phasor& rhs); +Phasor operator-(const Phasor& lhs, const Phasor& rhs); +Phasor operator*(const Phasor& lhs, const Phasor& rhs); +Phasor operator/(const Phasor& lhs, const Phasor& rhs); + +Phasor operator+(const Phasor& phasor, double scalar); +Phasor operator+(double scalar, const Phasor& phasor); +Phasor operator-(const Phasor& phasor, double scalar); +Phasor operator-(double scalar, const Phasor& phasor); +Phasor operator*(const Phasor& phasor, double scalar); +Phasor operator*(double scalar, const Phasor& phasor); +Phasor operator/(const Phasor& phasor, double scalar); +Phasor operator/(double scalar, const Phasor& phasor); + +Phasor MakePhasorCartesian(double real, double imag); +Phasor MakePhasorPolar(double magnitude, double phase); +Phasor MakePhasorPolarDeg(double magnitude, double phase_deg); + +std::ostream& operator<<(std::ostream& os, const Phasor& p); diff --git a/04_week/tasks/phasor/test.cpp b/04_week/tasks/phasor/test.cpp new file mode 100644 index 00000000..eb92cfb9 --- /dev/null +++ b/04_week/tasks/phasor/test.cpp @@ -0,0 +1,661 @@ +#include + +#include +#include + +#include "phasor.cpp" + +namespace { + using std::numbers::pi; + constexpr double EPS = 1e-6; +} + + +TEST(PhasorTest, SizeCheck) { + EXPECT_EQ(sizeof(Phasor), 2 * sizeof(double)); +} + +TEST(PhasorTest, DefaultCtor) { + Phasor p; + EXPECT_DOUBLE_EQ(p.Magnitude(), 0.0); + EXPECT_DOUBLE_EQ(p.Phase(), 0.0); + EXPECT_DOUBLE_EQ(p.Real(), 0.0); + EXPECT_DOUBLE_EQ(p.Imag(), 0.0); +} + +TEST(PhasorTest, PolarCtor) { + { + Phasor p(10.0, pi / 4); + EXPECT_NEAR(p.Magnitude(), 10.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 4, EPS); + EXPECT_NEAR(p.PhaseDeg(), 45., EPS); + EXPECT_NEAR(p.Real(), 5.0 * std::sqrt(2), EPS); + EXPECT_NEAR(p.Imag(), 5.0 * std::sqrt(2), EPS); + } + { + Phasor p(10.0, -pi / 4); + EXPECT_NEAR(p.Magnitude(), 10.0, EPS); + EXPECT_NEAR(p.Phase(), -pi / 4, EPS); + EXPECT_NEAR(p.PhaseDeg(), -45., EPS); + EXPECT_NEAR(p.Real(), 5.0 * std::sqrt(2), EPS); + EXPECT_NEAR(p.Imag(), -5.0 * std::sqrt(2), EPS); + } + { + Phasor p(10.0, 3 * pi / 4); + EXPECT_NEAR(p.Magnitude(), 10.0, EPS); + EXPECT_NEAR(p.Phase(), 3 * pi / 4, EPS); + EXPECT_NEAR(p.PhaseDeg(), 135., EPS); + EXPECT_NEAR(p.Real(), -5.0 * std::sqrt(2), EPS); + EXPECT_NEAR(p.Imag(), 5.0 * std::sqrt(2), EPS); + } + { + Phasor p(10.0, -3 * pi / 4); + EXPECT_NEAR(p.Magnitude(), 10.0, EPS); + EXPECT_NEAR(p.Phase(), -3 * pi / 4, EPS); + EXPECT_NEAR(p.PhaseDeg(), -135., EPS); + EXPECT_NEAR(p.Real(), -5.0 * std::sqrt(2), EPS); + EXPECT_NEAR(p.Imag(), -5.0 * std::sqrt(2), EPS); + } +} + +TEST(PhasorTest, NegativeMagnitude) { + { + Phasor p(-10.0, pi / 4); + EXPECT_NEAR(p.Magnitude(), 10.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 4 - pi, EPS); + EXPECT_NEAR(p.PhaseDeg(), -135., EPS); + EXPECT_NEAR(p.Real(), -5.0 * std::sqrt(2), EPS); + EXPECT_NEAR(p.Imag(), -5.0 * std::sqrt(2), EPS); + } + { + Phasor p(-10.0, -pi / 4); + EXPECT_NEAR(p.Magnitude(), 10.0, EPS); + EXPECT_NEAR(p.Phase(), - pi / 4 + pi, EPS); + EXPECT_NEAR(p.PhaseDeg(), 135., EPS); + EXPECT_NEAR(p.Real(), -5.0 * std::sqrt(2), EPS); + EXPECT_NEAR(p.Imag(), 5.0 * std::sqrt(2), EPS); + } + { + Phasor p(-10.0, 3 * pi / 4); + EXPECT_NEAR(p.Magnitude(), 10.0, EPS); + EXPECT_NEAR(p.Phase(), - pi / 4, EPS); + EXPECT_NEAR(p.PhaseDeg(), -45., EPS); + EXPECT_NEAR(p.Real(), 5.0 * std::sqrt(2), EPS); + EXPECT_NEAR(p.Imag(), -5.0 * std::sqrt(2), EPS); + } + { + Phasor p(-10.0, -3 * pi / 4); + EXPECT_NEAR(p.Magnitude(), 10.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 4, EPS); + EXPECT_NEAR(p.PhaseDeg(), 45., EPS); + EXPECT_NEAR(p.Real(), 5.0 * std::sqrt(2), EPS); + EXPECT_NEAR(p.Imag(), 5.0 * std::sqrt(2), EPS); + } +} + +TEST(PhasorTest, ExpTagConstructor) { + { + Phasor p(5.0, pi / 3, ExpTag{}); + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 3, EPS); + } + { + Phasor p(-5.0, pi / 3, ExpTag{}); + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.Phase(), - 2 * pi / 3, EPS); + } + { + Phasor p(5.0, 2 * pi / 3, ExpTag{}); + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.Phase(), 2 * pi / 3, EPS); + } + { + Phasor p(5.0, 7 * pi / 3, ExpTag{}); + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 3, EPS); + } +} + +TEST(PhasorTest, DegTagConstructor) { + { + Phasor p(5.0, 60.0, DegTag{}); + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.PhaseDeg(), 60.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 3, EPS); + } + { + Phasor p(5.0, -60.0, DegTag{}); + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.PhaseDeg(), -60.0, EPS); + EXPECT_NEAR(p.Phase(), -pi / 3, EPS); + } + { + Phasor p(-5.0, -60.0, DegTag{}); + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.PhaseDeg(), 120.0, EPS); + EXPECT_NEAR(p.Phase(), 2 * pi / 3, EPS); + } + { + Phasor p(5.0, -360.0, DegTag{}); + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.PhaseDeg(), 0.0, EPS); + EXPECT_NEAR(p.Phase(), 0.0, EPS); + } +} + +TEST(PhasorTest, AlgTagConstructor) { + { + Phasor p(3.0, 4.0, AlgTag{}); + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.Phase(), std::atan2(4.0, 3.0), EPS); + EXPECT_DOUBLE_EQ(p.Real(), 3.0); + EXPECT_DOUBLE_EQ(p.Imag(), 4.0); + } + { + Phasor p(std::sqrt(2), std::sqrt(2), AlgTag{}); + EXPECT_NEAR(p.Magnitude(), 2.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 4, EPS); + EXPECT_DOUBLE_EQ(p.Real(), std::sqrt(2)); + EXPECT_DOUBLE_EQ(p.Imag(), std::sqrt(2)); + } + { + Phasor p(-std::sqrt(2), -std::sqrt(2), AlgTag{}); + EXPECT_NEAR(p.Magnitude(), 2.0, EPS); + EXPECT_NEAR(p.Phase(), -3 * pi / 4, EPS); + EXPECT_DOUBLE_EQ(p.Real(), -std::sqrt(2)); + EXPECT_DOUBLE_EQ(p.Imag(), -std::sqrt(2)); + } + { + Phasor p(std::sqrt(2), -std::sqrt(2), AlgTag{}); + EXPECT_NEAR(p.Magnitude(), 2.0, EPS); + EXPECT_NEAR(p.Phase(), -pi / 4, EPS); + EXPECT_DOUBLE_EQ(p.Real(), std::sqrt(2)); + EXPECT_DOUBLE_EQ(p.Imag(), -std::sqrt(2)); + } + { + Phasor p(-std::sqrt(2), std::sqrt(2), AlgTag{}); + EXPECT_NEAR(p.Magnitude(), 2.0, EPS); + EXPECT_NEAR(p.Phase(), 3 * pi / 4, EPS); + EXPECT_DOUBLE_EQ(p.Real(), -std::sqrt(2)); + EXPECT_DOUBLE_EQ(p.Imag(), std::sqrt(2)); + } +} + +TEST(PhasorTest, PhaseNormalization) { + Phasor p1(1.0, 3 * pi / 2); + EXPECT_NEAR(p1.Phase(), -pi / 2, EPS); + EXPECT_NEAR(p1.PhaseDeg(), -90., EPS); + + Phasor p2(1.0, -3 * pi / 2); + EXPECT_NEAR(p2.Phase(), pi / 2, EPS); + EXPECT_NEAR(p2.PhaseDeg(), 90., EPS); + + Phasor p3(1.0, 2 * pi + pi / 4); + EXPECT_NEAR(p3.Phase(), pi / 4, EPS); + EXPECT_NEAR(p3.PhaseDeg(), 45., EPS); +} + +TEST(PhasorTest, Synonyms) { + Phasor p(3.0, 4.0,AlgTag{}); + EXPECT_DOUBLE_EQ(p.Magnitude(), p.Abs()); + EXPECT_DOUBLE_EQ(p.Phase(), p.Angle()); + EXPECT_DOUBLE_EQ(p.PhaseDeg(), p.AngleDeg()); +} + +TEST(PhasorTest, SetPolar) { + Phasor p; + p.SetPolar(10.0, pi / 6); + + EXPECT_NEAR(p.Magnitude(), 10.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 6, EPS); + EXPECT_NEAR(p.Real(), 10.0 * std::sqrt(3) / 2, EPS); + EXPECT_NEAR(p.Imag(), 5.0, EPS); +} + +TEST(PhasorTest, SetCartesian) { + Phasor p; + p.SetCartesian(1.0, sqrt(3.0)); + + EXPECT_NEAR(p.Magnitude(), 2.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 3, EPS); + EXPECT_DOUBLE_EQ(p.Real(), 1.0); + EXPECT_DOUBLE_EQ(p.Imag(), std::sqrt(3.0)); +} + +TEST(MathPhasorTest, UnaryMinus) { + Phasor p(3.0, 4.0, AlgTag{}); + Phasor p2 = -p; + + EXPECT_DOUBLE_EQ(p2.Real(), -3.0); + EXPECT_DOUBLE_EQ(p2.Imag(), -4.0); + EXPECT_NEAR(p2.Magnitude(), p.Magnitude(), EPS); + EXPECT_NEAR(p2.Phase(), p.Phase() - pi, EPS); +} + +TEST(MathPhasorTest, Addition) { + Phasor p1(1.0, 2.0, AlgTag{}); + Phasor p2(3.0, 4.0, AlgTag{}); + Phasor res = p1 + p2; + + Phasor expected(4.0, 6.0, AlgTag{}); + EXPECT_EQ(res, expected); +} + +TEST(MathPhasorTest, Subtraction) { + Phasor p1(5.0, 6.0, AlgTag{}); + Phasor p2(2.0, -3.0, AlgTag{}); + Phasor res = p1 - p2; + + Phasor expected(3.0, 9.0, AlgTag{}); + EXPECT_EQ(res, expected); +} + +TEST(MathPhasorTest, Multiplication) { + Phasor p1(1.0, 2.0, AlgTag{}); + Phasor p2(3.0, 4.0, AlgTag{}); + Phasor res = p1 * p2; + + EXPECT_NEAR(res.Real(), -5.0, EPS); + EXPECT_NEAR(res.Imag(), 10.0, EPS); + + Phasor p3(2.0, 60.0, DegTag{}); + Phasor p4(3.0, 30.0, DegTag{}); + res = p3 * p4; + + EXPECT_NEAR(res.Magnitude(), 6.0, EPS); + EXPECT_NEAR(res.PhaseDeg(), 90.0, EPS); +} + +TEST(MathPhasorTest, Division) { + Phasor p1(3.0, 4.0, AlgTag{}); + Phasor p2(1.0, 1.0, AlgTag{}); + Phasor res = p1 / p2; + + EXPECT_NEAR(res.Real(), 3.5, EPS); + EXPECT_NEAR(res.Imag(), 0.5, EPS); + + Phasor p3(6.0, 90.0, DegTag{}); + Phasor p4(3.0, 30.0, DegTag{}); + res = p3 / p4; + + EXPECT_NEAR(res.Magnitude(), 2.0, EPS); + EXPECT_NEAR(res.PhaseDeg(), 60.0, EPS); +} + +TEST(MathPhasorTest, CompoundAssignment) { + Phasor p1(2.0, 3.0, AlgTag{}); + Phasor p2(1.0, 1.0, AlgTag{}); + + p1 += p2; + EXPECT_DOUBLE_EQ(p1.Real(), 3.0); + EXPECT_DOUBLE_EQ(p1.Imag(), 4.0); + + p1 -= p2; + EXPECT_DOUBLE_EQ(p1.Real(), 2.0); + EXPECT_DOUBLE_EQ(p1.Imag(), 3.0); + + p1 *= Phasor(2.0, 0.0, DegTag{}); + EXPECT_NEAR(p1.Magnitude(), 2.0 * sqrt(13.0), EPS); + EXPECT_DOUBLE_EQ(p1.Phase(), atan2(3.0, 2.0)); + + p1 /= Phasor(2.0, 0.0, DegTag{}); + EXPECT_NEAR(p1.Magnitude(), std::sqrt(13.0), EPS); + EXPECT_DOUBLE_EQ(p1.Phase(), std::atan2(3.0, 2.0)); +} + +TEST(MathPhasorTest, ScalarAddition) { + Phasor p(1.0, 2.0, AlgTag{}); + Phasor res = p + 3.0; + EXPECT_DOUBLE_EQ(res.Real(), 4.0); + EXPECT_DOUBLE_EQ(res.Imag(), 2.0); + + res = -3.0 + p; + EXPECT_DOUBLE_EQ(res.Real(), -2.0); + EXPECT_DOUBLE_EQ(res.Imag(), 2.0); +} + +TEST(MathPhasorTest, ScalarSubtraction) { + Phasor p(5.0, 2.0, AlgTag{}); + Phasor res = p - 7.0; + EXPECT_DOUBLE_EQ(res.Real(), -2.0); + EXPECT_DOUBLE_EQ(res.Imag(), 2.0); + + res = 3.0 - p; + EXPECT_DOUBLE_EQ(res.Real(), -2.0); + EXPECT_DOUBLE_EQ(res.Imag(), -2.0); +} + +TEST(MathPhasorTest, ScalarMultiplication) { + Phasor p(2.0, 60.0, DegTag{}); + + Phasor res = p * 3.0; + EXPECT_NEAR(res.Magnitude(), 6.0, EPS); + EXPECT_NEAR(res.PhaseDeg(), 60.0, EPS); + + res = -2.0 * p; + EXPECT_NEAR(res.Magnitude(), 4.0, EPS); + EXPECT_NEAR(res.PhaseDeg(), 60.0 - 180.0, EPS); + + res = 3.0 * p; + EXPECT_NEAR(res.Magnitude(), 6.0, EPS); + EXPECT_NEAR(res.PhaseDeg(), 60.0, EPS); +} + +TEST(MathPhasorTest, ScalarDivision) { + Phasor p(6.0, 60.0, DegTag{}); + + Phasor res = p / 2.0; + EXPECT_NEAR(res.Magnitude(), 3.0, EPS); + EXPECT_NEAR(res.PhaseDeg(), 60.0, EPS); + + res = 12.0 / p; + EXPECT_NEAR(res.Magnitude(), 2.0, EPS); + EXPECT_NEAR(res.PhaseDeg(), -60.0, EPS); +} + +TEST(PhasorTest, Conjugate) { + Phasor p(3.0, 4.0,AlgTag{}); + Phasor conj = p.Conj(); + + EXPECT_DOUBLE_EQ(conj.Real(), p.Real()); + EXPECT_DOUBLE_EQ(conj.Imag(), -p.Imag()); + EXPECT_DOUBLE_EQ(conj.Magnitude(), p.Magnitude()); + EXPECT_DOUBLE_EQ(conj.Phase(), -p.Phase()); + + Phasor res = p * conj; + EXPECT_NEAR(res.Imag(), 0.0, EPS); + EXPECT_NEAR(res.Real(), p.Magnitude() * p.Magnitude(), EPS); +} + +TEST(PhasorTest, Inverse) { + Phasor p(4.0, 60.0, DegTag{}); + Phasor inv = p.Inv(); + + EXPECT_NEAR(inv.Magnitude(), 0.25, EPS); + EXPECT_NEAR(inv.PhaseDeg(), -60.0, EPS); + + Phasor res = p * inv; + EXPECT_NEAR(res.Magnitude(), 1.0, EPS); + EXPECT_NEAR(res.Phase(), 0.0, EPS); +} + +TEST(PhasorTest, Equality) { + Phasor p1(1.0, 2.0, AlgTag{}); + Phasor p2(1.0, 2.0, AlgTag{}); + Phasor p3(1.0, 2.000000001, AlgTag{}); + + EXPECT_TRUE(p1 == p2); + EXPECT_FALSE(p1 != p2); + EXPECT_FALSE(p1 == p3); + EXPECT_TRUE(p1 != p3); + + Phasor p4(1.0, 45.0, DegTag{}); + Phasor p5(std::cos(pi / 4), std::sin(pi / 4), AlgTag{}); + EXPECT_TRUE(p4 == p5); +} + +TEST(PhasorTest, FactoryFunctions) { + Phasor p1 = MakePhasorCartesian(3.0, 4.0); + EXPECT_DOUBLE_EQ(p1.Real(), 3.0); + EXPECT_DOUBLE_EQ(p1.Imag(), 4.0); + + Phasor p2 = MakePhasorPolar(5.0, pi / 3); + EXPECT_NEAR(p2.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p2.Phase(), pi / 3, EPS); + + Phasor p3 = MakePhasorPolarDeg(5.0, 60.0); + EXPECT_NEAR(p3.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p3.PhaseDeg(), 60.0, EPS); +} + +TEST(PhasorTest, OutputOperator) { + Phasor p(5.0, 45.0, DegTag{}); + std::stringstream ss; + ss << p; + + std::string output = ss.str(); + + EXPECT_TRUE(output.find("5.000") != std::string::npos); + EXPECT_TRUE(output.find("45.000") != std::string::npos); + EXPECT_TRUE(output.find("*e(j*") != std::string::npos); + EXPECT_TRUE(output.find(") [") != std::string::npos); + EXPECT_TRUE(output.find(" + j*") != std::string::npos); + EXPECT_TRUE(output.find("]") != std::string::npos); +} + +TEST(MathPhasorTest, ComplexCalculations) { + Phasor z1(3.0, 30.0, DegTag{}); + Phasor z2(4.0, 60.0, DegTag{}); + Phasor z3(2.0, -45.0, DegTag{}); + + Phasor result = (z1 + z2) * z3 / 2.0; + + EXPECT_NEAR(result.Magnitude(), 6.7664, 0.0001); + EXPECT_NEAR(result.PhaseDeg(), 2.1921, 0.0001); + EXPECT_NEAR(result.Magnitude(), 6.7664, 0.0001); + EXPECT_NEAR(result.Real(), 6.7615, 0.0001); + EXPECT_NEAR(result.Imag(), 0.2588, 0.0001); +} + +TEST(MathPhasorTest, CommutativeProperty) { + Phasor p1(2.0, 3.0, AlgTag{}); + Phasor p2(4.0, 5.0,AlgTag{}); + + EXPECT_TRUE(p1 + p2 == p2 + p1); + EXPECT_TRUE(p1 * p2 == p2 * p1); +} + +TEST(MathPhasorTest, AssociativeProperty) { + Phasor p1(1.0, 2.0, AlgTag{}); + Phasor p2(3.0, 4.0, AlgTag{}); + Phasor p3(5.0, 6.0, AlgTag{}); + + Phasor left = (p1 + p2) + p3; + Phasor right = p1 + (p2 + p3); + EXPECT_TRUE(left == right); + + left = (p1 * p2) * p3; + right = p1 * (p2 * p3); + EXPECT_TRUE(left == right); +} + +TEST(MathPhasorTest, DistributiveProperty) { + Phasor p1(1.0, 2.0, AlgTag{}); + Phasor p2(3.0, 4.0, AlgTag{}); + Phasor p3(5.0, 6.0, AlgTag{}); + + Phasor left = p1 * (p2 + p3); + Phasor right = p1 * p2 + p1 * p3; + EXPECT_TRUE(left == right); +} + +TEST(PhasorTest, SpecialAngles) { + Phasor p1(1.0, 0.0, DegTag{}); + EXPECT_NEAR(p1.Real(), 1.0, EPS); + EXPECT_NEAR(p1.Imag(), 0.0, EPS); + + Phasor p2(1.0, 90.0, DegTag{}); + EXPECT_NEAR(p2.Real(), 0.0, EPS); + EXPECT_NEAR(p2.Imag(), 1.0, EPS); + + Phasor p3(1.0, 180.0, DegTag{}); + EXPECT_NEAR(p3.Real(), -1.0, EPS); + EXPECT_NEAR(p3.Imag(), 0.0, EPS); + EXPECT_NEAR(p3.PhaseDeg(), 180.0, EPS); + + p3 = Phasor(1.0, -180.0, DegTag{}); + EXPECT_NEAR(p3.Real(), -1.0, EPS); + EXPECT_NEAR(p3.Imag(), 0.0, EPS); + EXPECT_NEAR(p3.PhaseDeg(), 180.0, EPS); + + Phasor p4(1.0, -90.0, DegTag{}); + EXPECT_NEAR(p4.Real(), 0.0, EPS); + EXPECT_NEAR(p4.Imag(), -1.0, EPS); +} + +TEST(ConstPhasorTest, ConstPhasorMethods) { + const Phasor p(5.0, 60.0, DegTag{}); + + EXPECT_NEAR(p.Magnitude(), 5.0, EPS); + EXPECT_NEAR(p.Phase(), pi / 3, EPS); + EXPECT_NEAR(p.PhaseDeg(), 60.0, EPS); + EXPECT_NEAR(p.Real(), 2.5, EPS); + EXPECT_NEAR(p.Imag(), 5.0 * std::sqrt(3) / 2, EPS); + + EXPECT_NEAR(p.Abs(), 5.0, EPS); + EXPECT_NEAR(p.Angle(), p.Phase(), EPS); + EXPECT_NEAR(p.AngleDeg(), 60.0, EPS); +} + +TEST(ConstPhasorTest, ConstPhasorComparison) { + const Phasor p1(3.0, 45.0, DegTag{}); + const Phasor p2(3.0, 45.0, DegTag{}); + const Phasor p3(4.0, 45.0, DegTag{}); + + EXPECT_TRUE(p1 == p2); + EXPECT_FALSE(p1 != p2); + EXPECT_FALSE(p1 == p3); + EXPECT_TRUE(p1 != p3); +} + +TEST(ConstPhasorTest, ConstPhasorUnaryOperators) { + const Phasor p(3.0, 30.0, DegTag{}); + + Phasor p2 = -p; + EXPECT_NEAR(p2.Magnitude(), p.Magnitude(), EPS); + EXPECT_NEAR(p2.Phase(), p.Phase() - pi, EPS); +} + +TEST(ConstPhasorTest, ConstPhasorBinaryOperators) { + const Phasor p1(2.0, 30.0, DegTag{}); + const Phasor p2(3.0, 60.0, DegTag{}); + + Phasor res = p1 + p2; + EXPECT_NEAR(res.Magnitude(), 4.8366, 0.0001); + EXPECT_NEAR(res.Phase(), 0.8389, 0.0001); + EXPECT_NEAR(res.PhaseDeg(), 48.0675, 0.0001); + EXPECT_NEAR(res.Real(), 3.2321, 0.0001); + EXPECT_NEAR(res.Imag(), 3.5981, 0.0001); + + res = p1 - p2; + EXPECT_NEAR(res.Magnitude(), 1.6148, 0.0001); + EXPECT_NEAR(res.Phase(), -1.4266, 0.0001); + EXPECT_NEAR(res.PhaseDeg(), -81.7380, 0.0001); + EXPECT_NEAR(res.Real(), 0.2321, 0.0001); + EXPECT_NEAR(res.Imag(), -1.5981, 0.0001); + + res = p1 * p2; + EXPECT_NEAR(res.Magnitude(), 6.0, 0.0001); + EXPECT_NEAR(res.Phase(), 1.5708, 0.0001); + EXPECT_NEAR(res.PhaseDeg(), 90.0000, 0.0001); + EXPECT_NEAR(res.Real(), 0.0000, 0.0001); + EXPECT_NEAR(res.Imag(), 6.0000, 0.0001); + + res = p1 / p2; + EXPECT_NEAR(res.Magnitude(), 0.6667, 0.0001); + EXPECT_NEAR(res.Phase(), -0.5236, 0.0001); + EXPECT_NEAR(res.PhaseDeg(), -30.0000, 0.0001); + EXPECT_NEAR(res.Real(), 0.5774, 0.0001); + EXPECT_NEAR(res.Imag(), -0.3333, 0.0001); + + Phasor p3 = p1 + 2.0; + Phasor p4 = 2.0 + p1; + Phasor p5 = p1 * 2.0; + Phasor p6 = 2.0 * p1; + + EXPECT_TRUE(p3 == p4); + EXPECT_TRUE(p5 == p6); +} + +TEST(ConstPhasorTest, ConstPhasorSpecialMethods) { + const Phasor p(4.0, 45.0, DegTag{}); + + Phasor conj = p.Conj(); + EXPECT_NEAR(conj.Real(), p.Real(), EPS); + EXPECT_NEAR(conj.Imag(), -p.Imag(), EPS); + + Phasor inv = p.Inv(); + EXPECT_NEAR(inv.Magnitude(), 1.0/p.Magnitude(), EPS); + EXPECT_NEAR(inv.Phase(), -p.Phase(), EPS); +} + +TEST(ConstPhasorTest, ConstPhasorInExpression) { + const Phasor a(3.0, 0.0, DegTag{}); + const Phasor b(4.0, 90.0, DegTag{}); + + Phasor result = (a * a.Conj() + b * b.Conj()) / 2.0; + + EXPECT_NEAR(result.Magnitude(), 12.5, EPS); + EXPECT_NEAR(result.Phase(), 0.0, EPS); +} + +TEST(ConstPhasorTest, ConstPhasorVectorOperations) { + const Phasor phasors[] = { + Phasor(1.0, 0.0, DegTag{}), + Phasor(1.0, 90.0, DegTag{}), + Phasor(1.0, 180.0, DegTag{}), + Phasor(1.0, 270.0, DegTag{}) + }; + Phasor sum; + for (const auto& p : phasors) { + sum += p; + } + EXPECT_NEAR(sum.Magnitude(), 0.0, EPS); +} + +TEST(ConstPhasorTest, ConstPhasorOutput) { + const Phasor p(2.5, 30.0, DegTag{}); + std::stringstream ss; + + ss << p; + + std::string output = ss.str(); + EXPECT_TRUE(output.find("2.500") != std::string::npos); + EXPECT_TRUE(output.find("30.000") != std::string::npos); +} + +TEST(ConstPhasorTest, ConstPhasorAssignmentFromConst) { + const Phasor source(10.0, 45.0, DegTag{}); + Phasor target; + + target = source; + + EXPECT_TRUE(target == source); + EXPECT_NEAR(target.Magnitude(), 10.0, EPS); + EXPECT_NEAR(target.PhaseDeg(), 45.0, EPS); +} + +TEST(ConstPhasorTest, MixedConstAndNonConst) { + const Phasor cp(3.0, 60.0, DegTag{}); + Phasor ncp(4.0, 30.0, DegTag{}); + + Phasor sum1 = cp + ncp; + Phasor sum2 = ncp + cp; + + EXPECT_TRUE(sum1 == sum2); + + Phasor prod1 = cp * ncp; + Phasor prod2 = ncp * cp; + + EXPECT_TRUE(prod1 == prod2); + + ncp += cp; + ncp -= cp; + ncp *= cp; + ncp /= cp; + + EXPECT_NEAR(ncp.Magnitude(), 4.0, EPS); + EXPECT_NEAR(ncp.PhaseDeg(), 30.0, EPS); +} + +TEST(ConstPhasorTest, ConstPhasorChainOperations) { + const Phasor a(2.0, 0.0, DegTag{}); + const Phasor b(3.0, 90.0, DegTag{}); + const Phasor c(4.0, 180.0, DegTag{}); + + Phasor result = a.Conj() * b + c / a - b.Inv(); + EXPECT_TRUE(result.Magnitude() >= 0.0); + + result = (a + b) * c.Conj() / 2.0; + EXPECT_TRUE(result.Magnitude() >= 0.0); +} diff --git a/04_week/tasks/queue/CMakeLists.txt b/04_week/tasks/queue/CMakeLists.txt new file mode 100644 index 00000000..0c8eae8a --- /dev/null +++ b/04_week/tasks/queue/CMakeLists.txt @@ -0,0 +1 @@ +add_gtest(test_queue test.cpp) \ No newline at end of file diff --git a/04_week/tasks/queue/README.md b/04_week/tasks/queue/README.md new file mode 100644 index 00000000..9fffd157 --- /dev/null +++ b/04_week/tasks/queue/README.md @@ -0,0 +1,46 @@ +[Очередь]: https://en.wikipedia.org/wiki/Queue_(abstract_data_type) + +# Очередь + +[Очередь] представляет собой FIFO (First Input First Output) структуру данных. +Необходимо реализовать класс `Queue`, который представляет собой очередь, +реализованную на **двух** контейнерах `std::vector`, используемых в качестве +стека. + +Элементы добавляются в конец одного контейнера (назовем его входным). +Достаются элементы из конца второго контейнера (назовем его выходным). +Если элементов в выходном контейнере нет, то перекладываются все элементы из +входного контейнера с конца в конец выходного контейнера (словно перекладываются +элементы из одного стека в другой). При таком перекладывании первый элемент +входного контейнера находится на верхушке выходного и его легко убрать за `O(1)`. +Все методы при такой реализации будут работать за амортизированную `O(1)`. + +Класс предоставляет следующий функционал: + +- Конструктор от `std::stack` +- Конструктор от `std::vector` +- Конструктор от `std::initializer_list` +- Конструктор от размера очереди выделяет достаточное количество памяти для работы + с очередью заданного размера без реалокации памяти. +- Метод `Push` - добавляет элемент в конец очереди +- Метод `Pop` - убирает элемент из начала очереди +- Метод `Front` - обеспечивает доступ на запись и чтение к элементу в начале очереди +- Метод `Back` - обеспечивает доступ на запись и чтение к элементу в конце очереди +- Метод `Empty` - возвращает результат проверки очереди на отсутствие элементов +- Метод `Size` - возвращает количество элементов в очереди +- Метод `Clear` - очищает очередь +- Метод `Swap` - меняется элементами с другой очередью (без копирования) +- Оператор `==` - сравнение очереди на равенство +- Оператор `!=` - сравнение очереди на неравенство + +Вызов метода `Pop` от пустой очереди является корректной операцией. Метод должен +возвращать `true` или `false` в зависимости от того выполнилась операция или нет. + +Вызов `Front` и `Back` от пустой очереди не ограничивается и ведет к **UB**. + +## Примечание + +- Запрещено использовать `std::queue`, `std::deque`, `std::list` +- Рекомендуется определять методы вне класса +- Некоторые методы могут потребовать перегрузки +- При необходимости вспомогательные методы реализуются в закрытой части класса \ No newline at end of file diff --git a/04_week/tasks/queue/queue.cpp b/04_week/tasks/queue/queue.cpp new file mode 100644 index 00000000..cc0e007b --- /dev/null +++ b/04_week/tasks/queue/queue.cpp @@ -0,0 +1,122 @@ +#include "queue.hpp" + +void Queue::TransferIfNeeded() const { + if (output_stack_.empty() && input_stack_.empty() == false) { + while (input_stack_.empty() == false) { + output_stack_.push_back(input_stack_.back()); + input_stack_.pop_back(); + } + } +} + +Queue::Queue(size_t capacity) { + input_stack_.reserve(capacity); +} + +Queue::Queue(const std::vector& vec) { + input_stack_ = vec; +} + +Queue::Queue(std::stack s) { + std::vector temp; + temp.reserve(s.size()); + while (s.empty() == false) { + temp.push_back(s.top()); + s.pop(); + } + std::reverse(temp.begin(), temp.end()); + input_stack_ = std::move(temp); +} + +Queue::Queue(std::initializer_list init) { + input_stack_.assign(init.begin(), init.end()); +} + +void Queue::Push(int value) { + input_stack_.push_back(value); +} + +bool Queue::Pop() { + TransferIfNeeded(); + if (output_stack_.empty()) { + return false; + } + output_stack_.pop_back(); + return true; +} + +int& Queue::Front() { + TransferIfNeeded(); + if (output_stack_.empty()) { + return dummy_; + } + return output_stack_.back(); +} + +const int& Queue::Front() const { + TransferIfNeeded(); + if (output_stack_.empty()) { + return dummy_; + } + return output_stack_.back(); +} + +int& Queue::Back() { + if (input_stack_.empty() == false) { + return input_stack_.back(); + } + if (output_stack_.empty() == false) { + return output_stack_.front(); + } + return dummy_; +} + +const int& Queue::Back() const { + if (input_stack_.empty() == false) { + return input_stack_.back(); + } + if (output_stack_.empty() == false) { + return output_stack_.front(); + } + return dummy_; +} + +bool Queue::Empty() const { + return input_stack_.empty() && output_stack_.empty(); +} + +size_t Queue::Size() const { + return input_stack_.size() + output_stack_.size(); +} + +void Queue::Clear() { + input_stack_.clear(); + output_stack_.clear(); +} + +void Queue::Swap(Queue& other) { + input_stack_.swap(other.input_stack_); + output_stack_.swap(other.output_stack_); +} + +bool Queue::operator==(const Queue& other) const { + if (Size() != other.Size()) { + return false; + } + + Queue a = *this; + Queue b = other; + + while (a.Empty() == false) { + if (a.Front() != b.Front()) { + return false; + } + a.Pop(); + b.Pop(); + } + return true; +} + +bool Queue::operator!=(const Queue& other) const { + return (*this == other) == false; +} \ No newline at end of file diff --git a/04_week/tasks/queue/queue.hpp b/04_week/tasks/queue/queue.hpp new file mode 100644 index 00000000..ae2fde4a --- /dev/null +++ b/04_week/tasks/queue/queue.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include +#include + +class Queue { +private: + mutable std::vector input_stack_; + mutable std::vector output_stack_; + mutable int dummy_ = 0; + + void TransferIfNeeded() const; + +public: + Queue() = default; + + explicit Queue(size_t capacity); + explicit Queue(const std::vector& vec); + explicit Queue(std::stack s); + Queue(std::initializer_list init); + + void Push(int value); + bool Pop(); + int& Front(); + const int& Front() const; + int& Back(); + const int& Back() const; + bool Empty() const; + size_t Size() const; + void Clear(); + void Swap(Queue& other); + + bool operator==(const Queue& other) const; + bool operator!=(const Queue& other) const; +}; \ No newline at end of file diff --git a/04_week/tasks/queue/test.cpp b/04_week/tasks/queue/test.cpp new file mode 100644 index 00000000..3bc5e562 --- /dev/null +++ b/04_week/tasks/queue/test.cpp @@ -0,0 +1,446 @@ +#include + +#include +#include + +#include "queue.cpp" + + +TEST(QueueTest, DefaultCtor) { + Queue q; + EXPECT_TRUE(q.Empty()); + EXPECT_EQ(q.Size(), 0); +} + +TEST(QueueTest, VectorCtor) { + std::vector vec = {1, 2, 3, 4, 5}; + Queue q(vec); + + EXPECT_EQ(q.Size(), 5); + EXPECT_EQ(q.Front(), 1); + EXPECT_EQ(q.Back(), 5); + for (size_t i = 0; i < vec.size(); ++i) { + EXPECT_EQ(q.Front(), vec[i]); + EXPECT_TRUE(q.Pop()); + } + EXPECT_TRUE(q.Empty()); + EXPECT_EQ(q.Size(), 0); +} + +TEST(QueueTest, StackCtor) { + std::vector vec = {1, 2, 3, 4, 5}; + std::stack s; + for (size_t i = 0; i < vec.size(); ++i) { + s.push(vec[i]); + } + Queue q(s); + + EXPECT_EQ(q.Size(), 5); + EXPECT_EQ(q.Front(), 1); + EXPECT_EQ(q.Back(), 5); + for (size_t i = 0; i < vec.size(); ++i) { + EXPECT_EQ(q.Front(), vec[i]); + EXPECT_TRUE(q.Pop()); + } + EXPECT_TRUE(q.Empty()); + EXPECT_EQ(q.Size(), 0); +} + +TEST(QueueTest, InitializerListCtor) { + Queue q = {10, 20, 30, 40, 50}; + + EXPECT_EQ(q.Size(), 5); + EXPECT_EQ(q.Front(), 10); + EXPECT_EQ(q.Back(), 50); + for (size_t i = 0; i < 5; ++i) { + EXPECT_EQ(q.Front(), (i + 1) * 10); + EXPECT_TRUE(q.Pop()); + } + EXPECT_TRUE(q.Empty()); + EXPECT_EQ(q.Size(), 0); +} + +TEST(QueueTest, PushAndSize) { + Queue q; + + q.Push(10); + EXPECT_EQ(q.Size(), 1); + EXPECT_FALSE(q.Empty()); + + q.Push(20); + EXPECT_EQ(q.Size(), 2); + + q.Push(30); + EXPECT_EQ(q.Size(), 3); +} + +TEST(QueueTest, Pop) { + Queue q = {1, 2, 3, 4, 5}; + + EXPECT_TRUE(q.Pop()); + EXPECT_EQ(q.Size(), 4); + EXPECT_EQ(q.Front(), 2); + + EXPECT_TRUE(q.Pop()); + EXPECT_EQ(q.Size(), 3); + EXPECT_EQ(q.Front(), 3); + + while (!q.Empty()) { + EXPECT_TRUE(q.Pop()); + } + EXPECT_FALSE(q.Pop()); + + EXPECT_TRUE(q.Empty()); + EXPECT_EQ(q.Size(), 0); +} + +TEST(QueueTest, Front) { + Queue q = {10, 20, 30}; + + EXPECT_EQ(q.Front(), 10); + q.Front() = 100; + EXPECT_EQ(q.Front(), 100); + q.Pop(); + + EXPECT_EQ(q.Front(), 20); + q.Front() = 200; + EXPECT_EQ(q.Front(), 200); + q.Pop(); + + EXPECT_EQ(q.Front(), 30); + q.Front() = 300; + EXPECT_EQ(q.Front(), 300); +} + +TEST(QueueTest, Back) { + Queue q = {10, 20, 30}; + + EXPECT_EQ(q.Back(), 30); + q.Back() = 300; + EXPECT_EQ(q.Back(), 300); + + q.Push(40); + EXPECT_EQ(q.Back(), 40); + q.Back() = 400; + EXPECT_EQ(q.Back(), 400); + + q.Pop(); + EXPECT_EQ(q.Back(), 400); +} + +TEST(QueueTest, FrontBack) { + Queue q; + + q.Push(1); + EXPECT_EQ(q.Front(), 1); + EXPECT_EQ(q.Back(), 1); + + q.Push(2); + EXPECT_EQ(q.Front(), 1); + EXPECT_EQ(q.Back(), 2); + + q.Push(3); + EXPECT_EQ(q.Front(), 1); + EXPECT_EQ(q.Back(), 3); + + q.Pop(); + EXPECT_EQ(q.Front(), 2); + EXPECT_EQ(q.Back(), 3); + + q.Pop(); + EXPECT_EQ(q.Front(), 3); + EXPECT_EQ(q.Back(), 3); +} + +TEST(QueueTest, FrontOnEmptyQueue) { + Queue q; + EXPECT_NO_THROW(q.Front()); + + const Queue& cq = q; + EXPECT_NO_THROW(cq.Front()); +} + +TEST(QueueTest, BackOnEmptyQueue) { + Queue q; + EXPECT_NO_THROW(q.Back()); + + const Queue& cq = q; + EXPECT_NO_THROW(cq.Back()); +} + +TEST(QueueTest, Clear) { + Queue q = {1, 2, 3, 4, 5}; + + EXPECT_EQ(q.Size(), 5); + EXPECT_FALSE(q.Empty()); + + q.Clear(); + EXPECT_EQ(q.Size(), 0); + EXPECT_TRUE(q.Empty()); + + q.Push(100); + EXPECT_EQ(q.Size(), 1); + EXPECT_FALSE(q.Empty()); + EXPECT_EQ(q.Front(), 100); + EXPECT_EQ(q.Back(), 100); +} + +TEST(QueueTest, Swap) { + Queue q1 = {1, 2, 3}; + Queue q2 = {4, 5, 6, 7}; + + q1.Swap(q2); + + EXPECT_EQ(q1.Size(), 4); + EXPECT_EQ(q1.Front(), 4); + EXPECT_EQ(q1.Back(), 7); + + EXPECT_EQ(q2.Size(), 3); + EXPECT_EQ(q2.Front(), 1); + EXPECT_EQ(q2.Back(), 3); + + q1.Swap(q1); + EXPECT_EQ(q1.Size(), 4); + EXPECT_EQ(q1.Front(), 4); + EXPECT_EQ(q1.Back(), 7); +} + +TEST(QueueTest, Equality) { + Queue q1 = {1, 2, 3, 4, 5}; + Queue q2 = {1, 2, 3, 4, 5}; + Queue q3 = {1, 2, 3, 4}; + Queue q4 = {5, 4, 3, 2, 1}; + Queue q5 = {2, 3, 4, 5}; + + EXPECT_TRUE(q1 == q1); + EXPECT_FALSE(q1 != q1); + EXPECT_TRUE(q1 == q2); + EXPECT_FALSE(q1 != q2); + + EXPECT_FALSE(q1 == q3); + EXPECT_TRUE(q1 != q3); + + EXPECT_FALSE(q1 == q4); + EXPECT_TRUE(q1 != q4); + + EXPECT_FALSE(q1 == q5); + EXPECT_TRUE(q1 != q5); + q1.Pop(); + EXPECT_TRUE(q1 == q5); + EXPECT_FALSE(q1 != q5); +} + +TEST(QueueTest, EqualityAfterOperations) { + Queue q1; + Queue q2; + + q1.Push(1); q1.Push(2); q1.Push(3); q1.Pop(); q1.Push(4); + q2.Push(2); q2.Push(3); q2.Push(4); + + EXPECT_TRUE(q1 == q2); +} + +TEST(QueueTest, EqualityAfterManyOperations) { + Queue q3; + Queue q4; + + for (int i = 0; i < 1000; ++i) { + q3.Push(i); + q4.Push(i); + } + + for (int i = 0; i < 500; ++i) { + q3.Pop(); + q4.Pop(); + } + EXPECT_TRUE(q3 == q4); +} + +TEST(QueueTest, SizeAfterManyOperations) { + Queue q; + const int N = 100'000; + + for (int i = 0; i < N; ++i) { + q.Push(i); + q.Push(i + 1); + q.Pop(); + } + + EXPECT_EQ(q.Size(), N); +} + +TEST(QueueTest, FifoOrder) { + Queue q; + const int N = 100'000; + + for (int i = 0; i < N; ++i) { + q.Push(i); + } + + for (int i = 0; i < N; ++i) { + EXPECT_EQ(q.Front(), i); + q.Pop(); + } + + EXPECT_TRUE(q.Empty()); +} + +TEST(QueueTest, MixedOperations) { + Queue q; + + q.Push(1); + q.Push(2); + EXPECT_EQ(q.Front(), 1); + EXPECT_EQ(q.Back(), 2); + + q.Push(3); + q.Pop(); + EXPECT_EQ(q.Front(), 2); + EXPECT_EQ(q.Back(), 3); + + q.Push(4); + q.Push(5); + q.Pop(); + EXPECT_EQ(q.Front(), 3); + EXPECT_EQ(q.Back(), 5); + + q.Pop(); + q.Pop(); + EXPECT_EQ(q.Front(), 5); + EXPECT_EQ(q.Back(), 5); + + q.Pop(); + EXPECT_TRUE(q.Empty()); +} + +TEST(QueueTest, ConstQueue) { + const Queue q = {1, 2, 3, 4, 5}; + EXPECT_EQ(q.Size(), 5); + EXPECT_FALSE(q.Empty()); + EXPECT_EQ(q.Front(), 1); + EXPECT_EQ(q.Back(), 5); + + const Queue q2 = {1, 2, 3, 4, 5}; + EXPECT_TRUE(q == q2); + EXPECT_FALSE(q != q2); +} + +TEST(QueueTest, ConstRefQueue) { + Queue q = {1, 2, 3, 4, 5}; + const Queue& q_ref = q; + EXPECT_EQ(q_ref.Size(), 5); + EXPECT_FALSE(q_ref.Empty()); + EXPECT_EQ(q_ref.Front(), 1); + EXPECT_EQ(q_ref.Back(), 5); + EXPECT_TRUE(q_ref == q_ref); + EXPECT_FALSE(q_ref != q_ref); + + q.Pop(); + EXPECT_EQ(q_ref.Size(), 4); + EXPECT_FALSE(q_ref.Empty()); + EXPECT_EQ(q_ref.Front(), 2); + EXPECT_EQ(q_ref.Back(), 5); +} + +TEST(QueueTest, SingleElement) { + Queue q; + + q.Push(42); + EXPECT_EQ(q.Size(), 1); + EXPECT_EQ(q.Front(), 42); + EXPECT_EQ(q.Back(), 42); + EXPECT_FALSE(q.Empty()); + + q.Pop(); + EXPECT_TRUE(q.Empty()); + EXPECT_EQ(q.Size(), 0); +} + +class QueuePerformanceTest : public ::testing::Test { +protected: + void SetUp() override { + } + + void TearDown() override { + } + + template + static long long MeasureTime(Func func) { + auto start = std::chrono::high_resolution_clock::now(); + func(); + auto end = std::chrono::high_resolution_clock::now(); + return std::chrono::duration_cast(end - start).count(); + } +}; + +TEST_F(QueuePerformanceTest, CapacityConstructor) { + constexpr int LARGE_SIZE = 10'000'000; + Queue q_with_reserve(LARGE_SIZE); + + long long time_with_reserve = MeasureTime([&q_with_reserve]() { + for (int i = 0; i < LARGE_SIZE; ++i) { + q_with_reserve.Push(i); + } + }); + + std::cout << "\nВремя заполнения очереди с резервированием (" + << LARGE_SIZE << " элементов): " + << time_with_reserve << " ms" << std::endl; + + Queue q_without_reserve; + long long time_without_reserve = MeasureTime([&q_without_reserve]() { + for (int i = 0; i < LARGE_SIZE; ++i) { + q_without_reserve.Push(i); + } + }); + + std::cout << "Время заполнения очереди без резервирования (" + << LARGE_SIZE << " элементов): " + << time_without_reserve << " ms" << std::endl; + + EXPECT_EQ(q_with_reserve.Size(), LARGE_SIZE); + EXPECT_EQ(q_without_reserve.Size(), LARGE_SIZE); + + for (int i = 0; i < LARGE_SIZE; ++i) { + EXPECT_EQ(q_with_reserve.Front(), i); + EXPECT_TRUE(q_with_reserve.Pop()); + EXPECT_EQ(q_without_reserve.Front(), i); + EXPECT_TRUE(q_without_reserve.Pop()); + } + EXPECT_TRUE(q_with_reserve.Empty()); + EXPECT_TRUE(q_without_reserve.Empty()); + + std::cout << "Разница: " << (time_without_reserve - time_with_reserve) + << " ms (экономия " + << (100.0 * (time_without_reserve - time_with_reserve) / time_without_reserve) + << "%)" << std::endl; + + EXPECT_LT(time_with_reserve * 1.0, time_without_reserve * 0.94); +} + +TEST_F(QueuePerformanceTest, CapacityCtorCompareWithVector) { + constexpr int LARGE_SIZE = 10'000'000; + + Queue q(LARGE_SIZE); + long long queue_push_time = MeasureTime([&q]() { + for (int i = 0; i < LARGE_SIZE; ++i) { + q.Push(i); + } + }); + + std::vector vec; + vec.reserve(LARGE_SIZE); + long long vector_push_time = MeasureTime([&vec]() { + for (int i = 0; i < LARGE_SIZE; ++i) { + vec.push_back(i); + } + }); + + std::cout << "\nСравнение с вектором (" << LARGE_SIZE << " элементов):" << std::endl; + std::cout << "Очередь на двух стеках:" << std::endl; + std::cout << " Push: " << queue_push_time << " ms" << std::endl; + std::cout << "Вектор:" << std::endl; + std::cout << " Push: " << vector_push_time << " ms" << std::endl; + + EXPECT_LT(queue_push_time * 1.0, vector_push_time * 1.5); +} \ No newline at end of file diff --git a/04_week/tasks/ring_buffer/CMakeLists.txt b/04_week/tasks/ring_buffer/CMakeLists.txt new file mode 100644 index 00000000..2893892c --- /dev/null +++ b/04_week/tasks/ring_buffer/CMakeLists.txt @@ -0,0 +1 @@ +add_gtest(test_ring_buffer test.cpp) \ No newline at end of file diff --git a/04_week/tasks/ring_buffer/README.md b/04_week/tasks/ring_buffer/README.md new file mode 100644 index 00000000..37d252d4 --- /dev/null +++ b/04_week/tasks/ring_buffer/README.md @@ -0,0 +1,49 @@ +# Кольцевой буфер + +Необходимо реализовать класс `RingBuffer`, который представляет собой кольцевой буфер +фиксированного размера, построенный на контейнере `std::vector`. + +При добавлении в заполненный буфер перезаписывается самый старый элемент. + +Может хранить либо позиции начала, конца и размер буфера, либо указатели на +соответствующие позиции. + +Класс предоставляет следующий функционал: + +- Конструктор от вместимости буфера +- Конструктор от вместимости буфера и начального значения, заполняет весь буфер +- Конструктор от `std::initializer_list`, вместимость соответствует размеру контейнера. +- Метод `Push` - добавляет элемент в буфер, может перезаписывать +- Метод `TryPush` - пытается добавить элемент без перезаписи, возвращает `true` в случае + успеха и `false` если буфер полон. +- Метод `Pop` - убирает самый старый элемент из буфера +- Метод `TryPop` - пытается извлечь самый старый элемент из буфера и возвращает `true` + в случае успеха и `false` для пустого буфера, и возвращает убранное значение через + параметр метода +- Оператор `[]` - доступ к элементу по логическому индексу (0 - наиболее старый элемент + кольцевого буфера) +- Метод `Front` - обеспечивает доступ на запись и чтение к самому новому элементу буфера +- Метод `Back` - обеспечивает доступ на запись и чтение к самому старому элементу буфера +- Метод `Empty` - возвращает результат проверки буфера на отсутствие элементов +- Метод `Full` - возвращает результат проверки буфера на заполненность +- Метод `Size` - возвращает количество элементов в буфере +- Метод `Capacity` - возвращает количество элементов в буфере +- Метод `Clear` - очищает буфер, позиции начала и конца соответствуют нулевому элементу +- Метод `Resize` - изменяет вместимость буфера, если буфер увеличивается, то все элементы + копируются в новый буфер в правильном порядке, если буфер уменьшается, то отбрасываются + старые элементы, остальные копируются в правильном порядке +- Метод `Vector` - возвращает `std::vector` - линейное представление буфера + +Сконструировать буфер нулевого размера нельзя, создается буфер единичного размера. +Аналогично для метода `Resize`. + +Вызов метода `Pop` от пустой очереди является корректной операцией. + +Вызов `Front` и `Back` от пустой очереди не ограничивается и ведет к **UB**. + +## Примечание + +- Запрещено использовать `std::queue`, `std::deque`, `std::list` +- Рекомендуется определять методы вне класса +- Некоторые методы могут потребовать перегрузки +- При необходимости вспомогательные методы реализуются в закрытой части класса \ No newline at end of file diff --git a/04_week/tasks/ring_buffer/a.out b/04_week/tasks/ring_buffer/a.out new file mode 100644 index 0000000000000000000000000000000000000000..8f866d69bbe3298bb9a105339470bd61c70821a3 GIT binary patch literal 287288 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�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�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 literal 0 HcmV?d00001 diff --git a/04_week/tasks/ring_buffer/ring_buffer.cpp b/04_week/tasks/ring_buffer/ring_buffer.cpp new file mode 100644 index 00000000..a5fd04c8 --- /dev/null +++ b/04_week/tasks/ring_buffer/ring_buffer.cpp @@ -0,0 +1,176 @@ +#include "ring_buffer.hpp" +#include + +size_t RingBuffer::CalculateIndex(size_t logical_index) const { + return (tail_ + logical_index) % capacity_; +} + +RingBuffer::RingBuffer(size_t capacity) + : capacity_(capacity == 0 ? 1 : capacity) + , size_(0) + , head_(0) + , tail_(0) { + data_.resize(capacity_); +} + +RingBuffer::RingBuffer(size_t capacity, int value) + : capacity_(capacity == 0 ? 1 : capacity) + , size_(capacity_) + , head_(0) + , tail_(0) { + data_.resize(capacity_, value); +} + +RingBuffer::RingBuffer(std::initializer_list init) + : capacity_(init.size() == 0 ? 1 : init.size()) + , size_(init.size()) + , head_(0) + , tail_(0) { + data_.resize(capacity_); + size_t idx = 0; + for (int value : init) { + data_[idx++] = value; + } +} + +RingBuffer::RingBuffer(const RingBuffer& other) + : data_(other.data_) + , capacity_(other.capacity_) + , size_(other.size_) + , head_(other.head_) + , tail_(other.tail_) { +} + +RingBuffer& RingBuffer::operator=(const RingBuffer& other) { + if (this != &other) { + data_ = other.data_; + capacity_ = other.capacity_; + size_ = other.size_; + head_ = other.head_; + tail_ = other.tail_; + } + return *this; +} + +void RingBuffer::Push(int value) { + data_[head_] = value; + head_ = (head_ + 1) % capacity_; + + if (size_ < capacity_) { + ++size_; + } else { + tail_ = (tail_ + 1) % capacity_; + } +} + +bool RingBuffer::TryPush(int value) { + if (Full()) { + return false; + } + Push(value); + return true; +} + +void RingBuffer::Pop() { + if (Empty()) { + return; + } + tail_ = (tail_ + 1) % capacity_; + --size_; +} + +bool RingBuffer::TryPop(int& value) { + if (Empty()) { + return false; + } + value = data_[tail_]; + Pop(); + return true; +} + +int& RingBuffer::operator[](size_t index) { + return data_[CalculateIndex(index)]; +} + +const int& RingBuffer::operator[](size_t index) const { + return data_[CalculateIndex(index)]; +} + +int& RingBuffer::Front() { + size_t front_idx = (head_ + capacity_ - 1) % capacity_; + return data_[front_idx]; +} + +const int& RingBuffer::Front() const { + size_t front_idx = (head_ + capacity_ - 1) % capacity_; + return data_[front_idx]; +} + +int& RingBuffer::Back() { + return data_[tail_]; +} + +const int& RingBuffer::Back() const { + return data_[tail_]; +} + +bool RingBuffer::Empty() const { + return size_ == 0; +} + +bool RingBuffer::Full() const { + return size_ == capacity_; +} + +size_t RingBuffer::Size() const { + return size_; +} + +size_t RingBuffer::Capacity() const { + return capacity_; +} + +void RingBuffer::Clear() { + size_ = 0; + head_ = 0; + tail_ = 0; +} + +void RingBuffer::Resize(size_t new_capacity) { + if (new_capacity == 0) { + new_capacity = 1; + } + + if (new_capacity == capacity_) { + return; + } + + std::vector new_data(new_capacity); + size_t new_size = std::min(size_, new_capacity); + + size_t start_offset = 0; + if (size_ > new_capacity) { + start_offset = size_ - new_capacity; + } + + for (size_t i = 0; i < new_size; ++i) { + new_data[i] = data_[CalculateIndex(start_offset + i)]; + } + + data_ = std::move(new_data); + capacity_ = new_capacity; + size_ = new_size; + tail_ = 0; + head_ = new_size % capacity_; +} + +std::vector RingBuffer::Vector() const { + std::vector result; + result.reserve(size_); + + for (size_t i = 0; i < size_; ++i) { + result.push_back(data_[CalculateIndex(i)]); + } + + return result; +} \ No newline at end of file diff --git a/04_week/tasks/ring_buffer/ring_buffer.hpp b/04_week/tasks/ring_buffer/ring_buffer.hpp new file mode 100644 index 00000000..d5ce435a --- /dev/null +++ b/04_week/tasks/ring_buffer/ring_buffer.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +class RingBuffer { +private: + std::vector data_; + size_t capacity_ = 0; + size_t size_ = 0; + size_t head_ = 0; // индекс для добавления (Front) + size_t tail_ = 0; // индекс для удаления (Back) + + // Метод для получения индекса + size_t CalculateIndex(size_t logical_index) const; + +public: + explicit RingBuffer(size_t capacity); + RingBuffer(size_t capacity, int value); + RingBuffer(std::initializer_list init); + RingBuffer(const RingBuffer& other); + + void Push(int value); + bool TryPush(int value); + + void Pop(); + bool TryPop(int& value); + + int& Front(); + const int& Front() const; + + int& Back(); + const int& Back() const; + + bool Empty() const; + bool Full() const; + size_t Size() const; + size_t Capacity() const; + void Clear(); + void Resize(size_t new_capacity); + std::vector Vector() const; + + int& operator[](size_t index); + const int& operator[](size_t index) const; + RingBuffer& operator=(const RingBuffer& other); + +}; \ No newline at end of file diff --git a/04_week/tasks/ring_buffer/test.cpp b/04_week/tasks/ring_buffer/test.cpp new file mode 100644 index 00000000..8fd2c251 --- /dev/null +++ b/04_week/tasks/ring_buffer/test.cpp @@ -0,0 +1,549 @@ +#include + +#include + +#include "ring_buffer.cpp" + + +TEST(RingBufferTest, CtorCapacity) { + RingBuffer buffer(5); + + EXPECT_EQ(buffer.Capacity(), 5); + EXPECT_EQ(buffer.Size(), 0); + EXPECT_TRUE(buffer.Empty()); + EXPECT_FALSE(buffer.Full()); +} + +TEST(RingBufferTest, CtorCapacityAndInitialValue) { + RingBuffer buffer(5, 42); + + EXPECT_EQ(buffer.Capacity(), 5); + EXPECT_EQ(buffer.Size(), 5); + EXPECT_FALSE(buffer.Empty()); + EXPECT_TRUE(buffer.Full()); + + for (size_t i = 0; i < 5; ++i) { + EXPECT_EQ(buffer[i], 42); + } +} + +TEST(RingBufferTest, CtorInitializerList) { + RingBuffer buffer = {1, 2, 3, 4, 5}; + + EXPECT_EQ(buffer.Capacity(), 5); + EXPECT_EQ(buffer.Size(), 5); + EXPECT_FALSE(buffer.Empty()); + EXPECT_TRUE(buffer.Full()); + + for (size_t i = 0; i < 5; ++i) { + EXPECT_EQ(buffer[i], static_cast(i + 1)); + } +} + +TEST(RingBufferTest, ZeroCapacity) { + { + RingBuffer buffer(0); + EXPECT_EQ(buffer.Capacity(), 1); + EXPECT_EQ(buffer.Size(), 0); + EXPECT_TRUE(buffer.Empty()); + EXPECT_FALSE(buffer.Full()); + } + { + RingBuffer buffer(0, 42); + EXPECT_EQ(buffer.Capacity(), 1); + EXPECT_EQ(buffer.Size(), 1); + EXPECT_FALSE(buffer.Empty()); + EXPECT_TRUE(buffer.Full()); + EXPECT_EQ(buffer[0], 42); + } + { + RingBuffer buffer({}); + EXPECT_EQ(buffer.Capacity(), 1); + EXPECT_EQ(buffer.Size(), 0); + EXPECT_TRUE(buffer.Empty()); + EXPECT_FALSE(buffer.Full()); + } +} + +TEST(RingBufferTest, PushToEmptyBuffer) { + RingBuffer buffer(3); + + buffer.Push(10); + EXPECT_EQ(buffer.Size(), 1); + EXPECT_EQ(buffer.Front(), 10); + EXPECT_EQ(buffer.Back(), 10); + + buffer.Push(20); + EXPECT_EQ(buffer.Size(), 2); + EXPECT_EQ(buffer.Front(), 20); + EXPECT_EQ(buffer.Back(), 10); + + buffer.Push(30); + EXPECT_EQ(buffer.Size(), 3); + EXPECT_TRUE(buffer.Full()); + EXPECT_EQ(buffer.Front(), 30); + EXPECT_EQ(buffer.Back(), 10); +} + +TEST(RingBufferTest, OverflowBehavior) { + RingBuffer buffer(3); + + buffer.Push(1); + buffer.Push(2); + buffer.Push(3); + buffer.Push(4); + + EXPECT_EQ(buffer.Size(), 3); + EXPECT_EQ(buffer.Front(), 4); + EXPECT_EQ(buffer.Back(), 2); + + buffer.Push(5); + EXPECT_EQ(buffer.Front(), 5); + EXPECT_EQ(buffer.Back(), 3); + + buffer.Push(6); + EXPECT_EQ(buffer.Front(), 6); + EXPECT_EQ(buffer.Back(), 4); +} + +TEST(RingBufferTest, PopFromBuffer) { + RingBuffer buffer = {1, 2, 3}; + + buffer.Pop(); + EXPECT_EQ(buffer.Size(), 2); + EXPECT_EQ(buffer.Back(), 2); + + buffer.Pop(); + EXPECT_EQ(buffer.Size(), 1); + EXPECT_EQ(buffer.Back(), 3); + + buffer.Pop(); + EXPECT_TRUE(buffer.Empty()); + EXPECT_EQ(buffer.Size(), 0); + + EXPECT_NO_THROW(buffer.Pop()); + EXPECT_TRUE(buffer.Empty()); +} + +TEST(RingBufferTest, TryPush) { + RingBuffer buffer(2); + + EXPECT_TRUE(buffer.TryPush(1)); + EXPECT_TRUE(buffer.TryPush(2)); + EXPECT_FALSE(buffer.TryPush(3)); + EXPECT_TRUE(buffer.Full()); + EXPECT_EQ(buffer.Size(), 2); + EXPECT_EQ(buffer.Front(), 2); + EXPECT_EQ(buffer.Back(), 1); + + buffer.Pop(); + EXPECT_EQ(buffer.Size(), 1); + EXPECT_TRUE(buffer.TryPush(3)); + EXPECT_EQ(buffer.Size(), 2); + EXPECT_EQ(buffer.Front(), 3); + EXPECT_EQ(buffer.Back(), 2); +} + +TEST(RingBufferTest, TryPop) { + RingBuffer buffer = {10, 20, 30}; + int value; + + EXPECT_TRUE(buffer.TryPop(value)); + EXPECT_EQ(value, 10); + EXPECT_EQ(buffer.Size(), 2); + + EXPECT_TRUE(buffer.TryPop(value)); + EXPECT_EQ(value, 20); + EXPECT_EQ(buffer.Size(), 1); + + EXPECT_TRUE(buffer.TryPop(value)); + EXPECT_EQ(value, 30); + EXPECT_TRUE(buffer.Empty()); + + EXPECT_FALSE(buffer.TryPop(value)); +} + +TEST(RingBufferTest, OperatorIndex) { + RingBuffer buffer(5); + + buffer.Push(10); + buffer.Push(20); + buffer.Push(30); + + EXPECT_EQ(buffer[0], 10); + EXPECT_EQ(buffer[1], 20); + EXPECT_EQ(buffer[2], 30); + + buffer[1] = 200; + EXPECT_EQ(buffer[1], 200); +} + +TEST(RingBufferTest, ConstOperatorIndex) { + const RingBuffer buffer = {1, 2, 3, 4, 5}; + + EXPECT_EQ(buffer[0], 1); + EXPECT_EQ(buffer[2], 3); + EXPECT_EQ(buffer[4], 5); +} + +TEST(RingBufferTest, FrontAndBack) { + RingBuffer buffer(5); + + buffer.Push(1); + EXPECT_EQ(buffer.Front(), 1); + EXPECT_EQ(buffer.Back(), 1); + + buffer.Push(2); + EXPECT_EQ(buffer.Front(), 2); + EXPECT_EQ(buffer.Back(), 1); + + buffer.Push(3); + buffer.Push(4); + buffer.Push(5); + EXPECT_EQ(buffer.Front(), 5); + EXPECT_EQ(buffer.Back(), 1); + + buffer.Front() = 500; + buffer.Back() = 100; + EXPECT_EQ(buffer.Front(), 500); + EXPECT_EQ(buffer.Back(), 100); +} + +TEST(RingBufferTest, EmptyAndFull) { + RingBuffer buffer(3); + + EXPECT_TRUE(buffer.Empty()); + EXPECT_FALSE(buffer.Full()); + + buffer.Push(1); + EXPECT_FALSE(buffer.Empty()); + EXPECT_FALSE(buffer.Full()); + + buffer.Push(2); + buffer.Push(3); + EXPECT_FALSE(buffer.Empty()); + EXPECT_TRUE(buffer.Full()); + + buffer.Pop(); + EXPECT_FALSE(buffer.Empty()); + EXPECT_FALSE(buffer.Full()); + + buffer.Pop(); + buffer.Pop(); + EXPECT_TRUE(buffer.Empty()); + EXPECT_FALSE(buffer.Full()); +} + +TEST(RingBufferTest, SizeAndCapacity) { + RingBuffer buffer(10); + + EXPECT_EQ(buffer.Capacity(), 10); + EXPECT_EQ(buffer.Size(), 0); + + for (int i = 0; i < 7; ++i) { + buffer.Push(i); + } + + EXPECT_EQ(buffer.Capacity(), 10); + EXPECT_EQ(buffer.Size(), 7); + + for (int i = 0; i < 10; ++i) { + buffer.Push(i * 10); + } + + EXPECT_EQ(buffer.Capacity(), 10); + EXPECT_EQ(buffer.Size(), 10); +} + +TEST(RingBufferTest, Clear) { + RingBuffer buffer = {1, 2, 3, 4, 5}; + + EXPECT_FALSE(buffer.Empty()); + buffer.Clear(); + + EXPECT_TRUE(buffer.Empty()); + EXPECT_EQ(buffer.Size(), 0); + EXPECT_EQ(buffer.Capacity(), 5); + + buffer.Push(100); + EXPECT_EQ(buffer.Size(), 1); + EXPECT_EQ(buffer.Front(), 100); + EXPECT_EQ(buffer.Back(), 100); +} + +TEST(RingBufferTest, ResizeIncrease) { + RingBuffer buffer(3); + buffer.Push(1); + buffer.Push(2); + buffer.Push(3); + + EXPECT_EQ(buffer.Capacity(), 3); + EXPECT_EQ(buffer.Size(), 3); + + buffer.Resize(5); + EXPECT_EQ(buffer.Capacity(), 5); + EXPECT_EQ(buffer.Size(), 3); + + EXPECT_EQ(buffer[0], 1); + EXPECT_EQ(buffer[1], 2); + EXPECT_EQ(buffer[2], 3); + + buffer.Push(4); + buffer.Push(5); + EXPECT_EQ(buffer.Size(), 5); + EXPECT_TRUE(buffer.Full()); + EXPECT_EQ(buffer[3], 4); + EXPECT_EQ(buffer[4], 5); +} + +TEST(RingBufferTest, ResizeDecrease) { + RingBuffer buffer(5); + + for (int i = 0; i < 5; ++i) { + buffer.Push(i); + } + + buffer.Resize(3); + + EXPECT_EQ(buffer.Capacity(), 3); + EXPECT_EQ(buffer.Size(), 3); + + EXPECT_EQ(buffer[0], 2); + EXPECT_EQ(buffer[1], 3); + EXPECT_EQ(buffer[2], 4); +} + +TEST(RingBufferTest, ResizeDecreaseForNotFullBuffer) { + RingBuffer buffer(5); + buffer.Push(1); + buffer.Push(2); + + buffer.Resize(3); + + EXPECT_EQ(buffer.Capacity(), 3); + EXPECT_EQ(buffer.Size(), 2); + EXPECT_EQ(buffer[0], 1); + EXPECT_EQ(buffer[1], 2); + + buffer.Resize(5); + buffer.Push(3); + buffer.Push(4); + buffer.Resize(3); + + EXPECT_EQ(buffer.Size(), 3); + EXPECT_EQ(buffer[0], 2); + EXPECT_EQ(buffer[1], 3); + EXPECT_EQ(buffer[2], 4); +} + +TEST(RingBufferTest, ResizeWithOverflow) { + RingBuffer buffer(5); + + for (int i = 0; i < 7; ++i) { + buffer.Push(i); + } + // buffer = {2, 3, 4, 5, 6} + buffer.Resize(3); + + EXPECT_EQ(buffer.Capacity(), 3); + EXPECT_EQ(buffer.Size(), 3); + EXPECT_EQ(buffer[0], 4); + EXPECT_EQ(buffer[1], 5); + EXPECT_EQ(buffer[2], 6); +} + +TEST(RingBufferTest, ResizeToSameSize) { + RingBuffer buffer = {1, 2, 3}; + + buffer.Resize(3); + + EXPECT_EQ(buffer.Capacity(), 3); + EXPECT_EQ(buffer.Size(), 3); + EXPECT_EQ(buffer[0], 1); + EXPECT_EQ(buffer[1], 2); + EXPECT_EQ(buffer[2], 3); +} + +TEST(RingBufferTest, ResizeZero) { + RingBuffer buffer(3); + buffer.Push(1); + + EXPECT_NO_THROW(buffer.Resize(0)); + EXPECT_EQ(buffer.Size(), 1); + EXPECT_EQ(buffer[0], 1); +} + +TEST(RingBufferTest, VectorConversion) { + RingBuffer buffer(5); + + buffer.Push(1); + buffer.Push(2); + buffer.Push(3); + + std::vector vec = buffer.Vector(); + + EXPECT_EQ(vec.size(), 3); + EXPECT_EQ(vec[0], 1); + EXPECT_EQ(vec[1], 2); + EXPECT_EQ(vec[2], 3); + + buffer.Push(4); + buffer.Push(5); + buffer.Push(6); + + vec = buffer.Vector(); + EXPECT_EQ(vec.size(), 5); + EXPECT_EQ(vec[0], 2); + EXPECT_EQ(vec[4], 6); +} + +TEST(RingBufferTest, VectorFromComplexBuffer) { + RingBuffer buffer(4); + + buffer.Push(1); + buffer.Push(2); + buffer.Push(3); + buffer.Push(4); + + buffer.Pop(); + buffer.Pop(); + + buffer.Push(5); + buffer.Push(6); + + std::vector vec = buffer.Vector(); + + EXPECT_EQ(vec.size(), 4); + EXPECT_EQ(vec[0], 3); + EXPECT_EQ(vec[1], 4); + EXPECT_EQ(vec[2], 5); + EXPECT_EQ(vec[3], 6); +} + +TEST(RingBufferTest, CopyConstructor) { + RingBuffer original(5); + original.Push(1); + original.Push(2); + original.Push(3); + + RingBuffer copy(original); + + EXPECT_EQ(copy.Capacity(), 5); + EXPECT_EQ(copy.Size(), 3); + EXPECT_EQ(copy[0], 1); + EXPECT_EQ(copy[1], 2); + EXPECT_EQ(copy[2], 3); + + original.Push(4); + EXPECT_EQ(original.Size(), 4); + EXPECT_EQ(copy.Size(), 3); +} + +TEST(RingBufferTest, CopyAssignment) { + RingBuffer b1(5); + b1.Push(1); + b1.Push(2); + + RingBuffer b2(3); + b2.Push(10); + b2.Push(20); + b2.Push(30); + + b2 = b1; + + EXPECT_EQ(b2.Capacity(), 5); + EXPECT_EQ(b2.Size(), 2); + EXPECT_EQ(b2[0], 1); + EXPECT_EQ(b2[1], 2); + + RingBuffer& ref = b1; + b1 = ref; + EXPECT_EQ(b1.Size(), 2); +} + +TEST(RingBufferTest, ComplexScenario) { + RingBuffer buffer(4); + + buffer.Push(1); + buffer.Push(2); + buffer.Push(3); + buffer.Push(4); + + buffer.Push(5); + buffer.Push(6); + + buffer.Pop(); + buffer.Pop(); + + buffer.Push(7); + buffer.Push(8); + buffer.Push(9); + + EXPECT_EQ(buffer.Size(), 4); + EXPECT_EQ(buffer[0], 6); + EXPECT_EQ(buffer[1], 7); + EXPECT_EQ(buffer[2], 8); + EXPECT_EQ(buffer[3], 9); +} + +TEST(RingBufferTest, ComplexScenarioTwo) { + RingBuffer buffer(3); + + buffer.Push(1); + buffer.Push(2); + buffer.Pop(); + buffer.Push(3); + buffer.Pop(); + buffer.Push(4); + buffer.Push(5); + buffer.Push(6); + buffer.Push(7); + + EXPECT_EQ(buffer.Size(), 3); + EXPECT_EQ(buffer[0], 5); + EXPECT_EQ(buffer[1], 6); + EXPECT_EQ(buffer[2], 7); +} + +TEST(RingBufferTest, LargeBufferOperations) { + constexpr size_t LARGE_SIZE = 1'000'000; + RingBuffer buffer(LARGE_SIZE); + + for (size_t i = 0; i < LARGE_SIZE; ++i) { + buffer.Push(static_cast(i)); + } + + EXPECT_EQ(buffer.Size(), LARGE_SIZE); + EXPECT_TRUE(buffer.Full()); + + for (size_t i = 0; i < LARGE_SIZE; ++i) { + EXPECT_EQ(buffer[i], static_cast(i)); + } + + // Быстрое очищение + while (!buffer.Empty()) { + buffer.Pop(); + } + + EXPECT_TRUE(buffer.Empty()); +} + +TEST(RingBufferTest, WrapAroundBehavior) { + RingBuffer buffer(5); + + for (int i = 0; i < 5; ++i) { + buffer.Push(i + 1); + } + + buffer.Pop(); + buffer.Pop(); + + buffer.Push(6); + buffer.Push(7); + + EXPECT_EQ(buffer[0], 3); + EXPECT_EQ(buffer[1], 4); + EXPECT_EQ(buffer[2], 5); + EXPECT_EQ(buffer[3], 6); + EXPECT_EQ(buffer[4], 7); +} \ No newline at end of file diff --git a/04_week/tasks/stack/CMakeLists.txt b/04_week/tasks/stack/CMakeLists.txt new file mode 100644 index 00000000..5dd310ae --- /dev/null +++ b/04_week/tasks/stack/CMakeLists.txt @@ -0,0 +1 @@ +add_gtest(test_stack test.cpp) \ No newline at end of file diff --git a/04_week/tasks/stack/README.md b/04_week/tasks/stack/README.md new file mode 100644 index 00000000..8d034401 --- /dev/null +++ b/04_week/tasks/stack/README.md @@ -0,0 +1,31 @@ +[Стек]: https://en.wikipedia.org/wiki/Stack_(abstract_data_type) + +# Стек + +[Стек] представляет собой LIFO (Last Input First Output) структуру данных. +Необходимо реализовать класс `Stack`, который представляет собой простую обертку +над классом вектор `std::vector`. + +Класс предоставляет следующие методы: + +- Метод `Push` - добавляет элемент на верхушку стека +- Метод `Pop` - убирает элемент с верхушки стека +- Метод `Top` - обеспечивает доступ к элементу на верхушке стека +- Метод `Empty` - возвращает результат проверки стека на отсутствие элементов +- Метод `Size` - возвращает количество элементов в стеке +- Метод `Clear` - очищает стек +- Метод `Swap` - меняется элементами с другим стеком (без копирования) +- Оператор `==` - сравнение стека на равенство +- Оператор `!=` - сравнение стека на неравенство + +Вызов метода `Pop` от пустого стека является корректной операцией. Метод должен +возвращать `true` или `false` в зависимости от того выполнялась операция или нет. + +## Примечание + +- Запрещено использовать класс `std::stack` +- Значения стека должны находится в закрытой части класса +- Рекомендуется определять методы вне класса +- Некоторые методы могут потребовать перегрузки +- Обратите внимание, что при использовании в качестве полей контейнеров стандартной + библиотеки нет необходимости писать собственные конструкторы \ No newline at end of file diff --git a/04_week/tasks/stack/stack.cpp b/04_week/tasks/stack/stack.cpp new file mode 100644 index 00000000..ea9ee193 --- /dev/null +++ b/04_week/tasks/stack/stack.cpp @@ -0,0 +1,53 @@ +#include "stack.hpp" + +void Stack::Push(int value) { + data_.push_back(value); +} + +bool Stack::Pop() { + if (data_.empty()) { + return false; + } + data_.pop_back(); + return true; +} + +int& Stack::Top() { + if (data_.empty()) { + static int dummy = 0; + return dummy; + } + return data_.back(); +} + +const int& Stack::Top() const { + if (data_.empty()) { + static constexpr int dummy = 0; + return dummy; + } + return data_.back(); +} + +bool Stack::Empty() const { + return data_.empty(); +} + +size_t Stack::Size() const { + return data_.size(); +} + +void Stack::Clear() { + data_.clear(); +} + +void Stack::Swap(Stack& other) { + data_.swap(other.data_); +} + +bool Stack::operator==(const Stack& other) const { + return data_ == other.data_; +} + +bool Stack::operator!=(const Stack& other) const { + return data_ != other.data_; +} \ No newline at end of file diff --git a/04_week/tasks/stack/stack.hpp b/04_week/tasks/stack/stack.hpp new file mode 100644 index 00000000..16c5f949 --- /dev/null +++ b/04_week/tasks/stack/stack.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +class Stack { +private: + std::vector data_; + +public: + void Push(int value); + + // Возвращает true если операция выполнена, false если стек пуст + bool Pop(); + + int& Top(); + const int& Top() const; + + bool Empty() const; + size_t Size() const; + void Clear(); + void Swap(Stack& other); + + bool operator==(const Stack& other) const; + bool operator!=(const Stack& other) const; +}; \ No newline at end of file diff --git a/04_week/tasks/stack/test.cpp b/04_week/tasks/stack/test.cpp new file mode 100644 index 00000000..1b1cb95f --- /dev/null +++ b/04_week/tasks/stack/test.cpp @@ -0,0 +1,353 @@ +#include + +#include + +#include "stack.cpp" + + +TEST(StackTest, EmptyStack) { + Stack s; + + EXPECT_TRUE(s.Empty()); + EXPECT_EQ(s.Size(), 0); +} + +TEST(StackTest, PushElements) { + Stack s; + + s.Push(1); + EXPECT_FALSE(s.Empty()); + EXPECT_EQ(s.Size(), 1); + EXPECT_EQ(s.Top(), 1); + + s.Push(-1); + EXPECT_EQ(s.Size(), 2); + EXPECT_EQ(s.Top(), -1); + + s.Push(9); + EXPECT_EQ(s.Size(), 3); + EXPECT_EQ(s.Top(), 9); +} + +TEST(StackTest, PopElements) { + Stack s; + s.Push(1); + s.Push(-1); + s.Push(9); + + EXPECT_EQ(s.Top(), 9); + EXPECT_TRUE(s.Pop()); + EXPECT_EQ(s.Size(), 2); + EXPECT_EQ(s.Top(), -1); + + EXPECT_TRUE(s.Pop()); + EXPECT_EQ(s.Size(), 1); + EXPECT_EQ(s.Top(), 1); + + EXPECT_TRUE(s.Pop()); + EXPECT_TRUE(s.Empty()); + EXPECT_EQ(s.Size(), 0); +} + +TEST(StackTest, PopFromEmptyStack) { + Stack s; + EXPECT_TRUE(s.Empty()); + EXPECT_EQ(s.Size(), 0); + + EXPECT_FALSE(s.Pop()); + EXPECT_FALSE(s.Pop()); + + EXPECT_TRUE(s.Empty()); + EXPECT_EQ(s.Size(), 0); +} + +TEST(StackTest, TopElement) { + Stack s; + + s.Push(42); + EXPECT_EQ(s.Top(), 42); + + s.Top() = 100; + EXPECT_EQ(s.Top(), 100); +} + +TEST(StackTest, TopElementForConstStack) { + Stack s; + + s.Push(42); + s.Top() = 100; + + const Stack& const_ref = s; + EXPECT_EQ(const_ref.Top(), 100); +} + +TEST(StackTest, TopOnEmptyStack) { + Stack s; + EXPECT_NO_THROW(s.Top()); + + const Stack& const_ref = s; + EXPECT_NO_THROW(const_ref.Top()); +} + +TEST(StackTest, SwapStacks) { + Stack s1; + s1.Push(1); + s1.Push(2); + s1.Push(3); + + Stack s2; + s2.Push(4); + s2.Push(5); + + EXPECT_EQ(s1.Size(), 3); + EXPECT_EQ(s1.Top(), 3); + EXPECT_EQ(s2.Size(), 2); + EXPECT_EQ(s2.Top(), 5); + + s1.Swap(s2); + EXPECT_EQ(s1.Size(), 2); + EXPECT_EQ(s1.Top(), 5); + EXPECT_EQ(s2.Size(), 3); + EXPECT_EQ(s2.Top(), 3); + + s1.Swap(s2); + EXPECT_EQ(s1.Size(), 3); + EXPECT_EQ(s1.Top(), 3); + EXPECT_EQ(s2.Size(), 2); + EXPECT_EQ(s2.Top(), 5); +} + +TEST(StackTest, SwapWithEmptyStack) { + Stack s1; + s1.Push(1); + s1.Push(2); + + Stack s2; + + s1.Swap(s2); + EXPECT_TRUE(s1.Empty()); + EXPECT_EQ(s1.Size(), 0); + EXPECT_EQ(s2.Size(), 2); + EXPECT_EQ(s2.Top(), 2); +} + +TEST(StackTest, SwapWithSelf) { + Stack s; + s.Push(1); + s.Push(2); + + EXPECT_NO_THROW(s.Swap(s)); + EXPECT_EQ(s.Size(), 2); + EXPECT_EQ(s.Top(), 2); +} + +TEST(StackTest, ClearStack) { + Stack s; + s.Push(1); + s.Push(2); + s.Push(3); + + EXPECT_EQ(s.Size(), 3); + + s.Clear(); + + EXPECT_TRUE(s.Empty()); + EXPECT_EQ(s.Size(), 0); +} + +TEST(StackTest, CompareStacks) { + Stack s1; + s1.Push(1); + s1.Push(2); + + Stack s2; + s2.Push(1); + s2.Push(2); + + Stack s3; + s3.Push(1); + s3.Push(3); + + EXPECT_TRUE(s1 == s1); + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 == s3); + + EXPECT_FALSE(s1 != s1); + EXPECT_FALSE(s1 != s2); + EXPECT_TRUE(s1 != s3); +} + +TEST(StackTest, CompareStacksWithDifferentSize) { + Stack s1; + s1.Push(1); + s1.Push(2); + s1.Push(3); + + Stack s2; + s2.Push(2); + s2.Push(3); + + EXPECT_FALSE(s1 == s2); + EXPECT_TRUE(s1 != s2); +} + +TEST(StackTest, CompareEmptyStacks) { + Stack s4; + Stack s5; + EXPECT_TRUE(s4 == s5); + EXPECT_FALSE(s4 != s5); +} + +TEST(StackTest, LifoBehavior) { + Stack s; + for (int i = 0; i < 5; ++i) { + s.Push(i); + EXPECT_EQ(s.Top(), i); + } + for (int i = 5; i > 0; --i) { + EXPECT_EQ(s.Top(), i - 1); + s.Pop(); + } + EXPECT_TRUE(s.Empty()); +} + +TEST(StackTest, MultipleOperations) { + Stack s; + + s.Push(10); + s.Push(20); + s.Pop(); + EXPECT_EQ(s.Top(), 10); + + s.Push(30); + s.Push(40); + EXPECT_EQ(s.Size(), 3); + + s.Pop(); + s.Pop(); + EXPECT_EQ(s.Top(), 10); + EXPECT_EQ(s.Size(), 1); + + s.Pop(); + EXPECT_TRUE(s.Empty()); +} + +TEST(StackTest, ManyElements) { + Stack s; + const int COUNT = 1'000'000; + + for (int i = 0; i < COUNT; ++i) { + s.Push(i); + EXPECT_EQ(s.Top(), i); + EXPECT_EQ(s.Size(), i + 1); + } + + for (int i = COUNT - 1; i >= 0; --i) { + EXPECT_EQ(s.Top(), i); + s.Pop(); + } + + EXPECT_TRUE(s.Empty()); + EXPECT_EQ(s.Size(), 0); +} + +TEST(StackTest, ConstMethods) { + Stack s; + s.Push(1); + s.Push(2); + s.Push(3); + + const Stack& cs = s; + + EXPECT_FALSE(cs.Empty()); + EXPECT_EQ(cs.Size(), 3); + EXPECT_EQ(cs.Top(), 3); + EXPECT_TRUE(cs == cs); + EXPECT_FALSE(cs != cs); +} + +TEST(StackTest, CopyCtor) { + Stack original; + original.Push(1); + original.Push(2); + original.Push(3); + + Stack copy(original); + + EXPECT_EQ(copy.Size(), 3); + EXPECT_EQ(copy.Top(), 3); + EXPECT_TRUE(copy == original); +} + +TEST(StackTest, CopyCtorWithCopyModification) { + Stack original; + original.Push(1); + original.Push(2); + original.Push(3); + + Stack copy(original); + copy.Pop(); + EXPECT_EQ(copy.Size(), 2); + EXPECT_EQ(copy.Top(), 2); + EXPECT_EQ(original.Size(), 3); + EXPECT_EQ(original.Top(), 3); + EXPECT_FALSE(copy == original); +} + +TEST(StackTest, CopyAssignmentOperator) { + Stack s1; + s1.Push(10); + s1.Push(20); + s1.Push(30); + + Stack s2; + s2.Push(40); + s2.Push(50); + + s2 = s1; + EXPECT_EQ(s2.Size(), 3); + EXPECT_EQ(s2.Top(), 30); + EXPECT_TRUE(s2 == s1); + + s2.Pop(); + EXPECT_EQ(s2.Size(), 2); + EXPECT_EQ(s2.Top(), 20); + EXPECT_EQ(s1.Size(), 3); + EXPECT_EQ(s1.Top(), 30); + EXPECT_FALSE(s2 == s1); +} + +TEST(StackTest, CopyEmptyStack) { + Stack empty1; + Stack empty2(empty1); + + EXPECT_TRUE(empty2.Empty()); + EXPECT_EQ(empty2.Size(), 0); + + Stack empty3; + empty3 = empty1; + + EXPECT_TRUE(empty3.Empty()); + EXPECT_EQ(empty3.Size(), 0); +} + +TEST(StackTest, ChainAssignment) { + Stack s1, s2, s3; + + s1.Push(1); + s1.Push(2); + + s3 = s2 = s1; + + EXPECT_TRUE(s1 == s2); + EXPECT_TRUE(s2 == s3); + EXPECT_TRUE(s1 == s3); + + EXPECT_EQ(s1.Size(), 2); + EXPECT_EQ(s2.Size(), 2); + EXPECT_EQ(s3.Size(), 2); + + EXPECT_EQ(s1.Top(), 2); + EXPECT_EQ(s2.Top(), 2); + EXPECT_EQ(s3.Top(), 2); +} \ No newline at end of file From 3d65f3ae8b57c9e348b47a63ef1370ff99a9faf6 Mon Sep 17 00:00:00 2001 From: Andrey <88825623+Andrey23525@users.noreply.github.com> Date: Fri, 26 Dec 2025 23:52:47 +0500 Subject: [PATCH 8/8] delete a.out file --- 04_week/tasks/ring_buffer/a.out | Bin 287288 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 04_week/tasks/ring_buffer/a.out diff --git a/04_week/tasks/ring_buffer/a.out b/04_week/tasks/ring_buffer/a.out deleted file mode 100644 index 8f866d69bbe3298bb9a105339470bd61c70821a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287288 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�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�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