diff --git a/01_week/tasks/addition/addition.cpp b/01_week/tasks/addition/addition.cpp index 92872802..6b468949 100644 --- a/01_week/tasks/addition/addition.cpp +++ b/01_week/tasks/addition/addition.cpp @@ -3,5 +3,5 @@ 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/char_changer/char_changer.cpp b/01_week/tasks/char_changer/char_changer.cpp index 3a7344d9..39ef54d7 100644 --- a/01_week/tasks/char_changer/char_changer.cpp +++ b/01_week/tasks/char_changer/char_changer.cpp @@ -1,7 +1,98 @@ #include #include +#include // для is функций из https://en.cppreference.com/w/cpp/string/byte.html +#include +#include +// Пересчёт символов с выводом их кол-ва - есть . C>10 = C0 +// Замена непонятных символов (а не букв) на '_' - есть +// замена цифр на звездочки - есть +//22 заменились на звездочки и посчитались, вывелось *2 - есть +// Пробел заменился на ',' если передать в функцию чем заменяем - есть +//err: Проблема раннего перевода в верхний регистр. мб сделать поднятие в верхний регистр после того как повторяющиеся буквы заменились на букву+цифру повторения - есть size_t CharChanger(char array[], size_t size, char delimiter = ' ') { - throw std::runtime_error{"Not implemented"}; + if (size == 0) return 0; + + size_t outputArray = 0; + size_t i = 0; + + while (i < size && array[i] != '\0') { + char currentSymb = array[i]; + + //Смотрим пробелы + if (currentSymb == ' ') { + size_t spaceCounter = 1; + while (i + spaceCounter < size && array[i + spaceCounter] == ' ') { + spaceCounter++; + } + if (outputArray < size) { + array[outputArray++] = delimiter; + } + i += spaceCounter; + continue; + } + + //Для остальных символов + size_t sameSymbCounter = 1; + size_t nextSymb = i + 1; + + while (nextSymb < size && array[nextSymb] != '\0') { + if (array[nextSymb] == currentSymb) { + sameSymbCounter++; + nextSymb++; + } else { + break; + } + } + + //Преобразование символов + char transformed = '0'; + if (std::isdigit(currentSymb)) { + transformed = '*'; + } else if (std::islower(currentSymb)) { + transformed = std::toupper(currentSymb); + } else if (std::isupper(currentSymb)) { + transformed = currentSymb; + } else { + transformed = '_'; + } + + //Перепись великого пассажа + if (outputArray < size) { + array[outputArray++] = transformed; + } + + if (sameSymbCounter > 1) { + if (sameSymbCounter >= 10) { + if (outputArray < size) { + array[outputArray++] = '0'; + } + } else { + if (outputArray < size) { + array[outputArray++] = '0' + sameSymbCounter; + } + } + } + + i = nextSymb; // Для перехода к след итерации. + } + + if (outputArray < size) { + array[outputArray] = '\0'; + } else if (size > 0) { + array[size - 1] = '\0'; + outputArray = size - 1; + } + + return outputArray; } +// //Для отладки. И проверки своих выводов +// int main() { + +// char array[] = "aAaAaA_234_ssssDdd*$$ 3333a"; +// size_t size = 28; + +// CharChanger(array, size, ','); +// std::cout << array << std::endl; +// } diff --git a/01_week/tasks/check_flags/check_flags.cpp b/01_week/tasks/check_flags/check_flags.cpp index 75e7c652..001306bd 100644 --- a/01_week/tasks/check_flags/check_flags.cpp +++ b/01_week/tasks/check_flags/check_flags.cpp @@ -1,18 +1,96 @@ #include #include - - +#include +/* В stdexcept есть +Класс domain_error Этот класс служит базовым классом для всех исключений, создаваемых для сообщения об ошибке в домене. +Класс invalid_argument Этот класс служит базовым классом для всех исключений, создаваемых для сообщения о недопустимом аргументе. +Класс length_error Этот класс служит базовым для всех исключений, создаваемых для сообщения о попытке создания слишком длинного объекта. +Класс logic_error Этот класс служит базовым для всех исключений, создаваемых для сообщения об ошибках, которые можно обнаружить до выполнения программы, таких как нарушение логических предварительных условий. +Класс out_of_range Этот класс служит базовым для всех исключений, создаваемых для сообщения о том, что аргумент выходит за допустимый диапазон. +Класс overflow_error Этот класс служит базовым для всех исключений, создаваемых для сообщения об арифметическом переполнении. +Класс range_error Этот класс служит базовым для всех исключений, создаваемых для сообщения об ошибке в диапазоне. +Класс runtime_error Этот класс служит базовым для всех исключений, создаваемых для сообщения об ошибках, которые можно обнаружить только при выполнении программы. +Класс underflow_error Этот класс служит базовым для всех исключений, создаваемых для сообщения об арифметической неточности. +*/ enum class CheckFlags : uint8_t { - NONE = 0, - TIME = (1 << 0), - DATE = (1 << 1), - USER = (1 << 2), - CERT = (1 << 3), - KEYS = (1 << 4), - DEST = (1 << 5), - ALL = TIME | DATE | USER | CERT | KEYS | DEST + NONE = 0, // 0 0000000 + TIME = (1 << 0), // 1 0000001 + DATE = (1 << 1), // 2 0000010 + USER = (1 << 2), // 3 0000100 + CERT = (1 << 3), // 4 0001000 + KEYS = (1 << 4), // 5 0010000 + DEST = (1 << 5), // 6 0100000 + ALL = TIME | DATE | USER | CERT | KEYS | DEST // 7 1000000 }; +// 7 6 5 4 3 2 1 0 номера бит +// 128 64 32 16 8 4 2 1 степени дваойки , а вообще будет такт 127 макс число, тк 0 еще есть +/* +Берется битовая маска. напирмер 01010010. это значит что есть TIME, CERT, DEST + +// Сначала надо сделать преобразование в число +// Если число вдруг больше - выйти из проги +// Если равно нулю - вывести пустые скобки (флаг none) +// Проверяем каждый класс, если есть совпадение - выводим его +*/ void PrintCheckFlags(CheckFlags flags) { - throw std::runtime_error{"Not implemented"}; + + int flagValue = static_cast(flags) ; + bool isFirst = true; //Проверять первый элемент или нет будем так + + + if (flagValue > static_cast(CheckFlags::ALL)) return; + + if (flagValue == 0) { + std::cout << "[]"; + return; + } + +//Прошла жесткая проверка + std::cout << "["; + + if (flagValue & static_cast(CheckFlags::TIME)) { + if (!isFirst) {std::cout << ",";} + std::cout << "TIME"; + isFirst = false; + } + + + if (flagValue & static_cast(CheckFlags::DATE)) { + if (!isFirst) {std::cout << ",";} + std::cout << "DATE"; + isFirst = false; + } + + + if (flagValue & static_cast(CheckFlags::USER)) { + if (!isFirst) {std::cout << ",";} + std::cout << "USER"; + isFirst = false; + } + + + if (flagValue & static_cast(CheckFlags::CERT)) { + if (!isFirst) {std::cout << ",";} + std::cout << "CERT"; + isFirst = false; + } + + + if (flagValue & static_cast(CheckFlags::KEYS)) { + if (!isFirst) {std::cout << ",";} + std::cout << "KEYS"; + isFirst = false; + } + + if (flagValue & static_cast(CheckFlags::DEST)) { + if (!isFirst) {std::cout << ",";} + std::cout << "DEST"; + isFirst = false; + } + + + + std::cout << "]"; + } diff --git a/01_week/tasks/length_lit/length_lit.cpp b/01_week/tasks/length_lit/length_lit.cpp index e69de29b..be4f10b8 100644 --- a/01_week/tasks/length_lit/length_lit.cpp +++ b/01_week/tasks/length_lit/length_lit.cpp @@ -0,0 +1,97 @@ +#include +// Поскольку литералы - это константы +// Создание пользовательского литерала начинается с обозначения constexpr - Значение будет констатной и будет вычислено на этапе компиляции +// (по крайней мере компилятор будет пытаться это сделать:) +// explicit - запрет на неявный вызов. Если ожидается какой-то литерал, но он не найден - выдаст ошибку, мол я не нашел, не знаю чё делать +// Далее идет тип данных, который будет возвращать наш литерал +// Далее идет operator"" и после него название литерала _name +// Далее в скобках пишется принимаемое значение с определенным типом данных + +// необходимо создать 11 пользовательских литератов +// _ft_to_m +//_ft_to_cm +//_ft_to_in +//_in_to_m +//_in_to_cm +//_in_to_ft +//_m_to_ft +//_m_to_in +//_m_to_cm +//_cm_to_m +//_cm_to_ft +//_cm_to_in +// Прописать их логику подобным образом. необходимо правильно определить точность. Размер принимаемых значений. +// Причем все преобразования возвращают тип `double`. +/* +Параметры типов должны быть только такие: +const char +unsigned long long int // для целочисленного, но и то оно только unsigned типа +long double // просто double не проканает +char +wchar_t +char16_t +char32_t +const char'*', std::size_t +const wchar_t'*', std::size_t +const char16_t'*', std::size_t +const char32_t'*', std::size_t +*/ + +//1 фут = 0.3048 метра +//1 дюйм = 2.54 см = 0.0254м +// Только к 22 годам понял, что футы - это типо ноги. 30см то примерно стопа:) +//-----------------------------Футы В куда угодно------------------------ +constexpr long double operator""_ft_to_m(long double val) { + + return static_cast(val * 0.3048); +} + +constexpr long double operator""_ft_to_cm(long double val) { + return static_cast(val * 30.48); +} + +constexpr long double operator""_ft_to_in(long double val) { + return static_cast(val / 0.083333333); +} + +//-----------------------------Дюймы В куда угодно------------------------ + +constexpr long double operator""_in_to_m(long double val) { + return static_cast(val * 0.0254); +} + +constexpr long double operator""_in_to_cm(long double val) { + return static_cast(val * 2.54); +} + +constexpr long double operator""_in_to_ft(long double val) { + return static_cast(val / 12); +} + +//-----------------------------Метры В куда угодно------------------------ + +constexpr long double operator""_m_to_ft(long double val) { + return static_cast(val / 0.3048); +} + +constexpr long double operator""_m_to_in(long double val) { + return static_cast(val / 0.0254); +} + +constexpr long double operator""_m_to_cm(long double val) { + return static_cast(val * 100); +} + +//----------------------Сантиметры В куда угодно--------------------------- + +constexpr long double operator""_cm_to_m(long double val) { + return static_cast(val / 100); +} + +constexpr long double operator""_cm_to_ft(long double val) { + return static_cast(val / 30.48); +} + +constexpr long double operator""_cm_to_in(long double val) { + return static_cast(val / 2.54); +} diff --git a/01_week/tasks/print_bits/print_bits.cpp b/01_week/tasks/print_bits/print_bits.cpp index a48a43c1..e99928f9 100644 --- a/01_week/tasks/print_bits/print_bits.cpp +++ b/01_week/tasks/print_bits/print_bits.cpp @@ -1,7 +1,60 @@ #include #include +#include +#include +#include +// Если размер 1 числа - 0b0000'0000 +// Если размер 2 - 0b0000'0000'00000'000 +// Если размер 4 - 0b0000'0000'0000'0000'0000'0000'0000'0000 +// Если размер 8 - 0b0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000'0000 +// А если размер другой? например 16? Ограничим возможность представления других размеров, дабы тесты корректно выполнялись + +//Как перевести число в двоичную систему счисления? +//Берется десятичное число, напирмер 42 +// Если число не 10-чное, а например шестнадцатиричное или восьмиричное - приводим к десятичному +// делится на 2 до тех пор пока число не будет равно одному +// Запись остатков от деления ведется в массив +// Переворачивается задом на перед +// Выводится на экран в формате 0b[массив] +//!!!! При значении размера байт $bytes \notin (0, 8]$ функция ничего не выводит. - есть недопонимание. +// как бы cout << ""; - это вывод, но пустой, считается ли это что функция ничего не выводит? +// В тестах видно что есть разделитель между разрядами. Надо добавить + void PrintBits(long long value, size_t bytes) { - throw std::runtime_error{"Not implemented"}; -} + using namespace std; + + if (bytes != 1 && bytes != 2 && bytes != 4 && bytes != 8 ){ + cout << ""; //Просто return почему-то не работает, пока не могу понять почему. А так все тесты пройдены. + } + + const size_t bitValue = bytes * 8; + unsigned long long unsignedValue = 0; + + if (value < 0 && bytes < 8) { + switch (bytes) { + case 1: unsignedValue = static_cast(value); break; + case 2: unsignedValue = static_cast(value); break; + case 4: unsignedValue = static_cast(value); break; + default: unsignedValue = static_cast(value); + } + } else { + unsignedValue = static_cast(value); + } + + cout << "0b"; + + // Идем от старшего бита к младшему + for (int i = bitValue - 1; i >= 0; --i) { + unsigned long long bit = (unsignedValue >> i) & 1; + cout << bit; + + //Без разделителя тесты ругаются, добавим его + if (i > 0 && i % 4 == 0) { + cout << '\''; + } + } + + cout << endl; +} \ No newline at end of file diff --git a/01_week/tasks/quadratic/quadratic.cpp b/01_week/tasks/quadratic/quadratic.cpp index abf7d632..e7721fe7 100644 --- a/01_week/tasks/quadratic/quadratic.cpp +++ b/01_week/tasks/quadratic/quadratic.cpp @@ -1,6 +1,76 @@ #include +#include +#include +#include +// Дискриминант +//---если < 0 то корней нет(Если школьную версию пишем). +//---Если = 0. то два одинаковых корня. Выводим один. например x1 +//---Если > 0 - два корня и выводим их как x1,x2 (ps x1 < x2) +// У нас простой случай функции. ax^2+bx+c=0 +// Из тестов видно что если получается целое в результате то пишем int, а иначе double. Мне нужноо большее статик кастов + void SolveQuadratic(int a, int b, int c) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + +std::cout << std::setprecision(6); // конструкция для вывода. В целом и без нее всё проходится, но пусть будет по заданию + + //Особые случаи + if (a == 0 && b == 0 && c == 0){ + std::cout << "infinite solutions"; + return; + } + + if (a == 0) { + + if (b == 0) { + std::cout << "no solutions"; + return; } + + else { + double Ans = -static_cast(c) / b; + + if (Ans == static_cast(Ans)) { + std::cout << static_cast(Ans); + } else { + std::cout << Ans; + } + return; + } + } +//Решение + int D = b*b-4*a*c; + +//отриц дискриминант + if(D < 0){ + std::cout << "no solutions"; + return ; + } + + double x1 = (-b - sqrt(D)) / (2.0 * a); + double x2 = (-b + sqrt(D)) / (2.0 * a); + +//Для нулевого дискриминанта + if (D == 0) { + if (x1 == static_cast(x1)) { + std::cout << static_cast(x1); + } else { + std::cout << x1; + } + } else { +//Когда всё хорошо + if (x1 == static_cast(x1)) { + std::cout << static_cast(x1); + } else { + std::cout << x1; + } + + std::cout << " "; + + if (x2 == static_cast(x2)) { + std::cout << static_cast(x2); + } else { + std::cout << x2; + } + } +} diff --git a/01_week/tasks/rms/rms.cpp b/01_week/tasks/rms/rms.cpp index 6882f0a9..49c504ad 100644 --- a/01_week/tasks/rms/rms.cpp +++ b/01_week/tasks/rms/rms.cpp @@ -1,7 +1,23 @@ -#include +#include #include +#include +#include +//RMS - среднеквадратическое отклонение. +// Берем массив. Возводим текущее значение в квадрат, суммируем все значения, делим на кол-во элементов и всё под корень. 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 || size == 0) { + return 0.0; // доп проверка на nullptr. + } + + double RMS = 0.0; + for (size_t i = 0; i < size; ++i) { + RMS += values[i] * values[i] ; + + } + return sqrt(RMS / size); +} + diff --git a/02_week/tasks/func_array/func_array.cpp b/02_week/tasks/func_array/func_array.cpp index b327e68d..7bfee8c0 100644 --- a/02_week/tasks/func_array/func_array.cpp +++ b/02_week/tasks/func_array/func_array.cpp @@ -1,6 +1,40 @@ #include +#include +/* +0.1 - функции операций не должы имодифицировать исходные числа +1 - функция должна принять два числа, массив функций с опред.операциями, размер этого массива +2 - В зависимости от операции в функции будет разный результат +3 - нужно выдать 0.0 если что-то не то передали в функцию либо нет массива с операциями +4 - Можно пользоваться контейнерами +5- Результат является суммой результатов всех переданных в основную функцию действий над числами +// Создадим цикл который пройдется по всему переданному массиву функций, и сложит все результаты в этот момент -double ApplyOperations(double a, double b /* other arguments */) { - throw std::runtime_error{"Not implemented"}; + double(*)(double, double) Закрепим материал лекции. Читаем справа налево. + Функция принимающая два аргумента дабл -> указатель -> дабл. +//Для удобства создадим алиас. Некий пользовательный тип. указатель на функцию, которая принимает два double и возвращает doublе. Запутаешься так писать постоянно, + А прикол будет если бы этих конструкций было много в коде, попробуй ка все заменить. Вообще тяжко. + а так легко тут изменил да и и пошел пить чай + +*/ + +using funcType = double(*)(double, double); + +double ApplyOperations(double a, double b, funcType* arrayOp, size_t size) { + if (arrayOp == nullptr || size == 0) return 0.0; + + double resultSum = 0.0; + +for (size_t i = 0; i < size; ++i) { + funcType CurrentFunc = arrayOp[i]; + + if (CurrentFunc == nullptr) { + continue; + } + + double result = CurrentFunc(a, b); + resultSum += result; + } + + return resultSum; } \ No newline at end of file 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..5d3c32a6 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,32 @@ #include +/* +необходимо написать функцию которая будет находить последний элемент, удовлетворяющий функции-предикату +Функция-предикат — это функция, которая проверяет условие и всегда возвращает логическое значение true или false +//Функция принимает три указателя - на начало и конец целочисленного массива, а также на функцию предикат +// Если элемент не найден, то должен вернуться указатель на последний элемент (end) +//Указатели соответствуют диапазону $[begin, end)$. +1- Раз массив целочисленный. возвращать будем int +2 - Указатель на функцию предикат должен возвращать bool, принимая int +Что-то вроде bool(*)(int). Думаю сделать псевдоним для этой конструкции чтобы код стало приятнее читать, не знаю насчёт явности, но вроде явно. +3- теперь надо определиться как идти по массиву. С начала или с конца? - по сути с конца было бы быстрее тк мы же в конце ищем элемент(будет если не О(1), то что-то близкое), +но опять же пролистывать с начала мне более естественно и проще по пониманию(но тут всегд О(n)). +Но всё-таки наверно надо попробовать с конца. Но тут тогда появится риск что (end - 1) не всегда может быть +правильным. Иначе говоря, мне надо придумать проверку чтобы это условие выполнялось перед манипуляциями с циклом. +*/ +using PredicatePtr = bool(*)(int); +const int* FindLastElement(const int* begin,const int* end, PredicatePtr predicate) { + if (begin == nullptr + || end == nullptr + || predicate == nullptr + || begin == end + || begin > end) return end; -/* return_type */ FindLastElement(/* ptr_type */ begin, /* ptr_type */ end, /* func_type */ predicate) { - throw std::runtime_error{"Not implemented"}; +for (const int* ptr = end - 1; ptr >= begin; --ptr) { + if (predicate(*ptr)) { + return ptr; + } +} + +return end; } \ No newline at end of file diff --git a/02_week/tasks/little_big/little_big.cpp b/02_week/tasks/little_big/little_big.cpp index abe24379..da664eae 100644 --- a/02_week/tasks/little_big/little_big.cpp +++ b/02_week/tasks/little_big/little_big.cpp @@ -1,10 +1,63 @@ #include +#include +/* +//Две функции: +Одна для интов +Другая для дабл +//Принимает число возвращает число в шестрадцатиричной форме в формтате 0xYYYY; +//Нельзя использовать Сstyle Cast и контейнеры +В функцию передается вторым аргументом флаг который по запросу перевернет представление числа. Слева направо или справа налево (BE или LE). По умолчанию не инвертируем +// Для преобразования цифры в число сделаем массив всех чисел и букв для 16-ричной системы счисления +// Затем сделаем цифры символами чтобы вывести их на экран +// Тесты прошли, однако настроенный CI в гитхабе заругался на попытку сравнения знакового и беззнакового типа в цикле - -void PrintMemory(int /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +*/ +void PrintMemory(int number, bool reverseFlag = false) +{ + const unsigned char* bytes = reinterpret_cast(&number); + const char hexChars[] = "0123456789ABCDEF"; + + std::cout << "0x"; + const int size = static_cast(sizeof(number)); + + if (!reverseFlag) { + for (int i = 0; i < size; ++i) { + unsigned char currentByte = bytes[i]; + std::cout << hexChars[currentByte >> 4]; + std::cout << hexChars[currentByte & 0x0F]; + } + } else { + // С реверсом (BE) + for (int i = size - 1; i >= 0; --i) { + unsigned char currentByte = bytes[i]; + std::cout << hexChars[currentByte >> 4]; + std::cout << hexChars[currentByte & 0x0F]; + } + } + std::cout << std::endl; } -void PrintMemory(double /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; + +void PrintMemory(double number, bool reverseFlag = false) +{ + const unsigned char* bytes = reinterpret_cast(&number); + const char hexChars[] = "0123456789ABCDEF"; + + std::cout << "0x"; + const int size = static_cast(sizeof(number)); + + if (!reverseFlag) { + for (int i = 0; i < size; ++i) { + unsigned char currentByte = bytes[i]; + std::cout << hexChars[currentByte >> 4]; + std::cout << hexChars[currentByte & 0x0F]; + } + } else { + for (int i = size - 1; i >= 0; --i) { + unsigned char currentByte = bytes[i]; + std::cout << hexChars[currentByte >> 4]; + std::cout << hexChars[currentByte & 0x0F]; + } + } + std::cout << std::endl; } \ No newline at end of file diff --git a/02_week/tasks/longest/longest.cpp b/02_week/tasks/longest/longest.cpp index 04b3c354..39c68d1a 100644 --- a/02_week/tasks/longest/longest.cpp +++ b/02_week/tasks/longest/longest.cpp @@ -1,6 +1,66 @@ #include +#include +/* Функция должна находить наибольшую подпоследовательсть + 1- функция принимает два указателя ( на начало и на конец массива символов ) + 2- возвращает указатель на начало самой длинной подпоследовательности + 3- Длина подпоследовательности возвращается через третий аргумент функции. + 4- Указатели соответствуют диапазону $[begin, end)$. + // Если передано что-то не то, то возращается нулевой указатель nullptr + // Если подпоследовательности наибольшие одинаковой длины - возвращается первая +*/ +// .data() понадобится для указателя на начало последовательности. +// Из тестов видно, что например СССс - это не четыре. Регистр важен. +// С цифрами тоже работаем. +// Особенность: .append() и .push_back(). Оба добавляют что-то в конец, но .append может сразу несколько элементов добавить, а .push_back только один +// .append() в основном используется для пуша строк. по одной букве как-то долго, не так ли?) +// У нас встречаются как числа так и символы. если будем возвращать чисто int* или чисто char* то странно как-то. Надо иметь возможность и то и то. +// Тогда видимо придется перегружать функцию -/* return_type */ FindLongestSubsequence(/* ptr_type */ begin, /* ptr_type */ end, /* type */ count) { - throw std::runtime_error{"Not implemented"}; +const char* FindLongestSubsequence(const char* begin, const char* end, size_t& count) + { + if (begin == nullptr || end == nullptr || begin >= end) { + count = 0; return nullptr; + } + const char* best_begin = begin; + size_t maxLength = 1; + const char* current_begin = begin; + size_t currentLength = 1; + + for (const char* ptr = begin + 1; ptr != end; ++ptr) { + + if(*ptr == *(ptr - 1)) ++currentLength; + else { // если символ сменился + + if(currentLength > maxLength){ + maxLength = currentLength; + best_begin = current_begin; + + } + current_begin = ptr; + currentLength = 1; + } + } + + if(currentLength > maxLength){ + maxLength = currentLength; + best_begin = current_begin; + } + count = maxLength; + return best_begin; +} +// Вообще была идея изначально попробовать использовать template +// Это по сути было бы приятнее, но опять же тогда появился бы вопрос. Другой разработчик если бы начал читать код, не очевидно было бы +// Функция меняет что-то или не меняет? Она принимает констатны или нет? Пришлось бы внимателньо читать код и бегло уже не пройтись по коду. +// А как я знаю уже из опыта, любая сущность должна явно отражать что она делает исходя из названия и параметров +// Перегрузка +char* FindLongestSubsequence(char* begin, char* end, size_t& count) { + // Вызвав константную версию, приведем указатели к const + const char* result = FindLongestSubsequence( + static_cast(begin), + static_cast(end), + count + ); + // А затем снимаем констатность дабы всё прошло норм + return const_cast(result); } diff --git a/02_week/tasks/pretty_array/pretty_array.cpp b/02_week/tasks/pretty_array/pretty_array.cpp index 48eab341..5570e973 100644 --- a/02_week/tasks/pretty_array/pretty_array.cpp +++ b/02_week/tasks/pretty_array/pretty_array.cpp @@ -1,6 +1,79 @@ #include - - -void PrintArray(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +#include +#include +/* +Функция выводит целочисленный массив. +Принимает указатель на начало, конец массива ; также принимает ограничитель. 0 - нет ограничения, n - значит есть ограничение. +Причем задается кол-во элементов, если установлен ограничитель на n элементов, то а массив имеет n+m, то после n элементов +Будет через запятую троеточие, а в новой строке отступив пробел будет выводиться продолжение. +// Массив выводится в таком виде [, , , , ] +// Также из прошлого задания little big будет реализован разворот массива, однако здесь это задается не флагом, а условием: +указатель на end < указателя begin +// немного пробегусь по реализации: +1- Нужна проверка что указатели есть и массив вообще не нулевой. Проверяем nullptr +2- Проверка указателей. Как будет строиться массив, задом наперед или в прямом направлении +3- цикл for, который принимает элементы массива, и выкидывает их в cout в красивой форме [1, 2, 3, 4] +4- Условие цикла. Нужен счётчик при котором если наш элемент по счёту > чем ограничитель, мы печатаем ... +а затем в новой строке продолжаем перечисление элементов +5- вывод запятой не должен быть педед ] +//Было много недопонимания при продолжении печати после переноса, было принято добавить еще один аргумент в функию +некий флаг, который бы помог отличить функцию начальную, от функции которая вызвана рекурсивно. Так как тесты требуют что если задан ограничитель +то он будет всегда ограничивать одно и то же ко-во элементов, а массив может быть большим и переносов строк может быть не один. +// Будем пользоваться вкусными методами от vector. Так проще для восприятия. +*/ +void PrintArray(const int* begin, const int* end, size_t Limiter = 0, bool firstCall = true) +{ + if (begin == nullptr || end == nullptr) { + std::cout << "[]" << std::endl; + return; + } + // обратный порядок + if (begin > end) { + std::vector reversedArray = {}; + for (const int* currentItemPtr = begin; currentItemPtr != end; --currentItemPtr) { + reversedArray.push_back(*currentItemPtr); + } + +//Теперь вызываем для вектора (прямой порядок) + if (reversedArray.empty()) { + if (firstCall) std::cout << "[]" << std::endl; + else std::cout << "]" << std::endl; + } else { + PrintArray(reversedArray.data(), reversedArray.data() + reversedArray.size(), Limiter, firstCall); + } + return; + } + + // Прямой порядок (begin <= end) + if (begin == end) { + if (firstCall) std::cout << "[]" << std::endl; + else std::cout << "]" << std::endl; + return; + } + + if (firstCall) std::cout << "["; + + size_t remaining = end - begin; + + if (Limiter == 0 || Limiter >= remaining) { + // Без ограничения + for (const int* currentItemPtr = begin; currentItemPtr != end; ++currentItemPtr) { + if (currentItemPtr != begin) std::cout << ", "; + std::cout << *currentItemPtr; + } + std::cout << "]" << std::endl; + } else { + // с ограничителем + for (size_t i = 0; i < Limiter; ++i) { + if (i > 0) std::cout << ", "; + std::cout << begin[i]; + } + + if (begin + Limiter != end) { + std::cout << ", ...\n "; + PrintArray(begin + Limiter, end, Limiter, false); + } else { + std::cout << "]" << std::endl; + } + } } \ 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..40a3e292 100644 --- a/02_week/tasks/swap_ptr/swap_ptr.cpp +++ b/02_week/tasks/swap_ptr/swap_ptr.cpp @@ -1,6 +1,26 @@ #include -void SwapPtr(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +// В тестах есть три варианта каким могут быть аргументы 1-неконстартные указатели, 2 - константные указатели, 3 - указатели на указатели +// Тогда воспользуемся перегрузкой функций как из лекций. У нас тогда будет три функции одинаковые по содержанию и разные +// принимаемому значению. Тесты сами выберут чё им надо) + +void SwapPtr(int*& a, int*& b) { + int* tmp = a; + a = b; + b = tmp; +} + + +void SwapPtr(const int*& a, const int*& b) { + const int* tmp = a; + a = b; + b = tmp; +} + + +void SwapPtr(int**& a, int**& b) { + int** tmp = a; + a = b; + b = tmp; } \ No newline at end of file diff --git a/03_week/tasks/data_stats/data_stats.cpp b/03_week/tasks/data_stats/data_stats.cpp index b941c211..ecb0351c 100644 --- a/03_week/tasks/data_stats/data_stats.cpp +++ b/03_week/tasks/data_stats/data_stats.cpp @@ -1,11 +1,36 @@ #include +#include +#include +/* +Функция принимает на вход контейнер int, а возвращает структуру DataStats, в которой есть среднее отклонение average и стандарт отклонение standard deviation +Нельзя алгоритмы +Лучше решить в один проход +//Под корнем среднего отклонения не должно быть отрицательных чисел. Есть такая штука как std::max. Он сравнивает два аргумента и выдает наибольшой. +*/ - -struct DataStats { +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& Nums) { + DataStats resultOfMeasure; + size_t sizeNum = Nums.size(); + + if (sizeNum == 0) return DataStats{}; + + double sum = 0.0; + double sumSquares = 0.0; + + for (size_t i = 0; i < sizeNum; ++i) { + sum += Nums[i]; + sumSquares += static_cast(Nums[i]) * Nums[i]; + } + + resultOfMeasure.avg = sum / sizeNum; + double deviation = (sumSquares / sizeNum) - (resultOfMeasure.avg * resultOfMeasure.avg); + resultOfMeasure.sd = sqrt(std::max(deviation, 0.0)); + + return resultOfMeasure; + } diff --git a/03_week/tasks/easy_compare/easy_compare.cpp b/03_week/tasks/easy_compare/easy_compare.cpp index dd5cb7f6..00809969 100644 --- a/03_week/tasks/easy_compare/easy_compare.cpp +++ b/03_week/tasks/easy_compare/easy_compare.cpp @@ -1,16 +1,90 @@ #include - +#include struct Date { - unsigned year; - unsigned month; - unsigned day; + unsigned year = 0; + unsigned month = 0; + unsigned day = 0; }; +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 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 rhs < lhs; +} + +bool operator<=(const Date& lhs, const Date& rhs) { + return !(rhs < lhs); +} + +bool operator>=(const Date& lhs, const Date& rhs) { + return !(lhs < rhs); +} + struct StudentInfo { size_t id; char mark; int score; unsigned course; Date birth_date; -}; \ No newline at end of file +}; + +int markWeight(char mark) { + switch (mark) { + case 'Z': return 1; + case 'D': return 2; + case 'C': return 3; + case 'B': return 4; + case 'A': return 5; + default: return 0; + } +} + +bool operator==(const StudentInfo& lhs, const StudentInfo& rhs) { + return std::tie(lhs.mark, lhs.score) == + std::tie(rhs.mark, rhs.score); +} + +bool operator<(const StudentInfo& lhs, const StudentInfo& rhs) { + return std::make_tuple(markWeight(lhs.mark), + lhs.score, + -static_cast(lhs.course), + lhs.birth_date.year, + lhs.birth_date.month, + lhs.birth_date.day) + < + std::make_tuple(markWeight(rhs.mark), + rhs.score, + -static_cast(rhs.course), + rhs.birth_date.year, + rhs.birth_date.month, + rhs.birth_date.day); +} + +bool operator!=(const StudentInfo& lhs, const StudentInfo& rhs) { + return !(lhs == rhs); +} + +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); +} diff --git a/03_week/tasks/enum_operators/enum_operators.cpp b/03_week/tasks/enum_operators/enum_operators.cpp index a539be38..0d48c559 100644 --- a/03_week/tasks/enum_operators/enum_operators.cpp +++ b/03_week/tasks/enum_operators/enum_operators.cpp @@ -1,5 +1,23 @@ #include +#include #include +#include + +/* +Необходимо реализовать перегрузку побитовых операторов для перечисления `CheckFlags`: + +- `operator|` - возвращает результат побитового ИЛИ двух перечислений +- `operator&` - возвращает `true`, если все активные флаги одного операнда + присутствуют у другого операнда, иначе возвращает `false`. В случае когда у одного + из операндов нет активных флагов возвращает `false` +- `operator^` - возвращает результат исключающего ИЛИ двух перечислений. +- `operator~` - инвертирует установленные флаги (для `NONE` результат будет `ALL`) +- `operator<<` - выводит через запятую в произвольный поток вывода имена включенных + флагов проверки +// Думаю сделать мини функцию для маскирования + + +*/ enum class CheckFlags : uint8_t { NONE = 0, @@ -12,22 +30,106 @@ enum class CheckFlags : uint8_t { ALL = TIME | DATE | USER | CERT | KEYS | DEST }; -/* return_type */ operator|(/* args */) { - throw std::runtime_error{"Not implemented"}; +// Вспомогательная функция для маскирования +uint8_t maskFlags(CheckFlags flags) { + return static_cast(flags) & static_cast(CheckFlags::ALL); +} + +//operator| - побитовое ИЛИ +CheckFlags operator|(CheckFlags lhs, CheckFlags rhs) { + uint8_t result = maskFlags(lhs) | maskFlags(rhs); + return static_cast(result); } -/* return_type */ operator&(/* args */) { - throw std::runtime_error{"Not implemented"}; +// operator& - проверка что один набор содержит другой +bool operator&(CheckFlags lhs, CheckFlags rhs) { + uint8_t lhsMasked = maskFlags(lhs); + uint8_t rhsMasked = maskFlags(rhs); + + // Если любой из операндов NONE -> false (по условию) + if (lhsMasked == 0 || rhsMasked == 0) { + return false; + } + + return ((lhsMasked & rhsMasked) == lhsMasked) || + ((lhsMasked & rhsMasked) == rhsMasked); } -/* return_type */ operator^(/* args */) { - throw std::runtime_error{"Not implemented"}; +//operator^ - исключающее ИЛИ +CheckFlags operator^(CheckFlags lhs, CheckFlags rhs) { + uint8_t result = maskFlags(lhs) ^ maskFlags(rhs); + return static_cast(result); } -/* return_type */ operator~(/* args */) { - throw std::runtime_error{"Not implemented"}; +//operator~ - инвертирование +CheckFlags operator~(CheckFlags flags) { + uint8_t masked = maskFlags(flags); + uint8_t inverted = ~masked; + uint8_t result = inverted & static_cast(CheckFlags::ALL); + + return static_cast(result); } -/* return_type */ operator<<(/* args */) { - throw std::runtime_error{"Not implemented"}; +// operator<< - вывод в поток +std::ostream& operator<<(std::ostream& os, CheckFlags flags) { + uint8_t masked = maskFlags(flags); + + if (masked == 0) { + os << "NONE"; + return os; + } + + if (masked == static_cast(CheckFlags::ALL)) { + os << "TIME, DATE, USER, CERT, KEYS, DEST"; + return os; + } + + bool isFirst = true; + + // Проверяем каждый флаг + if (masked & static_cast(CheckFlags::TIME)) { + os << "TIME"; + isFirst = false; + } + + if (masked & static_cast(CheckFlags::DATE)) { + if (!isFirst) { + os << ", "; + } + os << "DATE"; + isFirst = false; + } + + if (masked & static_cast(CheckFlags::USER)) { + if (!isFirst) { + os << ", "; + } + os << "USER"; + isFirst = false; + } + + if (masked & static_cast(CheckFlags::CERT)) { + if (!isFirst) { + os << ", "; + } + os << "CERT"; + isFirst = false; + } + + if (masked & static_cast(CheckFlags::KEYS)) { + if (!isFirst) { + os << ", "; + } + os << "KEYS"; + isFirst = false; + } + + if (masked & static_cast(CheckFlags::DEST)) { + if (!isFirst) { + os << ", "; + } + os << "DEST"; + } + + return os; } diff --git a/03_week/tasks/filter/filter.cpp b/03_week/tasks/filter/filter.cpp index 6648cb39..767169aa 100644 --- a/03_week/tasks/filter/filter.cpp +++ b/03_week/tasks/filter/filter.cpp @@ -1,6 +1,29 @@ #include +#include +/* +Функция принимает std::vector +и указатель на функцию предикат, и оставляет в контейнере элементы, +удовлетворяющие предикату, в исходном порядке. +Нельзя алгоритм +Алгоритм долэен проходить за O(n) +*/ -/* return_type */ Filter(/* args */) { - throw std::runtime_error{"Not implemented"}; +using PredicatePtr = bool(*)(int); +void Filter(std::vector& array, PredicatePtr predicate) { + if (!predicate) return; + + + size_t writeIndex = 0; + + for (size_t readIndex = 0; readIndex < array.size(); ++readIndex) { + if (predicate(array[readIndex])) { + if (writeIndex != readIndex) { + array[writeIndex] = std::move(array[readIndex]); + } + ++writeIndex; + } + } + + array.resize(writeIndex); } \ 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..7b889847 100644 --- a/03_week/tasks/find_all/find_all.cpp +++ b/03_week/tasks/find_all/find_all.cpp @@ -1,6 +1,32 @@ #include +#include +/* +Функция принимает на вход std::vector и указатель на функцию-предикат +Возвращает контейнер позиций всех элементов, удовлетворяющих предикату. +Нельзя алгоритмы +//Люблю я всё-таки эти псевдонимы. Как в одном из прошлых заданий, будет также добавлено кастомное название для типа функции. +// Тесты хотят чтобы вернулся std::vector +// Воспользуемся методом .shrink_to_fit(); для подгона размера вектора и то что там находится. +// В одной из прошлых задач было реализовано два прогона цикла, сначала проходимся и определяем размер, а только потом заполняем +// Оказывается есть вкусный метод, который сделает это в одну строчку, но опять же, скорее всего это более затратно. Так как происходит полная переаллокация +// Сейчас нам не особо важно это, но когда будет огромное кол-во элементов там то уже наверно и скажется на скорости +// Но цель то обучиться, поэтому надо все попробовать)) +*/ - -/* return_type */ FindAll(/* args */) { - throw std::runtime_error{"Not implemented"}; +using PredicatePtr = bool(*)(int); +std::vector FindAll(const std::vector& wetArray, PredicatePtr predicateFunc) +{ + if (!predicateFunc) return {}; + + std::vector result; + result.reserve(wetArray.size()); + + for (size_t i = 0; i < wetArray.size(); ++i) { + if (predicateFunc(wetArray[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..ad62ffa0 100644 --- a/03_week/tasks/minmax/minmax.cpp +++ b/03_week/tasks/minmax/minmax.cpp @@ -1,6 +1,39 @@ #include +#include +/* +Функция должна найти максимальное и минимальное число в переданном ей std::vector. +1.Вернуть должна пару итераторов, указывающих на миминмал и максимал элементы +2.Нельзя алгоритмы +3.Надо найти максимал и минимал элемент за один проход +4.для пустого контейнера необходимо вернуть пару итераторов на конец контейнера. +5.В случае нескольких одинаковых элементов, итератор на минимум должен указывать + на первое вхождение, итератор на максимум на последнее вхождение соответствующих + элементов +// Спустя несколько попыток решить задачу, наконец дошло что обычная структура не подойдет, надо бы использовать std::pair как возвращаемое значение +// Думаю никто не обидется если длинное некрасивое нечто в возвращаемом значении заменю одной фразой, так приятнее. +// Хотя наверно можно было просто написать auto в возвр. значении, но мне не нравится эта непонятная штука, не очевидная. +//Итераторы ведут себя примерно также как указатели, но они могут быть и не указателями, а хоть чем. Это абстракция некая над указателем, если можно так сказать +*/ -/* return_type */ MinMax(/* args */) { - throw std::runtime_error{"Not implemented"}; +using IteratorsPairReturn = std::pair::const_iterator,std::vector::const_iterator> ; + +IteratorsPairReturn MinMax(const std::vector& wetArray) +{ + if (wetArray.empty() == true) return {wetArray.end(), wetArray.end()}; + + //оба итератора на .begin потому что если вектор не пустой, первый элемент одновременно является и текущим минимумом, и текущим максимумом. По сути + auto minIt = wetArray.begin(); + auto maxIt = wetArray.begin(); + //Тогда начинаем итерироваться с +1 значения, тк первый это и есть и минимум и максимум, до тех пор пока его не изменим + for (auto iter = wetArray.begin() + 1; iter != wetArray.end(); ++iter) { + if (*iter < *minIt) { + minIt = iter; + } + else if (*iter >= *maxIt) { + maxIt = iter; + } + } + + return std::make_pair(minIt, maxIt); } diff --git a/03_week/tasks/os_overload/os_overload.cpp b/03_week/tasks/os_overload/os_overload.cpp index e473418d..4d5da085 100644 --- a/03_week/tasks/os_overload/os_overload.cpp +++ b/03_week/tasks/os_overload/os_overload.cpp @@ -1,21 +1,66 @@ #include #include #include - +#include struct Coord2D { - int x; - int y; + int x = 0; + int y = 0; }; struct Circle { Coord2D coord; - unsigned radius; + unsigned radius = 1; // по умолчанию 1 }; using CircleRegion = std::pair; using CircleRegionList = std::vector; -/* return_type */ operator<<(/* args */) { - throw std::runtime_error{"Not implemented"}; +//оператор вывода для Coord2D +std::ostream& operator<<(std::ostream& os, const Coord2D& coord) { + os << "(" << coord.x << ", " << coord.y << ")"; + return os; +} + +// Оператор вывода для Circle +std::ostream& operator<<(std::ostream& os, const Circle& circle) { + os << "circle["; + + if (circle.radius != 0) { + os << circle.coord << ", r = " << circle.radius; + } + + os << "]"; + return os; +} + +// Оператор вывода для CircleRegion +std::ostream& operator<<(std::ostream& os, const CircleRegion& region) { + + if (region.second) { + os << "+"; + } else { + os << "-"; + } + os << region.first; + return os; +} + + // Оператор вывода для CircleRegionList +std::ostream& operator<<(std::ostream& os, const CircleRegionList& list) { + os << "{"; + + if (!list.empty()) { + 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; } diff --git a/03_week/tasks/range/range.cpp b/03_week/tasks/range/range.cpp index d2085495..75b5fe40 100644 --- a/03_week/tasks/range/range.cpp +++ b/03_week/tasks/range/range.cpp @@ -1,7 +1,42 @@ #include #include +/* +Функция принимает значение начала и конца диапазона и шаг +Возвращает вектор std::vector из значений с опред шагом +По умолчанию шаг = 1 +[from, to) +Нельзя алгоритмы +Если выделять память, то под нужное количество элементов заранее +//Отрациательный шаг тоже шаг +*/ -std::vector Range(int from, int to, int step) { - throw std::runtime_error{"Not implemented"}; +std::vector Range(int from, int to, int step = 1) +{ + if (step == 0) return {}; + int countSteps = 0; + + if (step > 0 && from < to) { + countSteps = (to - from + step - 1) / step; + } + else if (step < 0 && from > to) { + countSteps = (from - to - step - 1) / (-step); + } + + if (countSteps <= 0) return {}; + + std::vector rangedArray = {}; + rangedArray.reserve(countSteps); + + if (step > 0) { + for (int i = from; i < to; i += step) { + rangedArray.push_back(i); + } + } else { + for (int i = from; i > to; i += step) { + rangedArray.push_back(i); + } + } + + return rangedArray; } diff --git a/03_week/tasks/unique/unique.cpp b/03_week/tasks/unique/unique.cpp index 9d2545bb..678a809e 100644 --- a/03_week/tasks/unique/unique.cpp +++ b/03_week/tasks/unique/unique.cpp @@ -1,6 +1,34 @@ #include #include +/* +Функция принимает отсортированный вектор std::vector и возвращает уникальные элементы в порядке их встречи (то есть массив тоже будет, из тестов вижу целочисленный) +Нельзя алгоритмы +Не надо частых аллокаций +Вместимость сделать соответствующей кол-ву элементов +//Вообще можно использовать std::unique и тогда можно сделать код в раазыыы короче, но я не понимаю насколько это оправданно. Насколько этот std:unique эффективен +Написал без него, мне кажется моя версия должна быть эффективнее по памяти так как unique более тяжелая и мощная вещь. +*/ -/* return_type */ Unique(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::vector Unique(const std::vector& inputArray) { + size_t size = inputArray.size(); + if (size == 0) return {}; + + size_t uniqueCount = 1; + for (size_t i = 1; i < size; ++i) { + if (inputArray[i] != inputArray[i-1]) { + ++uniqueCount; + } + } + + std::vector outputArray; + outputArray.reserve(uniqueCount); + + outputArray.push_back(inputArray[0]); + for (size_t i = 1; i < size; ++i) { + if (inputArray[i] != inputArray[i-1]) { + outputArray.push_back(inputArray[i]); + } + } + + return outputArray; } diff --git a/04_week/tasks/phasor/phasor.cpp b/04_week/tasks/phasor/phasor.cpp index 3ec1b9ad..093e56b6 100644 --- a/04_week/tasks/phasor/phasor.cpp +++ b/04_week/tasks/phasor/phasor.cpp @@ -1,10 +1,372 @@ +#include +#include +#include +#include // Для форматирования вывода +/* +Необходимо реализовать класс, представляющий комплесн амплитуду +Комплексная амплитуда может быть реализована в различных формах: алгебраическая, показательная, тригонометрическая, временная +- Конструктор по умолчанию создает нулевой фазор. +- Конструктор, принимающий амплитуду и фазу в радианах. +Конструкторы с тегами `ExpTag`, `DegTag`, `AlgTag` в качестве третьего параметра: +- Конструктор с тегом `ExpTag` - делегирует работу основному конструктору +- Конструктор с тегом `DegTag` - из амплитуды и фазы в градусах +- Конструктор с тегом `AlgTag` - из алгебраической формы записи (_real_, _imag_) +//Нельзя `std::complex` +- Операторы `+` и `-` удобно реализовывать в декартовых координатах +- Операторы `*` и `/` удобно реализовывать в полярных координатах +Реализовать перегрузку оператора `<<` для вывода комплексной амплитуды в +поток в формате: + +`{mag}*e(j*{arg}) [{real} + j*{imag}]`, где + +- `{mag}` - амплитуда +- `{arg}` - аргумент в градусах +- `{real}` - действительная часть +- `{imag}` - мнимая часть +Также предоставляются синонимы: +- Метод `Abs` - синоним метода `Magnitude` +- Метод `Angle` - синоним метода `Phase` +- Метод `A +//также необходима реализация и доступность арфим. операций "+" "-" "*" ; "/" ; "унарный -"" +//Нужна перегрузка += -= *= /= +Мыыы друзьяя, а для них, у друзей нет выходных +//Ключевое слово friend позволяет внешней функции или классу получать доступ к приватным private и защищенным protected членам класса. +-Дается прямой доступ к приватным полям +-Не вызывает методы +-Не наследуется +-Нет двунаправленности(например если А дружит с Б, значит Б является другом А, но не наоборот). +Понадобилось для перегрузки вывода. Можно и по-другому, но мне просто понравилось это. +//Из тестов видно, что нужен setprecition(3) или что-то подобное +/////Осталась часть, которая дублируется на мой взгляд, но как это грамотно исправить пока не знаю(в конце кода где операторы) +1. Бинарные операторы (не члены класса) +2. Операторы с вещественными числами +*/ struct ExpTag {}; struct DegTag {}; struct AlgTag {}; - class Phasor { +public: + Phasor() : real_(0.0), imag_(0.0) {} // конструкторы + Phasor(double magnitude, double phaseRad); + Phasor(double magnitude, double phaseRad, ExpTag tag); + Phasor(double magnitude, double phaseDeg, DegTag tag); + Phasor(double real, double imag, AlgTag tag); + + void SetPolar(double magnitude, double phase_rad); + void SetCartesian(double real, double imag); + + double Magnitude() const; + double Phase() const; + double PhaseDeg() const; + double Real() const; + double Imag() const; + //Синонимы + double Abs() const { return Magnitude(); } + double Angle() const { return Phase(); } + double AngleDeg() const { return PhaseDeg(); } + + Phasor operator+() const; + Phasor operator-() const; + + Phasor& operator+=(const Phasor& other); + Phasor& operator-=(const Phasor& other); + Phasor& operator*=(const Phasor& other); + Phasor& operator/=(const Phasor& other); + + Phasor& operator+=(double scalar); + Phasor& operator-=(double scalar); + Phasor& operator*=(double scalar); + Phasor& operator/=(double scalar); + Phasor Conj() const; + Phasor Inv() const; + + friend bool operator==(const Phasor& lhs, const Phasor& rhs); + friend bool operator!=(const Phasor& lhs, const Phasor& rhs); + + friend std::ostream& operator<<(std::ostream& os, const Phasor& p); + +private: + double real_; + double imag_; + + static double NormalizeAngle(double angleRad); + static double DegToRad(double deg); + static double RadToDeg(double rad); }; + +Phasor MakePhasorCartesian(double real, double imag); +Phasor MakePhasorPolar(double magnitude, double phaseRad); +Phasor MakePhasorPolarDeg(double magnitude, double phaseDeg); + +// Реализации конструкторов +Phasor::Phasor(double magnitude, double phaseRad) { + SetPolar(magnitude, phaseRad); +} + +Phasor::Phasor(double magnitude, double phaseRad, ExpTag) + : Phasor(magnitude, phaseRad) { //Делегирование +} + +Phasor::Phasor(double magnitude, double phaseDeg, DegTag) { + SetPolar(magnitude, DegToRad(phaseDeg)); +} + +Phasor::Phasor(double real, double imag, AlgTag) + : real_(real), imag_(imag) { + // уже в декартовых координатах +} + +// Реализации методов +void Phasor::SetPolar(double magnitude, double phaseRad) { + phaseRad = NormalizeAngle(phaseRad); + real_ = magnitude * std::cos(phaseRad); + imag_ = magnitude * std::sin(phaseRad); +} + +void Phasor::SetCartesian(double real, double imag) { + real_ = real; + imag_ = imag; +} + +double Phasor::Magnitude() const { + return std::sqrt(real_ * real_ + imag_ * imag_); +} + +double Phasor::Phase() const { + if (real_ == 0.0 && imag_ == 0.0) return 0.0; // для нулевого фазора фаза не определена, возвращаем 0 + return std::atan2(imag_, real_); // лучше чем std::atan(y/x) тк обрабатывает все квадранты и синтаксис приятнее +} + +double Phasor::PhaseDeg() const { + return RadToDeg(Phase()); +} + +double Phasor::Real() const { + return real_; +} + +double Phasor::Imag() const { + return imag_; +} + +Phasor Phasor::operator+() const { + return *this; // унарный "+"" ничего не меняет +} + +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 mag1 = Magnitude(); + double mag2 = other.Magnitude(); + double phase1 = Phase(); + double phase2 = other.Phase(); + + double newMag = mag1 * mag2; + double newPhase = phase1 + phase2; + + SetPolar(newMag, newPhase); + return *this; +} + +Phasor& Phasor::operator/=(const Phasor& other) { + // Деление в полярных координатах + double mag1 = Magnitude(); + double mag2 = other.Magnitude(); + + if (mag2 == 0.0) throw std::runtime_error("division by zero detected"); //кидать всякое я уже умею. В тестах деление на ноль не проверяется, но пусть будет. не мешает же + + double phase1 = Phase(); + double phase2 = other.Phase(); + + double newMag = mag1 / mag2; + double newPhase = phase1 - phase2; + + SetPolar(newMag, newPhase); + return *this; +} + +Phasor& Phasor::operator+=(double scalar) { + real_ += scalar; + return *this; +} + +Phasor& Phasor::operator-=(double scalar) { + real_ -= scalar; + return *this; +} + +Phasor& Phasor::operator*=(double scalar) { + real_ *= scalar; + imag_ *= scalar; + return *this; +} + +Phasor& Phasor::operator/=(double scalar) { + if (scalar == 0.0) throw std::runtime_error("division by zero detected"); + real_ /= scalar; + imag_ /= scalar; + return *this; +} + +//Спец и доп. методы +//Сопряженное число. То есть если было x=a+ib, то вернется x'=a-ib +Phasor Phasor::Conj() const { + return Phasor(real_, -imag_, AlgTag()); +} + +Phasor Phasor::Inv() const { + // 1/z = conj(z) / |z|^2 + double mag_sq = real_ * real_ + imag_ * imag_; + + return Phasor(real_ / mag_sq, -imag_ / mag_sq, AlgTag()); +} + +double Phasor::NormalizeAngle(double angleRad) { + // Приводим угол к диапазону (-П, П]. Это надо потому что каждые 360 градусов ничего не меняют 370=10 + const double two_pi = 2.0 * M_PI; + // Убираем полные обороты + angleRad = std::fmod(angleRad, two_pi); //Нашел fmod. Возвращает остаток от деления. Работает как сколько останется от x после вычитания максимально возможного количества целых y + // Приводим к (-П, П] + if (angleRad > M_PI) { + angleRad -= two_pi; + } else if (angleRad <= -M_PI) { + angleRad += two_pi; + } + + return angleRad; +} + +double Phasor::DegToRad(double deg) { + return deg * M_PI / 180.0; +} + +double Phasor::RadToDeg(double rad) { + return rad * 180.0 / M_PI; +} + +// Дружественные операторы сравнения +bool operator==(const Phasor& lhs, const Phasor& rhs) { + const double eps = 1e-10; // точность сравнения + return std::abs(lhs.real_ - rhs.real_) < eps && + std::abs(lhs.imag_ - rhs.imag_) < eps; +} + +bool operator!=(const Phasor& lhs, const Phasor& rhs) { + return !(lhs == rhs); +} + +// Дружественный оператор вывода +std::ostream& operator<<(std::ostream& os, const Phasor& p) { + double mag = p.Magnitude(); + double arg_deg = p.PhaseDeg(); + double real = p.Real(); + double imag = p.Imag(); + + // Устанавливаем фиксированный формат и точность 3 знака после запятой(тесты требуют) + os << std::fixed << std::setprecision(3); + os << mag << "*e(j*" << arg_deg << ") [" + << real << " + j*" << imag << "]"; + + // Восстанавливаем состояние потока после наших издевательств над ним + os.unsetf(std::ios_base::floatfield); + os.precision(6); // стандартная точность + + return os; +} +// Бинарные операторы (не члены класса) +Phasor operator+(const Phasor& lhs, const Phasor& rhs) { + Phasor result = lhs; + result += rhs; + return result; +} + +Phasor operator-(const Phasor& lhs, const Phasor& rhs) { + Phasor result = lhs; + result -= rhs; + return result; +} + +Phasor operator*(const Phasor& lhs, const Phasor& rhs) { + Phasor result = lhs; + result *= rhs; + return result; +} + +Phasor operator/(const Phasor& lhs, const Phasor& rhs) { + Phasor result = lhs; + result /= rhs; + return result; +} + +// Операторы с вещественными числами +Phasor operator+(const Phasor& phasor, double scalar) { + Phasor result = phasor; + result += scalar; + return result; +} + +Phasor operator+(double scalar, const Phasor& phasor) { + return phasor + scalar; // коммутативность +} + +Phasor operator-(const Phasor& phasor, double scalar) { + Phasor result = phasor; + result -= scalar; + return result; +} + +Phasor operator-(double scalar, const Phasor& phasor) { + return Phasor(scalar, 0, AlgTag()) - phasor; +} + +Phasor operator*(const Phasor& phasor, double scalar) { + Phasor result = phasor; + result *= scalar; + return result; +} + +Phasor operator*(double scalar, const Phasor& phasor) { + return phasor * scalar; // коммутативность +} + +Phasor operator/(const Phasor& phasor, double scalar) { + Phasor result = phasor; + result /= scalar; + return result; +} + +Phasor operator/(double scalar, const Phasor& phasor) { + return Phasor(scalar, 0, AlgTag()) / phasor; +} + +// Функции создания +Phasor MakePhasorCartesian(double real, double imag) { + return Phasor(real, imag, AlgTag()); +} + +Phasor MakePhasorPolar(double magnitude, double phaseRad) { + return Phasor(magnitude, phaseRad); +} + +Phasor MakePhasorPolarDeg(double magnitude, double phaseDeg) { + return Phasor(magnitude, phaseDeg, DegTag()); +} \ No newline at end of file diff --git a/04_week/tasks/queue/queue.cpp b/04_week/tasks/queue/queue.cpp index 2a9f8493..ee420478 100644 --- a/04_week/tasks/queue/queue.cpp +++ b/04_week/tasks/queue/queue.cpp @@ -1,6 +1,182 @@ #include +#include +/* +//очередь работает по принципу FIFO. +//Нельзя `std::queue`, `std::deque`, `std::list` +// Методы определяем вне класса +//Была идея использовать algorithm, но оттуда чисто один метод нужен был, проше уж самому реализовать через цикл, а не тащить целую библиотеку +//необходима реализация в зависимости от конструктора. +//Добавил строгости в преобразовании. запрет на неявность. explicit +*/ + + class Queue { +public: + //Конструкторы + Queue() = default; + explicit Queue(size_t capacity); + explicit Queue(const std::vector& vec); + Queue(std::initializer_list init); + explicit Queue(const std::stack& stack); + //Методы + void Push(int value); + void Clear(); + void Swap(Queue& otherQueue); + + int& Front(); + const int& Front() const; + int& Back(); + const int& Back() const; + + bool Pop(); + bool Empty() const; + size_t Size() const; + + bool operator==(const Queue& otherQueue) const; + bool operator!=(const Queue& otherQueue) const; +private: + std::vector inputDat; + std::vector outputDat; + + void MoveInputToOutput() { + while (!inputDat.empty()) { + outputDat.push_back(inputDat.back()); + inputDat.pop_back(); + } + } }; + +// Реализации конструкторов +Queue::Queue(size_t capacity) { + inputDat.reserve(capacity / 2 + 1); + outputDat.reserve(capacity / 2 + 1); +} + +Queue::Queue(const std::vector& vec) : inputDat(vec) {} + +Queue::Queue(std::initializer_list initList) : inputDat(initList) {} + +Queue::Queue(const std::stack& stack) { + std::stack temp = stack; + // Извлекаем элементы из стека в обратном порядке + while (!temp.empty()) { + inputDat.insert(inputDat.begin(), temp.top()); + temp.pop(); + } +} + +// Реализации методов +void Queue::Push(int value) { + inputDat.push_back(value); +} + +void Queue::Clear() { + inputDat.clear(); + outputDat.clear(); +} + +void Queue::Swap(Queue& otherQueue) { + inputDat.swap(otherQueue.inputDat); + outputDat.swap(otherQueue.outputDat); +} + +int& Queue::Front() { + if (outputDat.empty()) { + MoveInputToOutput(); + } + return outputDat.back(); +} + +const int& Queue::Front() const { + if (outputDat.empty()) { + // Создаем временные копии + std::vector tempInput = inputDat; + std::vector tempOutput = outputDat; + + // Перекладываем элементы + while (!tempInput.empty()) { + tempOutput.push_back(tempInput.back()); + tempInput.pop_back(); + } + + static int returnZero = 0; + if (!tempOutput.empty()) { + returnZero = tempOutput.back(); + } + return returnZero; + } + return outputDat.back(); +} + +int& Queue::Back() { + if (!inputDat.empty()) return inputDat.back(); + if (!outputDat.empty()) return outputDat.front(); + + static int returnZero = 0; + return returnZero; +} + +const int& Queue::Back() const { + if (!inputDat.empty()) return inputDat.back(); + if (!outputDat.empty()) return outputDat.front(); + + static int returnZero = 0; + return returnZero; +} + +bool Queue::Pop() { + if (Empty()) { + return false; + } + + if (outputDat.empty()) { + MoveInputToOutput(); + } + + outputDat.pop_back(); + return true; +} + +bool Queue::Empty() const { + return inputDat.empty() && outputDat.empty(); +} + +size_t Queue::Size() const { + return inputDat.size() + outputDat.size(); +} + +bool Queue::operator==(const Queue& otherQueue) const { + if (Size() != otherQueue.Size()) return false; + if (Empty()) return true; + +//Для одной очереди + std::vector temp1; + + if (!outputDat.empty()) { + for (size_t i = outputDat.size(); i > 0; --i) { + temp1.push_back(outputDat[i - 1]); + } + } + for (size_t i = 0; i < inputDat.size(); ++i) { + temp1.push_back(inputDat[i]); + } + +//Для второй очереди + std::vector temp2; + if (!otherQueue.outputDat.empty()) { + for (size_t i = otherQueue.outputDat.size(); i > 0; --i) { + temp2.push_back(otherQueue.outputDat[i - 1]); + } + } + for (size_t i = 0; i < otherQueue.inputDat.size(); ++i) { + temp2.push_back(otherQueue.inputDat[i]); + } + return temp1 == temp2; +} + +bool Queue::operator!=(const Queue& otherQueue) const { + return !(*this == otherQueue); +} diff --git a/04_week/tasks/ring_buffer/ring_buffer.cpp b/04_week/tasks/ring_buffer/ring_buffer.cpp index e2b57ba2..9308d721 100644 --- a/04_week/tasks/ring_buffer/ring_buffer.cpp +++ b/04_week/tasks/ring_buffer/ring_buffer.cpp @@ -1,6 +1,227 @@ #include - +#include //Осваиваю throw вместо простого return что-то +/* +Необходимо реализовать кольцевой буфер фиксированного размера, построенный на контейнере вектора интов +//Нельзя `std::queue`, `std::deque`, `std::list` +При добавлении в заполненный буфер перезаписывается самый старый элемент. +Может хранить либо позиции начала, конца и размер буфера, либо указатели на +соответствующие позиции. +//Нельзя сконструировать буфер нулевого размера, минимально 1 +//Методы определяем вне класса, исключение - приватные вспомогательные методы. +- Конструктор от вместимости буфера +- Конструктор от вместимости буфера и начального значения, заполняет весь буфер +- Конструктор от `std::initializer_list`, вместимость соответствует размеру контейнера. +//Исходя из прошлых ошибок по оформлению теперь использую name_ для обозначения переменных класса, для явности пренадлежности +// Постарался побольше использовать тернарные операторы так где это оправданно. +*/ class RingBuffer { +public: + explicit RingBuffer(size_t capacity); + RingBuffer(size_t capacity, int initialValue); + RingBuffer(std::initializer_list init); + + void Push(int value); + bool TryPush(int value); + + bool 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 newCapacity); + + std::vector Vector() const; + + bool operator==(const RingBuffer& other) const; + bool operator!=(const RingBuffer& other) const; + int& operator[](size_t index); + const int& operator[](size_t index) const; + +private: + std::vector buffer_; + size_t oldestElement_ = 0; + size_t indexNextElem_ = 0; + size_t currentCountElem_ = 0; + //Для удобства добавил следующие конструкции: + size_t NextIndex(size_t index) const { + return (index + 1) % buffer_.capacity(); + } + + size_t PhysicalIndex(size_t logical) const { + return (oldestElement_ + logical) % buffer_.capacity(); + } + void ValidateIndex(size_t index) const { + if (index >= currentCountElem_) throw std::out_of_range("out of range"); + } + + void ValidateNotEmpty() const { + if (Empty()) throw std::logic_error("Buff is empty"); + } }; + +RingBuffer::RingBuffer(size_t capacity) { + capacity = capacity ? capacity : 1; // минимум 1 по тз + buffer_.reserve(capacity); + buffer_.resize(capacity); + oldestElement_ = 0; + indexNextElem_ = 0; + currentCountElem_ = 0; +} + +RingBuffer::RingBuffer(size_t capacity, int initialValue) + : RingBuffer(capacity) { //жесточайшее делегирование и лень) + if (capacity > 0) { + for (size_t i = 0; i < capacity; ++i) { + Push(initialValue); + } + } else { + buffer_[0] = initialValue; + indexNextElem_ = 1 % buffer_.capacity(); + currentCountElem_ = 1; + } +} + +RingBuffer::RingBuffer(std::initializer_list init) { + size_t capacity = init.size() ? init.size() : 1; + buffer_.reserve(capacity); + buffer_.resize(capacity); + oldestElement_ = 0; + indexNextElem_ = 0; + currentCountElem_ = 0; + for (int value : init) Push(value); //Добавил range based, так как будто бы уютнее смотрится +} + +void RingBuffer::Push(int value) { + if (Full()) { + buffer_[indexNextElem_] = value; + oldestElement_ = NextIndex(oldestElement_); + indexNextElem_ = NextIndex(indexNextElem_); + } else { + buffer_[indexNextElem_] = value; + indexNextElem_ = NextIndex(indexNextElem_); + ++currentCountElem_; + } +} + +bool RingBuffer::TryPush(int value) { + if (Full()) return false; + buffer_[indexNextElem_] = value; + indexNextElem_ = NextIndex(indexNextElem_); + ++currentCountElem_; + return true; +} + +bool RingBuffer::Pop() { + if (Empty()) return false; + oldestElement_ = NextIndex(oldestElement_); + --currentCountElem_; + return true; +} + +bool RingBuffer::TryPop(int& value) { + if (Empty()) return false; + value = buffer_[oldestElement_]; + Pop(); + return true; +} + +int& RingBuffer::operator[](size_t index) { + ValidateIndex(index); + return buffer_[PhysicalIndex(index)]; +} + +const int& RingBuffer::operator[](size_t index) const { + ValidateIndex(index); + return buffer_[PhysicalIndex(index)]; +} + +int& RingBuffer::Front() { + ValidateNotEmpty(); + size_t frontIndex = indexNextElem_ ? indexNextElem_ - 1 : buffer_.capacity() - 1; + return buffer_[frontIndex]; +} + +const int& RingBuffer::Front() const { + ValidateNotEmpty(); + size_t frontIndex = indexNextElem_ ? indexNextElem_ - 1 : buffer_.capacity() - 1; + return buffer_[frontIndex]; +} + +int& RingBuffer::Back() { + ValidateNotEmpty(); + return buffer_[oldestElement_]; +} + +const int& RingBuffer::Back() const { + ValidateNotEmpty(); + return buffer_[oldestElement_]; +} + +bool RingBuffer::Empty() const { + return currentCountElem_ == 0; +} + +bool RingBuffer::Full() const { + return currentCountElem_ == buffer_.capacity(); +} + +size_t RingBuffer::Size() const { + return currentCountElem_; +} + +size_t RingBuffer::Capacity() const { + return buffer_.capacity(); +} + +void RingBuffer::Clear() { + oldestElement_ = indexNextElem_ = currentCountElem_ = 0; +} + +void RingBuffer::Resize(size_t newCapacity) { + newCapacity = newCapacity ? newCapacity : 1; + if (newCapacity == buffer_.capacity()) return; + + size_t newCount = currentCountElem_ < newCapacity ? currentCountElem_ : newCapacity; + std::vector newBuffer = {}; + newBuffer.reserve(newCapacity); + newBuffer.resize(newCapacity); + + for (size_t i = 0; i < newCount; ++i) { + newBuffer[i] = (*this)[currentCountElem_ - newCount + i]; + } + + buffer_ = std::move(newBuffer); + oldestElement_ = 0; + indexNextElem_ = newCount % newCapacity; + currentCountElem_ = newCount; +} + +std::vector RingBuffer::Vector() const { + std::vector result; + result.reserve(currentCountElem_); + for (size_t i = 0; i < currentCountElem_; ++i) result.push_back((*this)[i]); + return result; +} + +bool RingBuffer::operator==(const RingBuffer& other) const { + if (currentCountElem_ != other.currentCountElem_ || buffer_.capacity() != other.buffer_.capacity()) + return false; + for (size_t i = 0; i < currentCountElem_; ++i) + if ((*this)[i] != other[i]) return false; + return true; +} + +bool RingBuffer::operator!=(const RingBuffer& other) const { + return !(*this == other); +} \ No newline at end of file diff --git a/04_week/tasks/stack/stack.cpp b/04_week/tasks/stack/stack.cpp index 222e4ffc..7c69e514 100644 --- a/04_week/tasks/stack/stack.cpp +++ b/04_week/tasks/stack/stack.cpp @@ -1,6 +1,111 @@ #include +/* +Необходимо реализовать класс стек то есть обертку над вектором итнов +- Метод `Push` - добавляет элемент на верхушку стека +- Метод `Pop` - убирает элемент с верхушки стека +- Метод `Top` - обеспечивает доступ к элементу на верхушке стека +- Метод `Empty` - возвращает результат проверки стека на отсутствие элементов +- Метод `Size` - возвращает количество элементов в стеке +- Метод `Clear` - очищает стек +- Метод `Swap` - меняется элементами с другим стеком (без копирования) +- Оператор `==` - сравнение стека на равенство +- Оператор `!=` - сравнение стека на неравенство + +Вызов метода `Pop` от пустого стека является корректной операцией. Метод должен +возвращать `true` или `false` в зависимости от того выполнялась операция или нет. +//Значения стека должны находится в закрытой части класса +// Рекомендуется определять методы вне класса +//Некоторые методы могут потребовать перегрузки +//Обратите внимание, что при использовании в качестве полей контейнеров стандартной +//библиотеки нет необходимости писать собственные конструкторы + +//Перегрузка операторов +Синтаксис: ` operator(...);` + +- `` - символьное обозначение оператора (`+`, `<<`, `==`, ...) +- `...` - один или два аргумента (для унарного и бинарного операторов) +- `` - тип возвращаемого значения + +// Методы в классе это функции. +*/ +//реализации методов делаются с префиксом Stack:: class Stack { + public: + void Push(int value); + void Clear(); + void Swap(Stack& otherStack); + bool Pop(); + bool Empty() const; + int& Top(); // Для неконстантного стека + const int& Top() const; // Для константного стека + size_t Size() const; + + bool operator==(const Stack& otherStack) const; + bool operator!=(const Stack& otherStack) const; + + + private: + std::vector data; }; + +//push метод +void Stack::Push(int value) { + data.push_back(value); +} + +//CLear метод +void Stack::Clear() { + data.clear(); + +} + +//Swap метод +void Stack::Swap(Stack& otherStack) { + data.swap(otherStack.data); + +} + +//Pop метод +bool Stack::Pop() { + if (Empty()) return false; + + data.pop_back(); + return true; + +} + +//Top меттод +int& Stack::Top() { + static int throwMes = 0; + if(Empty()) return throwMes; + return data.back(); +} + +const int& Stack::Top() const { + static const int throwMes = 0; + if(Empty()) return throwMes; + + return data.back(); +} + +//Empty метод +bool Stack::Empty() const{ + return data.empty(); + +} + +size_t Stack::Size() const { + return data.size(); +} + +/////////////////////Перегрузка в 10G/////////////// +bool Stack::operator==(const Stack& otherStack) const { + return data == otherStack.data; +} + +bool Stack::operator!=(const Stack& otherStack) const { + return !(*this == otherStack); // используем == тк выше уже определили его +} \ No newline at end of file