diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..cec5a363 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/build +/build-asan diff --git a/01_week/tasks/addition/addition.cpp b/01_week/tasks/addition/addition.cpp index 92872802..cf0b78cf 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..bb92525d 100644 --- a/01_week/tasks/char_changer/char_changer.cpp +++ b/01_week/tasks/char_changer/char_changer.cpp @@ -1,7 +1,83 @@ #include #include +// Есть ощущение, что это можно решить как-то более лаконично и просто + +/** + * @brief Получить длину последовательности из одинаковых знаков. + * @param array указатель на элемент массива, с которого начнется проверка. + * @return Длина последовательности. + * @note Все символы будут сравниваться с первым из переданного массива. + */ +size_t GetIdenticalCharSequenceLen(char *array) { + size_t sequenceLen = 0; + + if (array[0] == '\0') { + return 0; + } + + while (array[0] == array[sequenceLen]) { + ++sequenceLen; + } + + return sequenceLen; +} + +/** + * @brief Сконвертировать одинаковые символы. + * @param array указатель на начало обрабатываемого массива. + * @param convertedSymIdx ссылка на индекс последнего сконвертированного символа. + * @param currentSymIdx ссылка на индекс текущего обрабатываемого символа. + * @param swapChar знак, на который будет произведена замена array[convertedSymIdx]. + * @return none + */ +void ConvertIdenticalCharacters(char array[], size_t& convertedSymIdx, size_t& currentSymIdx, char swapChar) { + size_t sequenceLen = GetIdenticalCharSequenceLen(&array[currentSymIdx]); + + array[convertedSymIdx++] = swapChar; + + if (sequenceLen == 1) { + currentSymIdx += sequenceLen; + return; + } + + if (sequenceLen >= 10) { + array[convertedSymIdx++] = '0'; + } else { + array[convertedSymIdx++] = sequenceLen + '0'; + } + + currentSymIdx += sequenceLen; +} size_t CharChanger(char array[], size_t size, char delimiter = ' ') { - throw std::runtime_error{"Not implemented"}; + size_t convertedSymbolIdx = 0, currentSymbolIdx = 0; + + while(currentSymbolIdx < size && convertedSymbolIdx < size) { + if (array[currentSymbolIdx] == '\0') { + break; + } + + if (isspace(array[currentSymbolIdx])) { + currentSymbolIdx += GetIdenticalCharSequenceLen(&array[currentSymbolIdx]); + + array[convertedSymbolIdx++] = delimiter; + continue; + } + + if (isalnum(array[currentSymbolIdx])) { + if (isdigit(array[currentSymbolIdx])) { + ConvertIdenticalCharacters(array, convertedSymbolIdx, currentSymbolIdx, '*'); + continue; + } + + ConvertIdenticalCharacters(array, convertedSymbolIdx, currentSymbolIdx, toupper(array[currentSymbolIdx])); + continue; + } + + ConvertIdenticalCharacters(array, convertedSymbolIdx, currentSymbolIdx, '_'); + } + + array[convertedSymbolIdx] = '\0'; + return convertedSymbolIdx; } diff --git a/01_week/tasks/check_flags/check_flags.cpp b/01_week/tasks/check_flags/check_flags.cpp index 75e7c652..a9a5f1f0 100644 --- a/01_week/tasks/check_flags/check_flags.cpp +++ b/01_week/tasks/check_flags/check_flags.cpp @@ -1,6 +1,6 @@ #include #include - +#include enum class CheckFlags : uint8_t { NONE = 0, @@ -13,6 +13,47 @@ enum class CheckFlags : uint8_t { ALL = TIME | DATE | USER | CERT | KEYS | DEST }; +// В данном случае можно было использовать map, но с ним придется использовать +// static_cast. Так же map отсортирует значения по возрасанию, соответственно +// использовать enum написанный иначе будет невозможно. +const std::vector> checkNames = { + {CheckFlags::TIME, "TIME"}, + {CheckFlags::DATE, "DATE"}, + {CheckFlags::USER, "USER"}, + {CheckFlags::CERT, "CERT"}, + {CheckFlags::KEYS, "KEYS"}, + {CheckFlags::DEST, "DEST"}, +}; + void PrintCheckFlags(CheckFlags flags) { - throw std::runtime_error{"Not implemented"}; + if (flags > CheckFlags::ALL) { + return; + } + + std::string needed_checks = "["; + + if (flags == CheckFlags::NONE) { + needed_checks += "]"; // Такая модификация происходит inplace, не + // создавая дорогостоящие копии + std::cout << needed_checks; + return; + } + + bool first = true; + for (const auto& [key, val] : checkNames) { + if (static_cast(flags) & static_cast(key)) { + if (!first) { + needed_checks += ","; // добавляем запятую перед элементом, а не после, + // проверяя на первый элемент, это гарантирует, что лишних + // запятых не будет + } + + needed_checks += val; + first = false; + } + } + + needed_checks += "]"; + + std::cout << needed_checks; } diff --git a/01_week/tasks/length_lit/length_lit.cpp b/01_week/tasks/length_lit/length_lit.cpp index e69de29b..a5bfb87c 100644 --- a/01_week/tasks/length_lit/length_lit.cpp +++ b/01_week/tasks/length_lit/length_lit.cpp @@ -0,0 +1,51 @@ +constexpr long double METER_IN_FOOT = 0.3048; +constexpr long double INCH_IN_FOOT = 12; +constexpr long double METER_IN_INCH = 0.0254; + +constexpr long double operator""_ft_to_m(long double foot) { + return foot * METER_IN_FOOT; +} + +constexpr long double operator""_m_to_ft(long double meter) { + return meter / METER_IN_FOOT; +} + +constexpr long double operator""_ft_to_cm(long double foot) { + return foot * METER_IN_FOOT * 100; +} + +constexpr long double operator""_cm_to_ft(long double cm) { + return cm / (METER_IN_FOOT * 100); +} + +constexpr long double operator""_ft_to_in(long double foot) { + return foot * INCH_IN_FOOT; +} + +constexpr long double operator""_in_to_ft(long double inch) { + return inch / INCH_IN_FOOT; +} + +constexpr long double operator""_in_to_m(long double inch) { + return inch * METER_IN_INCH; +} + +constexpr long double operator""_m_to_in(long double meter) { + return meter / METER_IN_INCH; +} + +constexpr long double operator""_in_to_cm(long double inch) { + return inch * METER_IN_INCH * 100; +} + +constexpr long double operator""_cm_to_in(long double inch) { + return inch / (METER_IN_INCH * 100); +} + +constexpr long double operator""_m_to_cm(long double meter) { + return meter * 100; +} + +constexpr long double operator""_cm_to_m(long double cm) { + return cm / 100; +} diff --git a/01_week/tasks/print_bits/print_bits.cpp b/01_week/tasks/print_bits/print_bits.cpp index a48a43c1..3db2d6ab 100644 --- a/01_week/tasks/print_bits/print_bits.cpp +++ b/01_week/tasks/print_bits/print_bits.cpp @@ -1,7 +1,17 @@ #include #include - +#include void PrintBits(long long value, size_t bytes) { - throw std::runtime_error{"Not implemented"}; + std::string byteForm = "0b"; + // i < bytes * 8 сработает, потому что 0ULL - 1 переполняется в ULL_MAX + for (size_t i = (bytes * 8 - 1); i < bytes * 8; --i) { + byteForm += ((value >> i) & 0x01U) + '0'; + + if (i != 0 && i % 4 == 0) { + byteForm += "'"; + } + } + + std::cout << byteForm << std::endl; } diff --git a/01_week/tasks/quadratic/quadratic.cpp b/01_week/tasks/quadratic/quadratic.cpp index abf7d632..9d3d58ba 100644 --- a/01_week/tasks/quadratic/quadratic.cpp +++ b/01_week/tasks/quadratic/quadratic.cpp @@ -1,6 +1,64 @@ #include +#include +#include +// Уверен, что это можно сделать значительно качественнее, но дедлайн близко, +// поэтому спагетти код >:) -void SolveQuadratic(int a, int b, int c) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file +void SolveQuadratic(int a, int b, int c) { + if (!a && !b && !c) { + std::cout << "infinite solutions"; + return; + } + + if (!a && !b) { + std::cout << "no solutions"; + return; + } + + std::cout << std::setprecision(6); + + if (!a) { + std::cout << (static_cast(-c) / b); + return; + } + + if (!b) { + if (static_cast(-c) / a < 0) { + std::cout << "no solutions"; + return; + } + + double root = std::sqrt(static_cast(-c) / a); + + if (root == 0) { + std::cout << root; + } else { + std::cout << -root << " " << root; + } + + return; + } + + double d = static_cast(b) * b - 4.0 * a * c; + double x1 = 0.0, x2 = 0.0; + + if (d < 0) { + std::cout << "no solutions"; + return; + } + + if (d > 0) { + x1 = ((-b - std::sqrt(d)) / (2.0 * a)); + x2 = ((-b + std::sqrt(d)) / (2.0 * a)); + + if (x1 > x2) { + std::cout << x2 << " " << x1; + } else { + std::cout << x1 << " " << x2; + } + return; + } + + std::cout << -b / (2.0 * a); +} diff --git a/01_week/tasks/rms/rms.cpp b/01_week/tasks/rms/rms.cpp index 6882f0a9..64cf032f 100644 --- a/01_week/tasks/rms/rms.cpp +++ b/01_week/tasks/rms/rms.cpp @@ -1,7 +1,16 @@ -#include +#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 || values == NULL) { + return 0.0; + } + + double sum = 0.0; + for (size_t i = 0; i < size; ++i) { + sum += values[i] * values[i]; + } + + return std::sqrt(sum / static_cast(size)); +} diff --git a/02_week/tasks/func_array/func_array.cpp b/02_week/tasks/func_array/func_array.cpp index b327e68d..68b25cef 100644 --- a/02_week/tasks/func_array/func_array.cpp +++ b/02_week/tasks/func_array/func_array.cpp @@ -1,6 +1,19 @@ #include +typedef double(*operations_t)(double, double); -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, operations_t mathOperations[], size_t size) { + if (size == 0 || mathOperations == nullptr) { + return 0.0; + } + + double sum = 0.0; + + for (size_t i = 0; i < size; ++i) { + if (mathOperations[i] != nullptr) { + sum += mathOperations[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 c7bf1a25..fa59bff9 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,26 @@ #include +typedef bool (*predicate_func_t)(int); -/* return_type */ FindLastElement(/* ptr_type */ begin, /* ptr_type */ end, /* func_type */ predicate) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file +const int* FindLastElement(const int* begin, const int* end, predicate_func_t predicate) { + if (begin == nullptr || end == nullptr) { + return end; + } + + if (begin >= end) { + return end; + } + + const int* result = end; + + // begin и end передаются by copy, так что инкремент указателя + // не повлияет на переданный указатель + while (begin != end) { + if (predicate(*begin)) { + result = begin; + } + ++begin; + } + + return result; +} diff --git a/02_week/tasks/little_big/little_big.cpp b/02_week/tasks/little_big/little_big.cpp index abe24379..2506fe16 100644 --- a/02_week/tasks/little_big/little_big.cpp +++ b/02_week/tasks/little_big/little_big.cpp @@ -1,10 +1,29 @@ -#include +#include +#include +template +void PrintMemory(T num, bool isReversed = false) { + std::string output = ""; -void PrintMemory(int /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; -} + // Надеюсь использование memcpy разрешено + unsigned char bytes[sizeof(T)]; + std::memcpy(bytes, &num, sizeof(T)); + + size_t start = isReversed ? (sizeof(T) - 1) : 0; + int step = isReversed ? -1 : 1; + + for (size_t i = start; i < sizeof(T); i += step) { + unsigned char currentByte = bytes[i]; + + for (int j = 4; j >= 0; j -= 4) { + int remainder = (currentByte >> j) & 0xf; + char hexChar = 0; -void PrintMemory(double /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + hexChar = remainder < 10 ? '0' + remainder : 'A' + (remainder - 10); + + output += hexChar; + } + } + output = "0x" + output; + std::cout << output << std::endl; +} diff --git a/02_week/tasks/longest/longest.cpp b/02_week/tasks/longest/longest.cpp index 04b3c354..12b87b36 100644 --- a/02_week/tasks/longest/longest.cpp +++ b/02_week/tasks/longest/longest.cpp @@ -1,6 +1,43 @@ #include -/* 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) { + count = 0; + return nullptr; + } + + if (begin >= end) { + count = 0; + return nullptr; + } + + size_t currSequenseLen = 0; + const char* longestSequenceStart = begin; + + while (begin != end) { + currSequenseLen++; + + if (*begin != *(begin + 1)) { + if (currSequenseLen > count) { + count = currSequenseLen; + longestSequenceStart = begin - (currSequenseLen - 1); + } + currSequenseLen = 0; + } + + ++begin; + } + + return longestSequenceStart; +} + +char* FindLongestSubsequence(char* begin, char* end, size_t& count) { + 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..15895d31 100644 --- a/02_week/tasks/pretty_array/pretty_array.cpp +++ b/02_week/tasks/pretty_array/pretty_array.cpp @@ -1,6 +1,37 @@ +#include #include +#include -void PrintArray(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file +void PrintArray(const int* begin, const int* end, int constrainer = 0) { + if (begin == nullptr || end == nullptr) { + std::cout << "[]" << std::endl; + return; + } + + std::string output = "["; + + size_t size = std::abs(begin - end); + + const int* arr = begin > end ? end + 1 : begin; + size_t startIndex = begin > end ? size - 1 : 0; + int step = begin > end ? -1 : 1; + size_t charCntr = 0; + + for (size_t i = startIndex; i < size; i += step) { + if (i != startIndex) { + output.append(", "); + if ((constrainer > 0) && (charCntr % constrainer == 0)) { + output.append("...\n "); + charCntr = 0; + } + } + + output.append(std::to_string(arr[i])); + charCntr++; + } + + output += "]"; + + std::cout << output << std::endl; +} diff --git a/02_week/tasks/swap_ptr/swap_ptr.cpp b/02_week/tasks/swap_ptr/swap_ptr.cpp index 93db625d..ffaf09dc 100644 --- a/02_week/tasks/swap_ptr/swap_ptr.cpp +++ b/02_week/tasks/swap_ptr/swap_ptr.cpp @@ -1,6 +1,21 @@ #include +template +void SwapPtr(T &ptr1, T &ptr2) { + T tmp = ptr1; + ptr1 = ptr2; + ptr2 = tmp; +} -void SwapPtr(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file +// Можно сделать перегрузкой, но мы же любим компактность :) +//void SwapPtr(const int* &ptr1, const int* &ptr2) { +// const int* tmp = ptr1; +// ptr1 = ptr2; +// ptr2 = tmp; +//} + +//void SwapPtr(int** &ptr1, int** &ptr2) { +// int** tmp = ptr1; +// ptr1 = ptr2; +// ptr2 = tmp; +//} diff --git a/03_week/tasks/data_stats/data_stats.cpp b/03_week/tasks/data_stats/data_stats.cpp index b941c211..3a29de14 100644 --- a/03_week/tasks/data_stats/data_stats.cpp +++ b/03_week/tasks/data_stats/data_stats.cpp @@ -1,11 +1,27 @@ -#include - +#include +#include struct DataStats { double avg = 0.0; double sd = 0.0; }; -/* return_type */ CalculateDataStats(/* args */) { - throw std::runtime_error{"Not implemented"}; +struct DataStats CalculateDataStats(const std::vector &v) { + if (v.empty()) { + return {0.0, 0.0}; + } + + long sum = 0; + long sumSq = 0; + + for (auto val : v) { + sum += val; + sumSq += static_cast(val) * val; + } + + auto n = v.size(); + double avg = static_cast(sum) / n; + double variance = (sumSq - (static_cast(sum) * sum) / n) / n; + + return { avg, std::sqrt(variance) }; } diff --git a/03_week/tasks/easy_compare/easy_compare.cpp b/03_week/tasks/easy_compare/easy_compare.cpp index dd5cb7f6..7436856d 100644 --- a/03_week/tasks/easy_compare/easy_compare.cpp +++ b/03_week/tasks/easy_compare/easy_compare.cpp @@ -1,10 +1,38 @@ #include - +#include struct Date { - unsigned year; - unsigned month; - unsigned day; + unsigned year = 0; + unsigned month = 0; + unsigned day = 0; + + bool operator==(const Date& other) const { + return std::tie(year, month, day) == std::tie(other.year, other.month, other.day); + } + + bool operator!=(const Date& other) const { + return !(*this == other); + } + + bool operator<(const Date& other) const { + return std::tie(year, month, day) < std::tie(other.year, other.month, other.day); + } + + bool operator>(const Date& other) const { + if (*this == other) { + return false; + } + + return !(*this < other); + } + + bool operator<=(const Date& other) { + return !(*this > other); + } + + bool operator>=(const Date& other) { + return !(*this < other); + } }; struct StudentInfo { @@ -13,4 +41,19 @@ struct StudentInfo { int score; unsigned course; Date birth_date; -}; \ No newline at end of file + + bool operator==(const StudentInfo& other) const { + return mark == other.mark && score == other.score; + } + + bool operator!=(const StudentInfo& other) const { + return !(*this == other); + } + + bool operator<(const StudentInfo& other) const { + // обратный знак, так как A < Z в таблице символов + return std::tie(other.mark, score, other.course, birth_date) < std::tie(mark, other.score, course, other.birth_date); + } +}; + + diff --git a/03_week/tasks/enum_operators/enum_operators.cpp b/03_week/tasks/enum_operators/enum_operators.cpp index a539be38..61599cfc 100644 --- a/03_week/tasks/enum_operators/enum_operators.cpp +++ b/03_week/tasks/enum_operators/enum_operators.cpp @@ -1,4 +1,10 @@ -#include +#include +#include +#include +#include +#include +#include +#include #include enum class CheckFlags : uint8_t { @@ -12,22 +18,77 @@ enum class CheckFlags : uint8_t { ALL = TIME | DATE | USER | CERT | KEYS | DEST }; -/* return_type */ operator|(/* args */) { - throw std::runtime_error{"Not implemented"}; +const std::vector> checkNames = { + {CheckFlags::TIME, "TIME"}, + {CheckFlags::DATE, "DATE"}, + {CheckFlags::USER, "USER"}, + {CheckFlags::CERT, "CERT"}, + {CheckFlags::KEYS, "KEYS"}, + {CheckFlags::DEST, "DEST"}, +}; + +std::underlying_type_t getVal(CheckFlags f) { + return static_cast>(f) & + static_cast>(CheckFlags::ALL); +} + +bool operator!(const CheckFlags f) { + return getVal(f) == 0; +} + +bool operator==(CheckFlags lhs, CheckFlags rhs) { + return getVal(lhs) == getVal(rhs); +} + +bool operator!=(CheckFlags lhs, CheckFlags rhs) { + return !(lhs == rhs); } -/* return_type */ operator&(/* args */) { - throw std::runtime_error{"Not implemented"}; +CheckFlags operator|(CheckFlags lhs, CheckFlags rhs) { + return static_cast((getVal(lhs) | getVal(rhs)) & getVal(CheckFlags::ALL)); } -/* return_type */ operator^(/* args */) { - throw std::runtime_error{"Not implemented"}; +bool operator&(CheckFlags lhs, CheckFlags rhs) { + auto lhsVal = getVal(lhs); + auto rhsVal = getVal(rhs); + + if (lhsVal == 0 || rhsVal == 0) { + return false; + } + + return ((lhsVal & rhsVal) == lhsVal) || ((lhsVal & rhsVal) == rhsVal); +} + +CheckFlags operator^(CheckFlags lhs, CheckFlags rhs) { + return static_cast((getVal(lhs) ^ getVal(rhs)) & getVal(CheckFlags::ALL)); } -/* return_type */ operator~(/* args */) { - throw std::runtime_error{"Not implemented"}; +CheckFlags operator~(const CheckFlags& f) { + return static_cast((~getVal(f)) & getVal(CheckFlags::ALL)); } -/* return_type */ operator<<(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::ostream& operator<<(std::ostream& os, const CheckFlags& f) { + std::string needed_checks = ""; + + auto fVal = getVal(f); + + if (f == CheckFlags::NONE) { + os << "NONE"; + return os; + } + + bool first = true; + for (const auto& [key, val] : checkNames) { + if (fVal & getVal(key)) { + if (!first) { + needed_checks += ", "; + } + + needed_checks += val; + first = false; + } + } + + os << needed_checks; + return os; } diff --git a/03_week/tasks/filter/filter.cpp b/03_week/tasks/filter/filter.cpp index 6648cb39..64cc2779 100644 --- a/03_week/tasks/filter/filter.cpp +++ b/03_week/tasks/filter/filter.cpp @@ -1,6 +1,23 @@ -#include +#include +typedef bool (*Predicate)(int); -/* return_type */ Filter(/* args */) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file +void Filter(std::vector &v, Predicate predicateFunc) { + if (v.empty() || predicateFunc == nullptr) { + return; + } + + auto secondIt = v.begin(); + size_t newSize = 0; + for (auto it = v.begin(); it != v.end(); ++it) { + if (predicateFunc(*it)) { + if (it != secondIt) { + *secondIt = *it; + } + ++secondIt; + ++newSize; + } + } + + v.resize(newSize); +} diff --git a/03_week/tasks/find_all/find_all.cpp b/03_week/tasks/find_all/find_all.cpp index 74f393b2..252f2b15 100644 --- a/03_week/tasks/find_all/find_all.cpp +++ b/03_week/tasks/find_all/find_all.cpp @@ -1,6 +1,22 @@ #include +typedef bool (*Predicate)(int); -/* return_type */ FindAll(/* args */) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file +std::vector FindAll(const std::vector &v, Predicate predicate_func) { + if (v.empty() || predicate_func == nullptr) { + return {}; + } + + std::vector output; + output.reserve(v.size()); + + for (size_t i = 0; i < v.size(); ++i) { + if (predicate_func(v[i])) { + output.push_back(i); + } + } + + output.shrink_to_fit(); + + return output; +} diff --git a/03_week/tasks/minmax/minmax.cpp b/03_week/tasks/minmax/minmax.cpp index c2869799..c7ddcbce 100644 --- a/03_week/tasks/minmax/minmax.cpp +++ b/03_week/tasks/minmax/minmax.cpp @@ -1,6 +1,28 @@ -#include +#include +#include +#include +std::pair::const_iterator, std::vector::const_iterator> MinMax(const std::vector& v) { + if (v.empty()) { + return {v.end(), v.end()}; + } -/* return_type */ MinMax(/* args */) { - throw std::runtime_error{"Not implemented"}; + auto minIt = v.begin(); + auto maxIt = v.end(); + int min = INT_MAX; + int max = INT_MIN; + + for (auto it = v.begin(); it != v.end(); ++it) { + if (*it < min) { + min = *it; + minIt = it; + } + + if (*it >= max) { + max = *it; + maxIt = it; + } + } + + return {minIt, maxIt}; } diff --git a/03_week/tasks/os_overload/os_overload.cpp b/03_week/tasks/os_overload/os_overload.cpp index e473418d..b62c77e6 100644 --- a/03_week/tasks/os_overload/os_overload.cpp +++ b/03_week/tasks/os_overload/os_overload.cpp @@ -1,21 +1,73 @@ -#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; }; 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& c) { + + if (c.radius == 0) { + os << "circle[]"; + return os; + } + + os << "circle[" << c.coord << ", " << "r = " << c.radius << ']'; + + return os; +} + +std::ostream& operator<<(std::ostream& os, const CircleRegion& r) { + if (r.second == true) { + os << '+'; + } else { + os << '-'; + } + + os << r.first; + + return os; +} + +std::ostream& operator<<(std::ostream& os, const CircleRegionList& lst) { + if (lst.empty()) { + os << "{}"; + return os; + } + + os << "{"; + + bool first = true; + + for (auto val : lst) { + if (!first) { + os << ','; + } + + os << std::endl << '\t' << val; + + first = false; + } + + os << std::endl <<"}"; + + return os; } diff --git a/03_week/tasks/range/range.cpp b/03_week/tasks/range/range.cpp index d2085495..fe27b102 100644 --- a/03_week/tasks/range/range.cpp +++ b/03_week/tasks/range/range.cpp @@ -1,7 +1,33 @@ -#include +#include +#include +#include #include -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) { + std::vector range{}; + + if (step == 0) { + return range; + } + + if (step < 0 && from < to) { + return range; + } + + if (step > 0 && from > to) { + return range; + } + + auto absDiff = std::abs(from - to); + + range.reserve(std::ceil(std::abs(absDiff / static_cast(step)))); + + int val = from; + for (size_t i = 0; i < range.capacity(); ++i) { + range.push_back(val); + val += step; + } + + return range; } diff --git a/03_week/tasks/unique/unique.cpp b/03_week/tasks/unique/unique.cpp index 9d2545bb..bec3950b 100644 --- a/03_week/tasks/unique/unique.cpp +++ b/03_week/tasks/unique/unique.cpp @@ -1,6 +1,18 @@ -#include #include -/* return_type */ Unique(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::vector Unique(const std::vector& v) { + std::vector uniqueElem{}; + + uniqueElem.reserve(v.size()); + + + for (auto val : v) { + if (uniqueElem.empty() || (uniqueElem.back() != val)) { + uniqueElem.push_back(val); + } + } + + uniqueElem.shrink_to_fit(); + + return uniqueElem; } diff --git a/04_week/CMakeLists.txt b/04_week/CMakeLists.txt index b15ca37c..ff9cd88d 100644 --- a/04_week/CMakeLists.txt +++ b/04_week/CMakeLists.txt @@ -12,4 +12,4 @@ add_subdirectory(tasks) # Создать исполняемый файл для каждого примера if (BUILD_EXAMPLES_04_WEEK) # add_example(class_examples ${EXAMPLES_DIR}/class_examples.cpp) -endif() \ No newline at end of file +endif() diff --git a/04_week/tasks/phasor/phasor.cpp b/04_week/tasks/phasor/phasor.cpp index 3ec1b9ad..3d5874fd 100644 --- a/04_week/tasks/phasor/phasor.cpp +++ b/04_week/tasks/phasor/phasor.cpp @@ -1,4 +1,34 @@ +#include +#include +#include +#include +namespace { + constexpr double EPS_ = 1e-12; +} + + +double DegToRad(double deg) { + return deg * M_PI / 180.0; +} + +double RadToDeg(double rad){ + return rad * 180 / M_PI; +} + +double NormalizePhase(double phase) { + phase = std::fmod(phase, 2.0 * M_PI); + + if (phase > M_PI) { + phase -= 2.0 * M_PI; + } + + if (phase <= -M_PI) { + phase += 2.0 * M_PI; + } + + return phase; +} struct ExpTag {}; struct DegTag {}; @@ -6,5 +36,225 @@ struct AlgTag {}; class Phasor { +public: + Phasor() = default; + Phasor(double A, double rad) { + if (A < 0) { + A = -A; + rad += M_PI; + } + + rad = NormalizePhase(rad); + + real_ = A * std::cos(rad); + imag_ = A * std::sin(rad); + }; + Phasor(double A, double rad, ExpTag) : Phasor(A, rad) {}; + Phasor(double A, double deg, DegTag) : Phasor(A, DegToRad(deg)) {}; + Phasor(double real, double imag, AlgTag) : real_(real), imag_(imag) {}; + + void SetPolar(double A, double 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; + double Angle() const; + double AngleDeg() const; + Phasor Conj() const; + Phasor Inv() const; + + Phasor& operator+=(const Phasor& other) { + real_ += other.real_; + imag_ += other.imag_; + return *this; + } + + Phasor& operator-=(const Phasor& other) { + real_ -= other.real_; + imag_ -= other.imag_; + return *this; + } + Phasor& operator*=(const Phasor& other) { + SetPolar(Magnitude() * other.Magnitude(), Phase() + other.Phase()); + return *this; + } + + Phasor& operator/=(const Phasor& other) { + SetPolar(Magnitude() / other.Magnitude(), Phase() - other.Phase()); + return *this; + } + + Phasor& operator+=(double real) { + real_ += real; + return *this; + } + + Phasor& operator-=(double real) { + real_ -= real; + return *this; + } + + Phasor& operator*=(double real) { + real_ *= real; + imag_ *= real; + return *this; + } + + Phasor& operator/=(double real) { + real_ /= real; + imag_ /= real; + return *this; + } + + Phasor operator-() const { + return Phasor(-real_, -imag_, AlgTag{}); + } + +private: + double real_ = 0.0; + double imag_ = 0.0; }; + +Phasor operator+(const Phasor& lhs, const Phasor& rhs) { + double real = lhs.Real() + rhs.Real(); + double imag = lhs.Imag() + rhs.Imag(); + return Phasor(real, imag, AlgTag{}); +} + +Phasor operator-(const Phasor& lhs, const Phasor& rhs) { + double real = lhs.Real() - rhs.Real(); + double imag = lhs.Imag() - rhs.Imag(); + return Phasor(real, imag, AlgTag{}); +} + +Phasor operator*(const Phasor& lhs, const Phasor& rhs) { + double A = lhs.Magnitude() * rhs.Magnitude(); + double rad = lhs.Phase() + rhs.Phase(); + + return Phasor(A, NormalizePhase(rad)); +} + +Phasor operator/(const Phasor& lhs, const Phasor& rhs) { + double A = lhs.Magnitude() / rhs.Magnitude(); + double rad = lhs.Phase() - rhs.Phase(); + + return Phasor(A, NormalizePhase(rad)); +} + +bool operator==(const Phasor& lhs, const Phasor& rhs) { + 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); +} + +Phasor operator+(const Phasor& lhs, double rhs) { + return Phasor(lhs.Real() + rhs, lhs.Imag(), AlgTag{}); +} + +// Сложение коммутативно +Phasor operator+(double rhs, const Phasor& lhs) { + return Phasor(lhs.Real() + rhs, lhs.Imag(), AlgTag{}); +} + +Phasor operator-(const Phasor& lhs, double rhs) { + return Phasor(lhs.Real() - rhs, lhs.Imag(), AlgTag{}); +} + +Phasor operator-(double lhs, const Phasor& rhs) { + return (lhs + (-rhs)); +} + + +Phasor operator*(const Phasor& lhs, double rhs) { + return Phasor(lhs.Real() * rhs, lhs.Imag() * rhs, AlgTag{}); +} + +// Умножение тоже коммутативно +Phasor operator*(double rhs, const Phasor& lhs) { + return Phasor(lhs.Real() * rhs, lhs.Imag() * rhs, AlgTag{}); +} + +Phasor operator/(const Phasor& lhs, double rhs) { + return Phasor(lhs.Real() / rhs, lhs.Imag() / rhs, AlgTag{}); +} + +Phasor operator/(double lhs, const Phasor& rhs) { + double A = std::abs(lhs) / rhs.Magnitude(); + double rad = ((lhs >= 0) ? 0.0 : M_PI) - rhs.Phase(); + return Phasor(A, NormalizePhase(rad)); +} + +std::ostream& operator<<(std::ostream& os, const Phasor& p) { + os << std::fixed << std::setprecision(3) + << p.Magnitude() << "*e(j*" << p.PhaseDeg() << ") [" + << p.Real() << " + j*" << p.Imag() << ']'; + return os; +} + +void Phasor::SetPolar(double A, double rad) { + *this = Phasor(A, rad); +} + +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 RadToDeg(Phase()); +} + +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 { + return 1.0 / (*this); +} + +Phasor MakePhasorCartesian(double real, double imag) { + return Phasor(real, imag, AlgTag{}); +} + +Phasor MakePhasorPolar(double A, double rad) { + return Phasor(A, rad); +} + +Phasor MakePhasorPolarDeg(double A, double deg) { + return Phasor(A, deg, DegTag{}); +} diff --git a/04_week/tasks/queue/queue.cpp b/04_week/tasks/queue/queue.cpp index 2a9f8493..77bdac17 100644 --- a/04_week/tasks/queue/queue.cpp +++ b/04_week/tasks/queue/queue.cpp @@ -1,6 +1,139 @@ +#include +#include #include - class Queue { +public: + Queue() {}; + + Queue(std::stack s) { + outputV_.reserve(s.size()); + while(!s.empty()) { + outputV_.push_back(s.top()); + s.pop(); + } + }; + + Queue(std::vector v) : outputV_(v.rbegin(), v.rend()){}; + + Queue(std::initializer_list list) : inputV_(list) {}; + + Queue(const size_t size) { + inputV_.reserve(size); + outputV_.reserve(size); + }; + + Queue(const int size) { + inputV_.reserve(size); + outputV_.reserve(size); + }; + + inline void Push(int val); + 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 { + if (Size() != other.Size()) { + return false; + } + + return this->GetQueueAsVector() == other.GetQueueAsVector(); + } + bool operator!=(const Queue& other) const { + return !(*this == other); + } + +private: + void CopyIfOutEmpty(); + std::vector GetQueueAsVector() const; + std::vector inputV_{}; + std::vector outputV_{}; }; + +void Queue::CopyIfOutEmpty() { + if (outputV_.empty()) { + outputV_ = std::vector(inputV_.rbegin(), inputV_.rend()); + inputV_.clear(); + } +} + +std::vector Queue::GetQueueAsVector() const { + std::vector result; + + std::copy(outputV_.rbegin(), outputV_.rend(), std::back_inserter(result)); + + std::copy(inputV_.begin(), inputV_.end(), std::back_inserter(result)); + + return result; +} + +inline void Queue::Push(int val) { + inputV_.push_back(val); +} + +bool Queue::Pop() { + if (outputV_.empty() && inputV_.empty()) { + return false; + } + + CopyIfOutEmpty(); + + outputV_.pop_back(); + + return true; +} + +int& Queue::Front() { + CopyIfOutEmpty(); + return outputV_.back(); +} + +const int& Queue::Front() const { + if (outputV_.empty()) { + return inputV_.front(); + } + + return outputV_.back(); +} + +int& Queue::Back() { + if (!inputV_.empty()) { + return inputV_.back(); + } + + return outputV_.front(); +} + +const int& Queue::Back() const { + if (!inputV_.empty()) { + return inputV_.back(); + } + + return outputV_.front(); +} + +bool Queue::Empty() const { + return (inputV_.empty() && outputV_.empty()); +} + +size_t Queue::Size() const { + return (inputV_.size() + outputV_.size()); +} + +void Queue::Clear() { + inputV_.clear(); + outputV_.clear(); +} + +void Queue::Swap(Queue& other) { + inputV_.swap(other.inputV_); + outputV_.swap(other.outputV_); +} diff --git a/04_week/tasks/ring_buffer/ring_buffer.cpp b/04_week/tasks/ring_buffer/ring_buffer.cpp index e2b57ba2..6e798755 100644 --- a/04_week/tasks/ring_buffer/ring_buffer.cpp +++ b/04_week/tasks/ring_buffer/ring_buffer.cpp @@ -1,6 +1,189 @@ +#include +#include #include - class RingBuffer { +public: + RingBuffer() : ringBuff_(1), head_(0), tail_(0), size_(0) {} + + RingBuffer(size_t capacity) : ringBuff_(capacity > 0 ? capacity : 1), head_(0), tail_(0), size_(0) {} + + RingBuffer(size_t capacity, const int iVal) : ringBuff_(capacity > 0 ? capacity : 1, iVal), head_(capacity), tail_(0), + size_(capacity > 0 ? capacity : 1) {} + + RingBuffer(std::initializer_list list) : ringBuff_(list), head_(0), tail_(0), size_(list.size()) { + if (list.size() == 0) { + ringBuff_.reserve(1); + size_ = 0; + } + } + + void Push(int val); + bool TryPush(int val); + void Pop(); + bool TryPop(int& val); + 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 newSize); + std::vector Vector() const; + + int& operator[](size_t idx) { + return ringBuff_[(tail_ + idx) % ringBuff_.size()]; + } + const int& operator[](size_t idx) const { + return ringBuff_[(tail_ + idx) % ringBuff_.size()]; + } + +private: + std::vector ringBuff_{}; + size_t head_ = 0; + size_t tail_ = 0; + size_t size_ = 0; }; + +void RingBuffer::Push(int val) { + size_t cap = ringBuff_.capacity(); + + ringBuff_[head_] = val; + // при head = buff.capacity(), head снова станет = 0 + head_ = (head_ + 1) % cap; + + if (size_ < cap) { + ++size_; + } else { + // аналогично head + tail_ = (tail_ + 1) % ringBuff_.capacity(); + } +} + +bool RingBuffer::TryPush(int val) { + size_t cap = ringBuff_.capacity(); + + if (size_ == cap) { + return false; + } + + ringBuff_[head_] = val; + // при head = buff.capacity(), head снова станет = 0 + head_ = (head_ + 1) % cap; + + ++size_; + + return true; +} + +void RingBuffer::Pop() { + if (size_ > 0) { + tail_ = (tail_ + 1) % ringBuff_.capacity(); + --size_; + } +} + +bool RingBuffer::TryPop(int& val) { + if (size_ > 0) { + val = ringBuff_[tail_]; + tail_ = (tail_ + 1) % ringBuff_.capacity(); + --size_; + return true; + } + + return false; +} + +int& RingBuffer::Front() { + if (head_ == 0) { + return ringBuff_.back(); + } + + return ringBuff_[head_ - 1]; +} + +const int& RingBuffer::Front() const { + if (head_ == 0) { + return ringBuff_.back(); + } + + return ringBuff_[head_ - 1]; +} + +int& RingBuffer::Back() { + return ringBuff_[tail_]; +} + +const int& RingBuffer::Back() const { + return ringBuff_[tail_]; +} + +bool RingBuffer::Empty() const { + return size_ == 0; +} + + +bool RingBuffer::Full() const { + return size_ == ringBuff_.capacity(); +} + +size_t RingBuffer::Size() const { + return size_; +} + +size_t RingBuffer::Capacity() const { + return ringBuff_.capacity(); +} + +void RingBuffer::Clear() { + head_ = 0; + tail_ = 0; + size_ = 0; +} + +void RingBuffer::Resize(size_t newSize) { + if (newSize == 0) { + ++newSize; + } + + if (newSize == ringBuff_.size()) { + return; + } + + size_t sz = std::min(size_, newSize); + + std::vector tempV; + tempV.reserve(sz); + + for (size_t i = 0; i < sz; ++i) { + tempV.push_back(ringBuff_[(head_ - 1 - i + ringBuff_.size()) % ringBuff_.size()]); + } + + std::reverse(tempV.begin(), tempV.end()); + ringBuff_.resize(newSize); + + for (size_t i = 0; i < sz; ++i) { + ringBuff_[i] = tempV[i]; + } + + ringBuff_.shrink_to_fit(); + + tail_ = 0; + head_ = sz; + size_ = sz; +} + +std::vector RingBuffer::Vector() const { + std::vector v; + v.reserve(size_); + + for (size_t i = 0; i < size_; ++i) { + v.push_back(ringBuff_[(tail_ + i) % ringBuff_.size()]); + } + + return v; + } diff --git a/04_week/tasks/stack/stack.cpp b/04_week/tasks/stack/stack.cpp index 222e4ffc..5f9241ed 100644 --- a/04_week/tasks/stack/stack.cpp +++ b/04_week/tasks/stack/stack.cpp @@ -1,6 +1,62 @@ +#include #include - class Stack { +public: + void Push(int val); + 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 { + return this->stack_ == other.stack_; + } + bool operator!=(const Stack& other) const { + return !(*this == other); + } + +private: + std::vector stack_{}; }; + +void Stack::Push(int val) { + stack_.push_back(val); +} + +bool Stack::Pop() { + if (stack_.empty()) { + return false; + } + + stack_.pop_back(); + return true; +} + +int& Stack::Top() { + return stack_.back(); +} + +const int& Stack::Top() const { + return stack_.back(); +} + +bool Stack::Empty() const { + return stack_.empty(); +} + +size_t Stack::Size() const { + return stack_.size(); +} + +void Stack::Clear() { + stack_.clear(); +} + +void Stack::Swap(Stack& other) { + stack_.swap(other.stack_); +} diff --git a/CMakeLists.txt b/CMakeLists.txt index b64ab3cd..fc3d5fa2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,4 +33,4 @@ add_week(06_week) add_week(07_week) add_week(08_week) add_week(09_week) -add_week(10_week) \ No newline at end of file +add_week(10_week)