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..e978c805 100644 --- a/01_week/tasks/addition/addition.cpp +++ b/01_week/tasks/addition/addition.cpp @@ -1,7 +1,5 @@ #include -#include - int64_t Addition(int a, int b) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + return static_cast(a) + b; +} diff --git a/01_week/tasks/char_changer/char_changer.cpp b/01_week/tasks/char_changer/char_changer.cpp index 3a7344d9..f16cfde6 100644 --- a/01_week/tasks/char_changer/char_changer.cpp +++ b/01_week/tasks/char_changer/char_changer.cpp @@ -1,7 +1,71 @@ +#include #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; + } + + array[convertedSymIdx++] = sequenceLen >= 10 ? '0' : 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..be3b33e7 100644 --- a/01_week/tasks/check_flags/check_flags.cpp +++ b/01_week/tasks/check_flags/check_flags.cpp @@ -1,6 +1,7 @@ #include -#include - +#include +#include +#include enum class CheckFlags : uint8_t { NONE = 0, @@ -13,6 +14,43 @@ enum class CheckFlags : uint8_t { ALL = TIME | DATE | USER | CERT | KEYS | DEST }; +namespace { + 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; + } + + if (flags == CheckFlags::NONE) { + std::cout << "[]"; + return; + } + + std::string needed_checks = "["; + + 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..8a305978 100644 --- a/01_week/tasks/quadratic/quadratic.cpp +++ b/01_week/tasks/quadratic/quadratic.cpp @@ -1,6 +1,61 @@ -#include +#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 == 0 && b == 0 && c == 0) { + std::cout << "infinite solutions"; + return; + } + + if (a == 0 && b == 0) { + std::cout << "no solutions"; + return; + } + + std::cout << std::setprecision(6); + + if (a == 0) { + std::cout << static_cast(-c) / b; + return; + } + + if (b == 0) { + 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 discriminant = static_cast(b) * b - 4.0 * a * c; + double root1 = 0.0, root2 = 0.0; + + if (discriminant == 0) { + std::cout << -b / (2.0 * a); + return; + } + + if (discriminant < 0) { + std::cout << "no solutions"; + return; + } + + root1 = ((-b - std::sqrt(discriminant)) / (2.0 * a)); + root2 = ((-b + std::sqrt(discriminant)) / (2.0 * a)); + + root1 > root2 ? std::cout << root2 << " " << root1 : + std:: cout << root1 << " " << root2; +} diff --git a/01_week/tasks/rms/rms.cpp b/01_week/tasks/rms/rms.cpp index 6882f0a9..9c1d69c7 100644 --- a/01_week/tasks/rms/rms.cpp +++ b/01_week/tasks/rms/rms.cpp @@ -1,7 +1,15 @@ -#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) { + 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..059cf696 100644 --- a/02_week/tasks/func_array/func_array.cpp +++ b/02_week/tasks/func_array/func_array.cpp @@ -1,6 +1,18 @@ -#include +#include +using operations_t = double(*)(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..9518214f 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,17 @@ -#include +typedef bool (*predicate_func_t)(int); +const int* FindLastElement(const int* begin, const int* end, predicate_func_t predicate) { + if (!begin || !end || begin >= end) { + return end; + } + + const int* result = end; + while (begin != end) { + if (predicate(*begin)) { + result = begin; + } + ++begin; + } -/* return_type */ FindLastElement(/* ptr_type */ begin, /* ptr_type */ end, /* func_type */ predicate) { - throw std::runtime_error{"Not implemented"}; -} \ No newline at end of file + 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..6479efd5 100644 --- a/02_week/tasks/longest/longest.cpp +++ b/02_week/tasks/longest/longest.cpp @@ -1,6 +1,37 @@ -#include +#include +const char* FindLongestSubsequence(const char* begin, const char* end, size_t& count) { + if (!begin || !end || begin >= end) { + count = 0; + return nullptr; + } -/* return_type */ FindLongestSubsequence(/* ptr_type */ begin, /* ptr_type */ end, /* type */ count) { - throw std::runtime_error{"Not implemented"}; + 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..38b89f9b 100644 --- a/02_week/tasks/pretty_array/pretty_array.cpp +++ b/02_week/tasks/pretty_array/pretty_array.cpp @@ -1,6 +1,36 @@ -#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 || !end) { + 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..368908d0 100644 --- a/02_week/tasks/swap_ptr/swap_ptr.cpp +++ b/02_week/tasks/swap_ptr/swap_ptr.cpp @@ -1,6 +1,20 @@ -#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..84b30479 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 &values) { + if (values.empty()) { + return {0.0, 0.0}; + } + + long sum = 0; + long sumSq = 0; + + for (auto val : values) { + sum += val; + sumSq += static_cast(val) * val; + } + + auto n = values.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..fe15cc0f 100644 --- a/03_week/tasks/enum_operators/enum_operators.cpp +++ b/03_week/tasks/enum_operators/enum_operators.cpp @@ -1,4 +1,5 @@ -#include +#include +#include #include enum class CheckFlags : uint8_t { @@ -12,22 +13,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..5f016922 100644 --- a/03_week/tasks/minmax/minmax.cpp +++ b/03_week/tasks/minmax/minmax.cpp @@ -1,6 +1,32 @@ -#include +#include +#include +#include +#include +using ItMin = std::vector::const_iterator; +using ItMax = std::vector::const_iterator; -/* return_type */ MinMax(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::pair MinMax(const std::vector& v) { + if (v.empty()) { + return {v.end(), v.end()}; + } + + auto minIt = v.begin(); + auto maxIt = v.end(); + int min = std::numeric_limits::max(); + int max = std::numeric_limits::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..8df947b5 100644 --- a/03_week/tasks/os_overload/os_overload.cpp +++ b/03_week/tasks/os_overload/os_overload.cpp @@ -1,21 +1,62 @@ -#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) { + return os << (r.second == true ? '+' : '-') << r.first; +} + +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 << "\n\t" << val; + + first = false; + } + + os << "\n}"; + + return os; } diff --git a/03_week/tasks/range/range.cpp b/03_week/tasks/range/range.cpp index d2085495..41814105 100644 --- a/03_week/tasks/range/range.cpp +++ b/03_week/tasks/range/range.cpp @@ -1,7 +1,25 @@ -#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) + || (step < 0 && from < to) + || (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..9a3f4b5d 100644 --- a/03_week/tasks/unique/unique.cpp +++ b/03_week/tasks/unique/unique.cpp @@ -1,6 +1,16 @@ -#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..f9fd823c 100644 --- a/04_week/tasks/phasor/phasor.cpp +++ b/04_week/tasks/phasor/phasor.cpp @@ -1,4 +1,33 @@ +#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.0 / 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 +35,224 @@ struct AlgTag {}; class Phasor { +public: + Phasor() = default; + Phasor(double magnitude, double rad) { + if (magnitude < 0) { + magnitude = -magnitude; + rad += M_PI; + } + + rad = NormalizePhase(rad); + + real_ = magnitude * std::cos(rad); + imag_ = magnitude * std::sin(rad); + }; + Phasor(double magnitude, double rad, ExpTag) : Phasor(magnitude, rad) {}; + Phasor(double magnitude, double deg, DegTag) : Phasor(magnitude, DegToRad(deg)) {}; + Phasor(double real, double imag, AlgTag) : real_(real), imag_(imag) {}; + + void SetPolar(double magnitude, 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 magnitude = lhs.Magnitude() * rhs.Magnitude(); + double rad = lhs.Phase() + rhs.Phase(); + + return Phasor(magnitude, NormalizePhase(rad)); +} + +Phasor operator/(const Phasor& lhs, const Phasor& rhs) { + double magnitude = lhs.Magnitude() / rhs.Magnitude(); + double rad = lhs.Phase() - rhs.Phase(); + + return Phasor(magnitude, 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 lhs, const Phasor& rhs) { + return rhs + lhs; +} + +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 lhs, const Phasor& rhs) { + return rhs * lhs; +} + +Phasor operator/(const Phasor& lhs, double rhs) { + return Phasor(lhs.Real() / rhs, lhs.Imag() / rhs, AlgTag{}); +} + +Phasor operator/(double lhs, const Phasor& rhs) { + double magnitude = std::abs(lhs) / rhs.Magnitude(); + double rad = ((lhs >= 0) ? 0.0 : M_PI) - rhs.Phase(); + return Phasor(magnitude, 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 magnitude, double rad) { + *this = Phasor(magnitude, 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 magnitude, double rad) { + return Phasor(magnitude, rad); +} + +Phasor MakePhasorPolarDeg(double magnitude, double deg) { + return Phasor(magnitude, deg, DegTag{}); +} diff --git a/04_week/tasks/queue/queue.cpp b/04_week/tasks/queue/queue.cpp index 2a9f8493..aba9160c 100644 --- a/04_week/tasks/queue/queue.cpp +++ b/04_week/tasks/queue/queue.cpp @@ -1,6 +1,165 @@ +#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(size_t size) { + inputV_.reserve(size); + outputV_.reserve(size); + }; + + // Queue(const int size) { + // inputV_.reserve(size); + // outputV_.reserve(size); + // }; + + 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; + } + + if (outputV_.size() == Size() && other.outputV_.size() == other.Size()) { + return outputV_ == other.outputV_; + } + + size_t idx = 0; + for (int i = outputV_.size() - 1; i >= 0; --i) { + if (outputV_[i] != other.GetElementAt(idx)) { + return false; + } + ++idx; + } + + for (size_t i = 0; i < inputV_.size(); ++i) { + if (inputV_[i] != other.GetElementAt(idx)) { + return false; + } + ++idx; + } + + return true; + } + + bool operator!=(const Queue& other) const { + return !(*this == other); + } + +private: + void CopyIfOutEmpty(); + int GetElementAt(size_t idx) const; + 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(); + } +} + +int Queue::GetElementAt(size_t idx) const { + if (idx < outputV_.size()) { + return outputV_[outputV_.size() - 1 - idx]; + } + + return inputV_[idx - outputV_.size()]; +} + +std::vector Queue::GetQueueAsVector() const { + std::vector result; + result.reserve(Size()); + + std::copy(outputV_.rbegin(), outputV_.rend(), std::back_inserter(result)); + std::copy(inputV_.begin(), inputV_.end(), std::back_inserter(result)); + + return result; +} + +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..4de57744 100644 --- a/04_week/tasks/ring_buffer/ring_buffer.cpp +++ b/04_week/tasks/ring_buffer/ring_buffer.cpp @@ -1,6 +1,187 @@ +#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, 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_.capacity()]; + } + const int& operator[](size_t idx) const { + return ringBuff_[(tail_ + idx) % ringBuff_.capacity()]; + } + +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) % cap; + } +} + +bool RingBuffer::TryPush(int val) { + size_t capacity = ringBuff_.capacity(); + + if (size_ == capacity) { + return false; + } + + ringBuff_[head_] = val; + // при head = buff.capacity(), head снова станет = 0 + head_ = (head_ + 1) % capacity; + + ++size_; + + return true; +} + +void RingBuffer::Pop() { + if (size_ > 0) { + tail_ = (tail_ + 1) % ringBuff_.capacity(); + --size_; + } +} + +bool RingBuffer::TryPop(int& val) { + if (size_ == 0) { + return false; + } + + val = ringBuff_[tail_]; + tail_ = (tail_ + 1) % ringBuff_.capacity(); + --size_; + return true; +} + +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 = 1; + } + + if (newSize == ringBuff_.capacity()) { + return; + } + + + std::vector tempV(newSize); + + size_t elemsToCopy = std::min(size_, newSize); + for (size_t i = 0; i < elemsToCopy; ++i) { + tempV[i] = ringBuff_[(tail_ + size_ - elemsToCopy + i) % ringBuff_.capacity()]; + } + + ringBuff_.swap(tempV); + + tail_ = 0; + head_ = elemsToCopy; + size_ = elemsToCopy; +} + +std::vector RingBuffer::Vector() const { + std::vector rb_as_vector; + size_t capacity = ringBuff_.capacity(); + rb_as_vector.reserve(capacity); + + for (size_t i = 0; i < size_; ++i) { + rb_as_vector.push_back(ringBuff_[(tail_ + i) % capacity]); + } + + return rb_as_vector; + } diff --git a/04_week/tasks/stack/stack.cpp b/04_week/tasks/stack/stack.cpp index 222e4ffc..94d0844a 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 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/05_week/tasks/cow_string/cow_string.cpp b/05_week/tasks/cow_string/cow_string.cpp index 34d59738..1c64b118 100644 --- a/05_week/tasks/cow_string/cow_string.cpp +++ b/05_week/tasks/cow_string/cow_string.cpp @@ -1,6 +1,282 @@ #include +#include #include +struct CowStringData { + char* data = nullptr; + size_t size = 0; + size_t refCount = 1; + + CowStringData() = default; + + CowStringData(const char* str) { + size = strlen(str); + data = new char[size + 1]; + std::strcpy(data, str); + refCount = 1; + } + + CowStringData(const std::string& str) { + size = str.size(); + data = new char[size + 1]; + std::strcpy(data, str.c_str()); + refCount = 1; + } + + ~CowStringData() { + delete[] data; + data = nullptr; + } +}; + class CowString { +public: + inline static size_t npos = std::numeric_limits::max(); + + CowString() : cowString_(new CowStringData) {} + + CowString(const char* str) : cowString_(new CowStringData(str)) {} + + CowString(const std::string& str) : cowString_(new CowStringData(str)) {} + + CowString(const CowString& other) : cowString_(other.cowString_){ + if (cowString_) { + ++cowString_->refCount; + } + } + + CowString(CowString&& other) : cowString_(other.cowString_) { + other.cowString_ = new CowStringData; + } + + ~CowString() { + DecreaseRefCount(); + } + + CowString& operator=(const CowString& other) { + if (this == &other) { + return *this; + } + + DecreaseRefCount(); + + cowString_ = other.cowString_; + if (cowString_) { + ++cowString_->refCount; + } + + return *this; + } + + CowString& operator=(CowString&& other) { + if (this == &other) { + return *this; + } + + DecreaseRefCount(); + cowString_ = other.cowString_; + other.cowString_ = new CowStringData; + + return *this; + } + + const char& operator[](size_t idx) const { + return cowString_->data[idx]; + } + + operator const char*() const { + return cowString_->data; + } + + char& operator[](size_t idx) { + if (cowString_->refCount > 1) { + MakeDeepCopy(); + } + + return cowString_->data[idx]; + } + + size_t Size() const; + bool Empty() const; + const char* ToCstr() const; + std::string ToString() const; + size_t Find(char symbol, size_t start) const; + size_t Find(const char* str, size_t start) const; + CowString& Append(const char* str); + CowString& Append(const std::string& str); + CowString Substr(size_t start, size_t len); + void Clear(); + +private: + CowStringData* cowString_ = nullptr; + + void DecreaseRefCount(); + void MakeDeepCopy(); }; + +void CowString::DecreaseRefCount() { + if (cowString_ && --cowString_->refCount == 0) { + delete cowString_; + } +} + +void CowString::MakeDeepCopy() { + CowStringData* deep_copy = new CowStringData(cowString_->data); + DecreaseRefCount(); + cowString_ = deep_copy; +} + +bool operator==(const CowString& lhs, const std::string& rhs) { + return std::strcmp(lhs.ToCstr(), rhs.c_str()) == 0; +} + +size_t CowString::Size() const { + return cowString_->size; +} + +bool CowString::Empty() const { + return cowString_->size == 0; +} + +const char* CowString::ToCstr() const { + return cowString_->data ? cowString_->data : ""; +} + +std::string CowString::ToString() const { + return cowString_->data ? std::string(cowString_->data, cowString_->size) + : ""; +} + +size_t CowString::Find(char symbol, size_t start = 0) const { + if (start > Size() || Empty()) { + return npos; + } + + const char* pos = std::strchr(cowString_->data + start, symbol); + + if (!pos) { + return npos; + } + + return pos - cowString_->data; +} + +size_t CowString::Find(const char* str, size_t start = 0) const { + if (start > Size() || std::strlen(str) > Size() || Empty()) { + return npos; + } + + const char* pos = std::strstr(cowString_->data + start, str); + + if (!pos) { + return npos; + } + + return pos - cowString_->data; +} + +CowString& CowString::Append(const char* str) { + if (!str || str[0] == '\0') { + return *this; + } + + if (!cowString_) { + cowString_ = new CowStringData(str); + return *this; + } + + if (cowString_->refCount > 1) { + MakeDeepCopy(); + } + + size_t newStrSize = std::strlen(str); + size_t newSize = cowString_->size + newStrSize; + char* newData = new char[newSize + 1]; + + size_t offset = 0; + + // memcpy чтобы не проверять на '\0' и избежать ошибки + // c strcat, когда data = nullptr + if (cowString_->data) { + std::memcpy(newData, cowString_->data, cowString_->size); + offset = cowString_->size; + } + std::memcpy(newData + offset, str, newStrSize + 1); + + delete[] cowString_->data; + cowString_->data = newData; + cowString_->size = newSize; + return *this; +} + +CowString& CowString::Append(const std::string& str) { + if (str.empty()) { + return *this; + } + + if (!cowString_) { + cowString_ = new CowStringData(str); + return *this; + } + + if (cowString_->refCount > 1) { + MakeDeepCopy(); + } + + size_t newSize = cowString_->size + str.size(); + char* newData = new char[newSize + 1]; + + if (cowString_->data) { + std::strcpy(newData, cowString_->data); + } + std::strcat(newData, str.c_str()); + + delete[] cowString_->data; + cowString_->data = newData; + cowString_->size = newSize; + return *this; +} + +CowString CowString::Substr(size_t start = 0, size_t len = npos) { + if (start == 0 && len == npos) { + return CowString(*this); + } + + if (start > cowString_->size || !cowString_->data) { + return CowString(); + } + + if (len > cowString_->size) { + len = cowString_->size; + } + + size_t substrSize = std::min(len, cowString_->size - start); + + char* subStr = new char[substrSize + 1]; + std::strncpy(subStr, cowString_->data + start, substrSize); + subStr[substrSize] = '\0'; + + CowString subCowStr; + delete[] subCowStr.cowString_->data; + subCowStr.cowString_->data = subStr; + subCowStr.cowString_->size = substrSize; + return subCowStr; +} + +void CowString::Clear() { + if (!cowString_) { + cowString_ = new CowStringData; + return; + } + + if (cowString_->refCount == 1) { + delete cowString_; + cowString_ = new CowStringData; + return; + } + + DecreaseRefCount(); + + cowString_ = new CowStringData; +} diff --git a/05_week/tasks/simple_vector/simple_vector.cpp b/05_week/tasks/simple_vector/simple_vector.cpp index 9b2ea971..8894635f 100644 --- a/05_week/tasks/simple_vector/simple_vector.cpp +++ b/05_week/tasks/simple_vector/simple_vector.cpp @@ -1,5 +1,290 @@ - +#include +#include +#include +#include class SimpleVector { +public: + SimpleVector() = default; + + SimpleVector(size_t size) : begin_(new int[size]{0}), end_(begin_ + size), capacity_(end_) {} + + SimpleVector(size_t size, int value) : begin_(new int[size]), end_(begin_ + size), capacity_(end_) { + std::fill(begin_, end_, value); + } + + SimpleVector(std::initializer_list list) : begin_(new int[list.size()]), + end_(std::copy(list.begin(), list.end(), begin_)), + capacity_(end_) {} + + SimpleVector(const SimpleVector& other) { + if (other.Empty()) { + begin_ = end_ = capacity_ = nullptr; + return; + } + + size_t capacity = other.Capacity(); + begin_ = new int[capacity]; + end_ = std::copy(other.begin_, other.end_, begin_); + capacity_ = begin_ + capacity; + } + + SimpleVector(SimpleVector&& other) : end_(other.end_), capacity_(other.capacity_) { + if (begin_) { + delete[] begin_; + } + + begin_ = other.begin_; + other.begin_ = nullptr; + other.end_ = nullptr; + other.capacity_ = nullptr; + } + + ~SimpleVector() { + delete [] begin_; + begin_ = end_ = capacity_ = nullptr; + } + + SimpleVector& operator=(const SimpleVector& other) { + if (&other == this) { + return *this; + } + + if (begin_) { + delete[] begin_; + } + + if (other.Empty()) { + begin_ = end_ = capacity_ = nullptr; + return *this; + } + + size_t capacity = other.Capacity(); + begin_ = new int[capacity]; + end_ = std::copy(other.begin_, other.end_, begin_); + capacity_ = begin_ + capacity; + return *this; + } + + SimpleVector& operator=(SimpleVector&& other) { + if (&other == this) { + return *this; + } + + if (begin_) { + delete[] begin_; + } + + begin_ = other.begin_; + end_ = other.end_; + capacity_ = other.capacity_; + other.begin_ = nullptr; + other.end_ = nullptr; + other.capacity_ = nullptr; + return *this; + } + + int& operator[](size_t idx) { + return begin_[idx]; + } + + const int& operator[](size_t idx) const { + return begin_[idx]; + } + + void Swap(SimpleVector& other); + size_t Size() const noexcept; + size_t Capacity() const noexcept; + bool Empty() const noexcept; + const int* Data() const; + const int* Begin() const; + const int* End() const; + void PushBack(int value); + void PopBack(); + int* Insert(size_t pos, int value); + int* Insert(const int* elem, int value); + int* Erase(size_t pos); + int* Erase(const int* value); + void Clear(); + void Resize(size_t size, int value); + void Reserve(size_t capacity); + +private: + int* begin_ = nullptr; + int* end_ = nullptr; + int* capacity_ = nullptr; + + void ChangeCapacity(size_t capacity, int value, bool init_with_value); +}; + +// Тут подошл бы обычный InreaseCapacity, который был бы проще, но меня переклинило +// и я вместо ТЗ смотрел на описание реализации std::vector, думая, что нужно делать +// shrink_to_fit +void SimpleVector::ChangeCapacity(size_t capacity, int value = 0, bool init_with_value = false) { + size_t size = std::min(Size(), capacity); + int* newSimpleVector = new int[capacity]; + + if (begin_) { + end_ = std::copy(begin_, begin_ + size, newSimpleVector); + delete[] begin_; + } + + begin_ = newSimpleVector; + end_ = begin_ + size; + capacity_ = begin_ + capacity; + + if (init_with_value && capacity > size) { + std::fill(end_, capacity_, value); + end_ = capacity_; + } +} + +bool operator==(const SimpleVector& lhs, const SimpleVector& rhs) { + if (lhs.Size() != rhs.Size()) { + return false; + } + + return std::equal(lhs.Begin(), lhs.End(), rhs.Begin()); +} + +bool operator!=(const SimpleVector& lhs, const SimpleVector& rhs) { + return !(lhs == rhs); +} + +void SimpleVector::Swap(SimpleVector& other) { + // Запрета на std::swap нет, используем >:) + std::swap(begin_, other.begin_); + std::swap(end_, other.end_); + std::swap(capacity_, other.capacity_); +} + +size_t SimpleVector::Size() const noexcept { + return end_ - begin_; +} + +size_t SimpleVector::Capacity() const noexcept { + return capacity_ - begin_; +} + +bool SimpleVector::Empty() const noexcept { + return end_ == begin_ ? true : false; +} + +const int* SimpleVector::Data() const { + return begin_; +} + +const int* SimpleVector::Begin() const { + return begin_; +} + +const int* SimpleVector::End() const { + return end_; +} + +void SimpleVector::PushBack(int value) { + if (end_ != capacity_) { + *end_ = value; + ++end_; + return; + } + + if (Empty()) { + ChangeCapacity(1, value, true); + return; + } + + ChangeCapacity(Capacity() * 2); + + *end_ = value; + ++end_; +} + +void SimpleVector::PopBack() { + if (end_ != begin_) { + --end_; + } +} + +int* SimpleVector::Insert(size_t pos, int value) { + if (pos > Size()) { + return end_; + } + + if (begin_ + pos == end_) { + PushBack(value); + return end_; + } + + if (end_ == capacity_) { + ChangeCapacity(Capacity() * 2); + } + + std::copy_backward(begin_ + pos, end_, end_ + 1); + begin_[pos] = value; + ++end_; + return begin_ + pos; +} + +int* SimpleVector::Insert(const int* elem, int value) { + if (!elem) { + return end_; + } + + return Insert(elem - begin_, value); +} + +int* SimpleVector::Erase(size_t pos) { + if (pos >= Size()) { + return end_; + } + + std::copy(begin_ + pos + 1, end_, begin_ + pos); + --end_; + return begin_ + pos; +} + +int* SimpleVector::Erase(const int* elem) { + if (!elem) { + return end_; + } + + return Erase(elem - begin_); +} + +void SimpleVector::Clear() { + end_ = begin_; +} + +void SimpleVector::Resize(size_t size, int value = 0) { + if (size == Size()) { + return; + } + + if (size < Size()) { + end_ = begin_ + size; + return; + } + + ChangeCapacity(size, value, true); +} + +void SimpleVector::Reserve(size_t capacity) { + if (capacity <= Capacity()) { + return; + } + + ChangeCapacity(capacity); +} + +auto begin(const SimpleVector& sVect) { + return sVect.Begin(); +} + +auto end(const SimpleVector& sVect) { + return sVect.End(); +} -}; \ No newline at end of file +void swap(SimpleVector& sVect1, SimpleVector& sVect2) { + sVect1.Swap(sVect2); +} diff --git a/05_week/tasks/string_view/string_view.cpp b/05_week/tasks/string_view/string_view.cpp index 438c4536..a65effbd 100644 --- a/05_week/tasks/string_view/string_view.cpp +++ b/05_week/tasks/string_view/string_view.cpp @@ -1,7 +1,164 @@ #include +#include #include - class StringView { +public: + inline static size_t npos = std::numeric_limits::max(); + + StringView() = default; + + StringView(const std::string& str, size_t start = 0, size_t len = npos) { + if (start > str.size() || str.empty()) { + return; + } + + if (len == npos || start + len > str.size()) { + len = str.size() - start; + } + + begin_ = str.data() + start; + end_ = begin_ + len; + }; + + StringView(const char* str) : begin_(str ? str : nullptr), end_(str ? str + std::strlen(str) : nullptr) {} + + StringView(const char* str, size_t len) { + if (!str) { + return; + } + + size_t strLen = std::strlen(str); + if (len > strLen) { + len = strLen; + } + + begin_ = str; + end_ = str + len; + } + + const char& operator[](size_t idx) const { + return begin_[idx]; + } + + const char* Data() const; + const char& Front() const; + const char& Back() const; + size_t Size() const; + size_t Length() const; + bool Empty() const; + int Compare(StringView& str) const; + void RemovePrefix(size_t len); + void RemoveSuffix(size_t len); + StringView Substr(size_t start, size_t len) const; + size_t Find(char symbol, size_t start) const; + size_t Find(const StringView& str, size_t start) const; + std::string ToString() const; + +private: + const char* begin_ = nullptr; + const char* end_ = nullptr; +}; + + +bool operator==(StringView& lhs, StringView& rhs) { + return std::strcmp(lhs.Data(), rhs.Data()) == 0; +} + +const char* StringView::Data() const { + return begin_; +} + +const char& StringView::Front() const { + return *begin_; +} + +const char& StringView::Back() const { + return *(end_ - 1); +} + +size_t StringView::Size() const { + return end_ - begin_; +} + +size_t StringView::Length() const { + return Size(); +} + +bool StringView::Empty() const { + if (begin_ == end_ || begin_ == nullptr) { + return true; + } + + return false; +} + +int StringView::Compare(StringView& str) const { + return std::strcmp(begin_, str.begin_); +} + +void StringView::RemovePrefix(size_t len) { + if (begin_ + len >= end_) { + begin_ = end_; + return; + } + + begin_ += len; +} + +void StringView::RemoveSuffix(size_t len) { + if (end_ - len <= begin_) { + end_ = begin_; + return; + } + + end_ -= len; +} + +StringView StringView::Substr(size_t start = 0, size_t len = 0) const { + if (start > Size() || Empty()) { + return StringView(); + } + + if (len == 0) { + return StringView(begin_ + start); + } + + return StringView(begin_ + start, len); +} + +size_t StringView::Find(char symbol, size_t start = 0) const { + if (start > Size() || Empty()) { + return npos; + } + + const char* pos = std::strchr(begin_ + start, symbol); + + if (!pos) { + return npos; + } + + return pos - begin_; +} + +size_t StringView::Find(const StringView& str, size_t start = 0) const { + if (str.Empty()) { + return 0; + } + + if (start > Size() || str.Size() > Size() || Empty()) { + return npos; + } + + const char* pos = std::strstr(begin_ + start, str.begin_); + + if (!pos) { + return npos; + } + + return pos - begin_; +} -}; \ No newline at end of file +std::string StringView::ToString() const { + return std::string(begin_, Size()); +} diff --git a/05_week/tasks/string_view/test.cpp b/05_week/tasks/string_view/test.cpp index 9a2d2875..631a56ab 100644 --- a/05_week/tasks/string_view/test.cpp +++ b/05_week/tasks/string_view/test.cpp @@ -346,4 +346,4 @@ TEST(StringViewTest, PerformanceCharacteristics) { std::string copy = sv.ToString(); EXPECT_EQ(copy.size(), 1000000); -} \ No newline at end of file +} diff --git a/05_week/tasks/tracer/tracer.cpp b/05_week/tasks/tracer/tracer.cpp index 2ccfb417..0e3869c0 100644 --- a/05_week/tasks/tracer/tracer.cpp +++ b/05_week/tasks/tracer/tracer.cpp @@ -1,6 +1,114 @@ #include - class Tracer { +public: + static size_t count; + static size_t default_ctor; + static size_t str_ctor; + static size_t copy_ctor; + static size_t move_ctor; + static size_t copy_assign; + static size_t move_assign; + static size_t dtor; + static size_t alive; + + Tracer() { + ++count; + ++default_ctor; + ++alive; + id_ = count; + name_ = "obj_" + std::to_string(id_); + } + + Tracer(const std::string& objName) { + ++count; + ++str_ctor; + ++alive; + id_ = count; + name_ = objName + '_' + std::to_string(id_); + } + + Tracer(const Tracer& other) { + ++count; + ++copy_ctor; + ++alive; + id_ = count; + name_ = other.name_; + } + + Tracer(Tracer&& other) noexcept { + ++count; + ++move_ctor; + ++alive; + id_ = count; + name_ = std::move(other.name_); + } + + Tracer& operator=(const Tracer& other) { + if (other.id_ == id_ ) { + return *this; + } + + ++copy_assign; + name_ = other.name_; + return *this; + } + + Tracer& operator=(Tracer&& other) noexcept { + if (other.id_ == id_) { + return *this; + } + + ++move_assign; + name_ = std::move(other.name_); + return *this; + } + + ~Tracer() { + ++dtor; + --alive; + } + + size_t Id(); + const std::string& Name() const; + const char* Data() const; + static void ResetStats(); + +private: + size_t id_; + std::string name_; +}; + +size_t Tracer::count = 0; +size_t Tracer::default_ctor = 0; +size_t Tracer::str_ctor = 0; +size_t Tracer::copy_ctor = 0; +size_t Tracer::move_ctor = 0; +size_t Tracer::copy_assign = 0; +size_t Tracer::move_assign = 0; +size_t Tracer::dtor = 0; +size_t Tracer::alive = 0; + +size_t Tracer::Id() { + return id_; +} + +const std::string& Tracer::Name() const { + return name_; +} + +const char* Tracer::Data() const { + return name_.data(); +} -}; \ No newline at end of file +void Tracer::ResetStats() { + count = 0; + default_ctor = 0; + str_ctor = 0; + copy_ctor = 0; + move_ctor = 0; + copy_assign = 0; + move_assign = 0; + dtor = 0; + alive = 0; +} 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)