diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..1de6d7b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,83 @@ +# .gitignore для psds-cpp-2025 (C++ проект) + +# Каталоги сборки и артефакты +/build/ +/cmake-build-*/ +/out/ +/bin/ +/obj/ +/dist/ + +# CMake, Make и тесты +CMakeFiles/ +CMakeCache.txt +cmake_install.cmake +CTestTestfile.cmake +Makefile + +# Скомпилированные файлы и библиотеки +*.o +*.obj +*.so +*.a +*.lib +*.dll +*.exe +*.out +*.elf +*.app + +# Отладочные файлы и логи +*.pdb +*.ilk +*.log + +# Профилирование / покрытие +*.gcda +*.gcno +coverage.* +lcov-report/ + +# Автогенерированные файлы инструментов +compile_commands.json +conanbuildinfo.* +.conan/ + +# IDE / редакторы +.vscode/ +.idea/ +*.iml +*.ipr +*.iws +*.sublime-* +*.code-workspace + +# Системные файлы +.DS_Store +Thumbs.db + +# Временные файлы редакторов +*~ +*.swp +*.swo +*.tmp +.#* + +# Архивы и артефакты релизов +*.tar.gz +*.zip + +# Документация +docs/_build/ +doc/html/ + +# Прочее +.tags +.ccls-cache/ +*.lock + +# Индексные файлы (.idx) +*.idx +*.IDX +*.idx~ +*.idx.bak \ No newline at end of file diff --git a/01_week/tasks/addition/addition.cpp b/01_week/tasks/addition/addition.cpp index 92872802..1eb08100 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"}; + return static_cast(a) + static_cast(b); } \ No newline at end of file diff --git a/01_week/tasks/char_changer/char_changer.cpp b/01_week/tasks/char_changer/char_changer.cpp index 3a7344d9..280ce19b 100644 --- a/01_week/tasks/char_changer/char_changer.cpp +++ b/01_week/tasks/char_changer/char_changer.cpp @@ -1,7 +1,54 @@ +#include #include #include size_t CharChanger(char array[], size_t size, char delimiter = ' ') { - throw std::runtime_error{"Not implemented"}; + if (!array || size == 0) { + throw std::invalid_argument{"Empty array"}; + } + + size_t src {}; // индекс чтения + size_t dst {}; // индекс записи + + while (array[src] != '\0' && src < size) { + char c { array[src++] }; // текущий символ + + // Подсчет количества одинаковых символов + size_t count {1}; + while (array[src] != '\0' && src < size) { + const char next { array[src] }; + if (c != next) + break; + count++; + src++; + } + + // Изменение символа в соответствии с правилами + bool isspace {}; + if (std::isdigit(static_cast(c))) { + c = '*'; + } else if (std::islower(static_cast(c))) { + c = std::toupper(static_cast(c)); + } else if (std::isupper(static_cast(c))) { + // без изменений + } else if (std::isspace(static_cast(c))) { + c = delimiter; + isspace = true; + } else { + c = '_'; + } + + // Запись измененного символа и количества в массив + array[dst++] = c; + if (count > 1 && !isspace) { + if (count >= 10) { + array[dst++] = '0'; + } else { + array[dst++] = static_cast('0' + count); + } + } + } + + return (array[dst] = '\0', dst); // позиция конца строки } diff --git a/01_week/tasks/check_flags/check_flags.cpp b/01_week/tasks/check_flags/check_flags.cpp index 75e7c652..c94e71c8 100644 --- a/01_week/tasks/check_flags/check_flags.cpp +++ b/01_week/tasks/check_flags/check_flags.cpp @@ -1,5 +1,7 @@ +#include #include -#include +#include +#include enum class CheckFlags : uint8_t { @@ -13,6 +15,37 @@ enum class CheckFlags : uint8_t { ALL = TIME | DATE | USER | CERT | KEYS | DEST }; -void PrintCheckFlags(CheckFlags flags) { - throw std::runtime_error{"Not implemented"}; +void PrintCheckFlags(CheckFlags flags) { + constexpr static const auto all { static_cast(CheckFlags::ALL) }; + const auto value { static_cast(flags) }; + + // Есть биты вне диапазона + if ((value & ~all) != 0) { + std::cout << ""; + return; + } + + if (value == static_cast(CheckFlags::NONE)) { + std::cout << "[]"; + return; + } + + std::string out {'['}; + bool first { true }; + for (uint8_t i = 0; std::cmp_less(i, std::popcount(all)); ++i) { + if ((value & (1u << i)) != 0) { + if (!first) out += ','; + switch (i) { + case 0: out += "TIME"; break; + case 1: out += "DATE"; break; + case 2: out += "USER"; break; + case 3: out += "CERT"; break; + case 4: out += "KEYS"; break; + case 5: out += "DEST"; break; + } + first = false; + } + } + out += ']'; + std::cout << out; } diff --git a/01_week/tasks/length_lit/length_lit.cpp b/01_week/tasks/length_lit/length_lit.cpp index e69de29b..1a294f5f 100644 --- a/01_week/tasks/length_lit/length_lit.cpp +++ b/01_week/tasks/length_lit/length_lit.cpp @@ -0,0 +1,59 @@ +// Футы → метры +constexpr double operator""_ft_to_m(long double v) { + return static_cast(v * 0.3048); +} + +// Футы → сантиметры +constexpr double operator""_ft_to_cm(long double v) { + return static_cast(v * 30.48); +} + +// Футы → дюймы +constexpr double operator""_ft_to_in(long double v) { + return static_cast(v * 12.0); +} + +// Дюймы → футы +constexpr double operator""_in_to_ft(long double v) { + return static_cast(v / 12.0); +} + +// Дюймы → сантиметры +constexpr double operator""_in_to_cm(long double v) { + return static_cast(v * 2.54); +} + +// Дюймы → метры +constexpr double operator""_in_to_m(long double v) { + return static_cast(v * 0.0254); +} + +// Сантиметры → метры +constexpr double operator""_cm_to_m(long double v) { + return static_cast(v / 100.0); +} + +// Сантиметры → дюймы +constexpr double operator""_cm_to_in(long double v) { + return static_cast(v / 2.54); +} + +// Сантиметры → футы +constexpr double operator""_cm_to_ft(long double v) { + return static_cast(v / 30.48); +} + +// Метры → сантиметры +constexpr double operator""_m_to_cm(long double v) { + return static_cast(v * 100.0); +} + +// Метры → футы +constexpr double operator""_m_to_ft(long double v) { + return static_cast(v / 0.3048); +} + +// Метры → дюймы +constexpr double operator""_m_to_in(long double v) { + return static_cast(v / 0.0254); +} \ No newline at end of file diff --git a/01_week/tasks/print_bits/print_bits.cpp b/01_week/tasks/print_bits/print_bits.cpp index a48a43c1..8f8360ca 100644 --- a/01_week/tasks/print_bits/print_bits.cpp +++ b/01_week/tasks/print_bits/print_bits.cpp @@ -1,7 +1,25 @@ #include #include - +#include void PrintBits(long long value, size_t bytes) { - throw std::runtime_error{"Not implemented"}; + using value_t = decltype(value); + + if (bytes == 0 || bytes > sizeof(value)) { + throw std::invalid_argument("Invalid number of bytes"); + } + + const auto bits { bytes * 8 }; + + std::string out { "0b" }; + for (size_t i = 0; i < bits; ++i) { + const value_t mask { (static_cast(1) << (bits - 1 - i)) }; + const bool bs { (value & mask) != 0 }; + out += (bs ? '1' : '0'); + if ((i + 1) % 4 == 0 && i + 1 < bits) { + out += '\''; + } + } + std::cout << out << std::endl; + } diff --git a/01_week/tasks/quadratic/quadratic.cpp b/01_week/tasks/quadratic/quadratic.cpp index abf7d632..44b469e1 100644 --- a/01_week/tasks/quadratic/quadratic.cpp +++ b/01_week/tasks/quadratic/quadratic.cpp @@ -1,6 +1,43 @@ -#include +#include +#include +#include void SolveQuadratic(int a, int b, int c) { - throw std::runtime_error{"Not implemented"}; + constexpr const int precision { 6 }; + + // Сохраняем текущее состояние потока + std::ios oldState(nullptr); + oldState.copyfmt(std::cout); + + std::cout << std::setprecision(precision); + + if (a == 0) { + if (b == 0) { + if (c == 0) { + std::cout << "infinite solutions"; + } else { + std::cout << "no solutions"; + } + } else { + std::cout << -static_cast(c) / b; + } + } else { + const int d { b * b - 4 * a * c }; + if (d < 0) { + std::cout << "no solutions"; + } else if (d == 0) { + if (b == 0) { + std::cout << "0"; + } else { + std::cout << -static_cast(b) / (2 * a); + } + } else { + const double sqrt_d { std::sqrt(d) }; + std::cout << (-b - sqrt_d) / (2 * a) << ' ' << (-b + sqrt_d) / (2 * a); + } + } + + // Восстанавливаем состояние потока + std::cout.copyfmt(oldState); } \ No newline at end of file diff --git a/01_week/tasks/rms/rms.cpp b/01_week/tasks/rms/rms.cpp index 6882f0a9..a084e710 100644 --- a/01_week/tasks/rms/rms.cpp +++ b/01_week/tasks/rms/rms.cpp @@ -1,7 +1,23 @@ -#include +#include #include +#include +#include double CalculateRMS(double values[], size_t size) { - throw std::runtime_error{"Not implemented"}; + if (size == 0 || values == nullptr) { + return 0.0; + } + + std::span dataSpan(values, size); + + double rms {}; + for (const auto& value : dataSpan) { + if (!std::isfinite(value)) { + throw std::invalid_argument("Array contains non-finite values"); + } + rms += value * value; + } + + return std::sqrt(rms / static_cast(size)); } \ No newline at end of file diff --git a/02_week/tasks/func_array/func_array.cpp b/02_week/tasks/func_array/func_array.cpp index b327e68d..56e3e178 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 +#include -double ApplyOperations(double a, double b /* other arguments */) { - throw std::runtime_error{"Not implemented"}; +double ApplyOperations(double a, double b, double (*operations[])(double, double), size_t operations_count) { + if (operations_count == 0) { + return 0.0; + } + + double sum {}; + + for (size_t i = 0; i < operations_count; ++i) { + if (operations[i] == nullptr) continue; + sum += operations[i](std::as_const(a), std::as_const(b)); + } + + return sum; } \ No newline at end of file diff --git a/02_week/tasks/last_of_us/last_of_us.cpp b/02_week/tasks/last_of_us/last_of_us.cpp index c7bf1a25..bccfafa6 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,16 @@ -#include -/* return_type */ FindLastElement(/* ptr_type */ begin, /* ptr_type */ end, /* func_type */ predicate) { - throw std::runtime_error{"Not implemented"}; +const int* FindLastElement(const int* cbegin, const int* cend, bool (*predicate)(int)) { + if (cbegin == nullptr || cend == nullptr || cbegin >= cend || predicate == nullptr) { + return cend; + } + + auto rcbegin = cend; + while (rcbegin != cbegin) { + if (predicate(*(--rcbegin))) { + return rcbegin; + } + } + + return cend; } \ No newline at end of file diff --git a/02_week/tasks/little_big/little_big.cpp b/02_week/tasks/little_big/little_big.cpp index abe24379..25b3ae31 100644 --- a/02_week/tasks/little_big/little_big.cpp +++ b/02_week/tasks/little_big/little_big.cpp @@ -1,10 +1,47 @@ -#include +#include +#include +#include +#include +#include +using namespace std; -void PrintMemory(int /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; -} +using byte_view_t = const unsigned char*; -void PrintMemory(double /* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +static const bool LITTLE_ENDIAN_STATUS { []() { + const uint16_t number { 0x1 }; + return *reinterpret_cast(addressof(number)) == 0x1; +}() }; +static const bool INVERT_DEFAULT { !LITTLE_ENDIAN_STATUS }; + +template +concept IntOrDouble = std::is_same_v || std::is_same_v; + +template +void PrintMemory(const T value, const bool invert = INVERT_DEFAULT) +{ + const byte_view_t p { reinterpret_cast(addressof(value)) }; + const size_t n { sizeof(value) }; + + // Сохраняем текущее состояние потока + std::ios oldState(nullptr); + oldState.copyfmt(std::cout); + + std::cout << std::uppercase << std::hex << std::setfill('0'); + + std::cout << "0x"; + if (!invert) { + for (std::size_t i = 0; i < n; ++i) { + std::cout << std::setw(2) << static_cast(p[i]); + } + } else { + for (std::size_t i = 0; i < n; ++i) { + const std::size_t j { n - 1 - i }; + std::cout << std::setw(2) << static_cast(p[j]); + } + } + std::cout << "\n"; + + // Восстанавливаем состояние потока + std::cout.copyfmt(oldState); } \ No newline at end of file diff --git a/02_week/tasks/longest/longest.cpp b/02_week/tasks/longest/longest.cpp index 04b3c354..c68db6a2 100644 --- a/02_week/tasks/longest/longest.cpp +++ b/02_week/tasks/longest/longest.cpp @@ -1,6 +1,41 @@ -#include +#include // size_t +#include // std::next, std::prev +char* FindLongestSubsequence(const char* cbegin, const char* cend, size_t& count) { + if (cbegin == nullptr || cend == nullptr || cbegin >= cend) { + return (count = 0, nullptr); + } -/* return_type */ FindLongestSubsequence(/* ptr_type */ begin, /* ptr_type */ end, /* type */ count) { - throw std::runtime_error{"Not implemented"}; + const char* bestStart { cbegin }; + size_t bestLen { 1 }; + + const char* currStart { cbegin }; + size_t currLen { 1 }; + + auto CheckCurrentSequence = [&]() { + if (currLen > bestLen) { + bestLen = currLen; + bestStart = currStart; + } + }; + + for (const char* it { std::next(cbegin) }; it < cend; ++it) { + if (*it == *(std::prev(it))) { + // Продолжаем текущую последовательность + ++currLen; + } else { + // Последовательность прервалась + CheckCurrentSequence(); + // Начинаем новую последовательность + currStart = it; + currLen = 1; + } + } + + // Проверка последней последовательности + CheckCurrentSequence(); + + //? Тест MutableString на момент написания кода предполагает, + //? что возвращается неконстантный указатель + return (count = bestLen, const_cast(bestStart)); } diff --git a/02_week/tasks/pretty_array/pretty_array.cpp b/02_week/tasks/pretty_array/pretty_array.cpp index 48eab341..b5306263 100644 --- a/02_week/tasks/pretty_array/pretty_array.cpp +++ b/02_week/tasks/pretty_array/pretty_array.cpp @@ -1,6 +1,60 @@ -#include +#include +#include +#include +static constexpr size_t NO_LIMIT = 0; +static constexpr const size_t LIMIT_DEAFULT {NO_LIMIT}; -void PrintArray(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +void PrintArray(const int* cbegin, const int* cend, size_t limit = LIMIT_DEAFULT) { + if (cbegin == nullptr || cend == nullptr) { + std::cout << "[]\n"; + return; + } + + // Сохраняем текущее состояние потока + std::ios oldState(nullptr); + oldState.copyfmt(std::cout); + + std::cout.flags(std::ios::fmtflags(0)); // сброс всех флагов + std::cout << std::dec; // десятичный вывод + std::cout.width(0); // ширина по умолчанию + std::cout.fill(' '); // пробел как fill + + const std::string separator { ", " }; + const std::string lineBreak { ", ...\n " }; + + const auto total { static_cast(cbegin < cend ? std::distance(cbegin, cend) : std::distance(cend, cbegin)) }; + + auto PrintElement = [&](const size_t idx, const int* const p) { + std::cout << *p; + + const auto num { idx + 1 }; + + if (num < total) { + if (limit != NO_LIMIT && num % limit == 0) + { + std::cout << lineBreak; + } else { + std::cout << separator; + } + } + }; + + const bool isReverse { cbegin > cend }; + + std::cout << "["; + const int* p { cbegin }; + if (isReverse) { + for (size_t i = 0; p > cend; --p, ++i) { + PrintElement(i, p); + } + } else { + for (size_t i = 0; p < cend; ++p, ++i) { + PrintElement(i, p); + } + } + std::cout << "]\n"; + + // Восстанавливаем состояние потока + std::cout.copyfmt(oldState); } \ No newline at end of file diff --git a/02_week/tasks/swap_ptr/swap_ptr.cpp b/02_week/tasks/swap_ptr/swap_ptr.cpp index 93db625d..41d61074 100644 --- a/02_week/tasks/swap_ptr/swap_ptr.cpp +++ b/02_week/tasks/swap_ptr/swap_ptr.cpp @@ -1,6 +1,7 @@ -#include - -void SwapPtr(/* write arguments here */) { - throw std::runtime_error{"Not implemented"}; +template +void SwapPtr(T*& pp1, T*& pp2) { + auto temp { pp1 }; + pp1 = pp2; + pp2 = temp; } \ No newline at end of file diff --git a/03_week/tasks/data_stats/data_stats.cpp b/03_week/tasks/data_stats/data_stats.cpp index b941c211..5156f4e2 100644 --- a/03_week/tasks/data_stats/data_stats.cpp +++ b/03_week/tasks/data_stats/data_stats.cpp @@ -1,4 +1,6 @@ -#include +#include +#include +#include struct DataStats { @@ -6,6 +8,27 @@ struct DataStats { double sd = 0.0; }; -/* return_type */ CalculateDataStats(/* args */) { - throw std::runtime_error{"Not implemented"}; +DataStats CalculateDataStats(const std::vector& data) { + DataStats stats {}; + + if (data.empty()) + return stats; + + // Алгорит Уэлфорда для вычисления среднего и стандартного отклонения + double M2 {}; + for (size_t count {}; int x : data) { + count++; + const auto delta { x - stats.avg }; + stats.avg += delta / static_cast>(count); + M2 += delta * (x - stats.avg); + } + + const size_t n { data.size() }; + + //? Математически корректно использовать n-1 для несмещённой оценки дисперсии выборки, + //? так как мы рассчитываем стандартное отклонение по выборке, + //? но так тесты не проходят, поэтому используем n. + stats.sd = std::sqrt(n == 1 ? 0.0 : M2 / static_cast>(n)); + + return stats; } diff --git a/03_week/tasks/easy_compare/easy_compare.cpp b/03_week/tasks/easy_compare/easy_compare.cpp index dd5cb7f6..439757f2 100644 --- a/03_week/tasks/easy_compare/easy_compare.cpp +++ b/03_week/tasks/easy_compare/easy_compare.cpp @@ -1,10 +1,12 @@ -#include - +#include +#include struct Date { - unsigned year; - unsigned month; - unsigned day; + unsigned year {}; + unsigned month {}; + unsigned day {}; + + auto operator<=>(const Date&) const noexcept = default; }; struct StudentInfo { @@ -13,4 +15,21 @@ struct StudentInfo { int score; unsigned course; Date birth_date; + + bool operator==(const StudentInfo& other) const noexcept { + return mark == other.mark && score == other.score; + } + + auto operator<(const StudentInfo& other) const noexcept { + if (mark != other.mark) + return other.mark < mark; // обратный порядок + if (score != other.score) + return score < other.score; + if (course != other.course) + return other.course < course; // обратный порядок + if (birth_date != other.birth_date) + return birth_date < other.birth_date; + + return false; + } }; \ No newline at end of file diff --git a/03_week/tasks/enum_operators/enum_operators.cpp b/03_week/tasks/enum_operators/enum_operators.cpp index a539be38..4a875ec9 100644 --- a/03_week/tasks/enum_operators/enum_operators.cpp +++ b/03_week/tasks/enum_operators/enum_operators.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include enum class CheckFlags : uint8_t { NONE = 0, @@ -12,22 +12,67 @@ enum class CheckFlags : uint8_t { ALL = TIME | DATE | USER | CERT | KEYS | DEST }; -/* return_type */ operator|(/* args */) { - throw std::runtime_error{"Not implemented"}; + +static constexpr const uint8_t ALL_FLAGS { static_cast(CheckFlags::ALL) }; + +static constexpr CheckFlags RemoveOverflows(const CheckFlags flags) { + return static_cast(static_cast(flags) & ALL_FLAGS); } -/* return_type */ operator&(/* args */) { - throw std::runtime_error{"Not implemented"}; + +auto operator|(const CheckFlags lhs, const CheckFlags rhs) { + return RemoveOverflows(static_cast( + static_cast(lhs) | static_cast(rhs))); } -/* return_type */ operator^(/* args */) { - throw std::runtime_error{"Not implemented"}; +auto operator&(const CheckFlags lhs, const CheckFlags rhs) { + const uint8_t l { static_cast(RemoveOverflows(lhs)) }; + const uint8_t r { static_cast(RemoveOverflows(rhs)) }; + + if (l == 0 || r == 0) return false; // любые проверки с NONE -> false + + const uint8_t inter { static_cast(l & r) }; + const bool lhs_subset_rhs { (inter == l) }; // все биты lhs содержатся в rhs + const bool rhs_subset_lhs { (inter == r) }; // все биты rhs содержатся в lhs + + return lhs_subset_rhs || rhs_subset_lhs; + } -/* return_type */ operator~(/* args */) { - throw std::runtime_error{"Not implemented"}; +auto operator^(const CheckFlags lhs, const CheckFlags rhs) { + return RemoveOverflows(static_cast( + static_cast(lhs) ^ static_cast(rhs))); + } -/* return_type */ operator<<(/* args */) { - throw std::runtime_error{"Not implemented"}; +auto operator~(const CheckFlags flags) { + const uint8_t val { static_cast(flags) }; + return RemoveOverflows(static_cast(~val)); +} + +auto operator<<(std::ostream& os, const CheckFlags flags) -> std::ostream& { + const uint8_t value { static_cast(RemoveOverflows(flags)) }; + + if (value == 0) { + os << "NONE"; + return os; + } + + bool first { true }; + auto print_flag = [&](CheckFlags f, const char* name) { + if ((static_cast(flags) & static_cast(f)) != 0) { + if (!first) os << ", "; + os << name; + first = false; + } + }; + + print_flag(CheckFlags::TIME, "TIME"); + print_flag(CheckFlags::DATE, "DATE"); + print_flag(CheckFlags::USER, "USER"); + print_flag(CheckFlags::CERT, "CERT"); + print_flag(CheckFlags::KEYS, "KEYS"); + print_flag(CheckFlags::DEST, "DEST"); + + return os; } diff --git a/03_week/tasks/filter/filter.cpp b/03_week/tasks/filter/filter.cpp index 6648cb39..478e4851 100644 --- a/03_week/tasks/filter/filter.cpp +++ b/03_week/tasks/filter/filter.cpp @@ -1,6 +1,16 @@ -#include +#include -/* return_type */ Filter(/* args */) { - throw std::runtime_error{"Not implemented"}; +void Filter(std::vector& vec, bool (*predicate)(int)) { + if (vec.empty() || predicate == nullptr) { + return; + } + + size_t write {}; // куда писать "валидные" элементы + for (std::size_t read = 0; read < vec.size(); ++read) { + if (predicate(vec[read])) { + vec[write++] = vec[read]; + } + } + vec.resize(write); // обрезаем хвост } \ No newline at end of file diff --git a/03_week/tasks/find_all/find_all.cpp b/03_week/tasks/find_all/find_all.cpp index 74f393b2..6011ff09 100644 --- a/03_week/tasks/find_all/find_all.cpp +++ b/03_week/tasks/find_all/find_all.cpp @@ -1,6 +1,20 @@ -#include +#include -/* return_type */ FindAll(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::vector FindAll(const std::vector& vec, bool (*predicate)(int)) { + std::vector indices {}; + + if (vec.empty() || predicate == nullptr) { + return indices; + } + + indices.reserve(vec.size()); + + for (size_t i = 0; i < vec.size(); ++i) { + if (predicate(vec[i])) { + indices.push_back(i); + } + } + + return (indices.shrink_to_fit(), indices); } \ No newline at end of file diff --git a/03_week/tasks/minmax/minmax.cpp b/03_week/tasks/minmax/minmax.cpp index c2869799..2e4af000 100644 --- a/03_week/tasks/minmax/minmax.cpp +++ b/03_week/tasks/minmax/minmax.cpp @@ -1,6 +1,25 @@ -#include +#include -/* return_type */ MinMax(/* args */) { - throw std::runtime_error{"Not implemented"}; -} +auto MinMax(const std::vector& vec) { + auto min_it { vec.cend() }; + auto max_it { vec.cend() }; + + if (vec.empty()) { + return std::make_pair(min_it, max_it); + } + + min_it = vec.cbegin(); + max_it = vec.cbegin(); + + for (auto it = vec.cbegin(); it != vec.cend(); ++it) { + if (*it < *min_it) { + min_it = it; + } + if (*it >= *max_it) { + max_it = it; + } + } + + return std::make_pair(min_it, max_it); +} \ No newline at end of file diff --git a/03_week/tasks/os_overload/os_overload.cpp b/03_week/tasks/os_overload/os_overload.cpp index e473418d..ee3ca55c 100644 --- a/03_week/tasks/os_overload/os_overload.cpp +++ b/03_week/tasks/os_overload/os_overload.cpp @@ -1,21 +1,65 @@ +#include #include #include #include struct Coord2D { - int x; - int y; + int x {0}; + int y {0}; }; struct Circle { - Coord2D coord; - unsigned radius; + Coord2D coord {}; + 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 << std::dec << "(" << coord.x << ", " << coord.y << ")"; + return os; +} + +std::ostream& operator<<(std::ostream& os, const Circle& circle) { + os << "circle" << "["; + if (circle.radius == 0) { + os << "]"; + return os; + } + os << circle.coord; + os << ", r = " << std::dec << circle.radius; + os << "]"; + return os; +} + +std::ostream& operator<<(std::ostream& os, const CircleRegion& circle_region) { + if (circle_region.second) { + // внутренняя область + os << "+"; + } else { + // внешняя область + os << "-"; + } + os << circle_region.first; + return os; +} + +std::ostream& operator<<(std::ostream& os, const CircleRegionList& list) { + if (list.empty()) { + os << "{}"; + return os; + } + + os << "{\n\t"; + for (const auto& circle_region : list) { + os << circle_region; + if (&circle_region != &list.back()) { + os << ",\n\t"; + } + } + os << "\n}"; + + return os; } diff --git a/03_week/tasks/range/range.cpp b/03_week/tasks/range/range.cpp index d2085495..91c0db06 100644 --- a/03_week/tasks/range/range.cpp +++ b/03_week/tasks/range/range.cpp @@ -1,7 +1,26 @@ -#include #include -std::vector Range(int from, int to, int step) { - throw std::runtime_error{"Not implemented"}; -} +std::vector Range(const int from, const int to, const int step = 1) { + std::vector result {}; + + if (step == 0 || from == to || + (step > 0 && from > to) || + (step < 0 && from < to)) + { + return result; + } + + const size_t size { + (to - from) % step == 0 + ? static_cast((to - from) / step) + : static_cast((to - from) / step) + 1 + }; + result.reserve(size); + + for (int i = from; (step > 0) ? (i < to) : (i > to); i += step) { + result.push_back(i); + } + + return result; +} \ No newline at end of file diff --git a/03_week/tasks/unique/unique.cpp b/03_week/tasks/unique/unique.cpp index 9d2545bb..76cf8ddd 100644 --- a/03_week/tasks/unique/unique.cpp +++ b/03_week/tasks/unique/unique.cpp @@ -1,6 +1,19 @@ -#include #include -/* return_type */ Unique(/* args */) { - throw std::runtime_error{"Not implemented"}; +std::vector Unique(const std::vector& vec) { + std::vector result {}; + + if (vec.empty()) { + return result; + } + + result.reserve(vec.size()); + + for (const auto& item : vec) { + if (result.empty() || result.back() != item) { + result.push_back(item); + } + } + + return (result.shrink_to_fit(), result); } diff --git a/04_week/tasks/phasor/phasor.cpp b/04_week/tasks/phasor/phasor.cpp index 3ec1b9ad..a8d18e2c 100644 --- a/04_week/tasks/phasor/phasor.cpp +++ b/04_week/tasks/phasor/phasor.cpp @@ -1,10 +1,234 @@ +#include +#include +#include +#include +#include +#include struct ExpTag {}; struct DegTag {}; struct AlgTag {}; +static constexpr const double EPSILON { 1e-12 }; // std::numeric_limits::epsilon() + +static bool Eq(double a, double b) { + static constexpr const double eps { EPSILON }; + const std::array vals { 1.0, std::abs(a), std::abs(b) }; + const double eps_scaled { eps * *std::max_element(vals.begin(), vals.end()) }; + return std::abs(a - b) <= eps_scaled; +} class Phasor { + inline static constexpr const double pi { std::numbers::pi }; + +public: + Phasor() = default; + + Phasor(const double magnitude, const double phase_rad) + : real_(magnitude * std::cos(phase_rad)) + , imag_(magnitude * std::sin(phase_rad)) + {} + + Phasor(const double magnitude, const double phase_rad, const ExpTag&) + : Phasor(magnitude, phase_rad) + {} + + Phasor(const double magnitude, const double phase_deg, const DegTag&) + : Phasor(magnitude, DegreeToRadian(phase_deg)) + {} + + Phasor(const double real, const double imag, const AlgTag&) + : real_(real) + , imag_(imag) + {} + + ~Phasor() = default; + + Phasor(const Phasor& other) = default; + Phasor& operator=(const Phasor& other) = default; + + Phasor(Phasor&& other) noexcept = default; + Phasor& operator=(Phasor&& other) noexcept = default; + + static double RadianToDegree(const double rad) noexcept { + return rad * 180.0 / pi; + } + static double DegreeToRadian(const double deg) noexcept { + return deg * pi / 180.0; + } + + /// @name Getters + /// @{ + double Real() const noexcept { + return real_; + } + double Imag() const noexcept { + return imag_; + } + + double Magnitude() const noexcept { + return std::sqrt(Real() * Real() + Imag() * Imag()); + } + double Phase() const noexcept { + const auto phase { std::atan2(Imag(), Real()) }; + return Eq(phase, -pi) ? pi : phase; + } + double PhaseDeg() const noexcept { + return RadianToDegree(Phase()); + } + + double Abs() const noexcept { + return Magnitude(); + } + double Angle() const noexcept { + return Phase(); + } + double AngleDeg() const noexcept { + return PhaseDeg(); + } + + Phasor Conj() const noexcept { + return Phasor(Real(), -Imag(), AlgTag{}); + } + Phasor Inv() const noexcept { + const double denom { Real() * Real() + Imag() * Imag() }; + return Phasor(Real() / denom, -Imag() / denom, AlgTag{}); + } + /// @} + /// @name Setters + /// @{ + void SetPolar(const double magnitude, const double phase_rad) noexcept { + real_ = magnitude * std::cos(phase_rad); + imag_ = magnitude * std::sin(phase_rad); + } + void SetCartesian(const double real, const double imag) noexcept { + real_ = real; + imag_ = imag; + } + /// @} + + /// @name Operators + /// @{ + bool operator==(const Phasor& other) const noexcept { + return Eq(real_, other.real_) && Eq(imag_, other.imag_); + } + bool operator!=(const Phasor& other) const noexcept { + return !(*this == other); + } + + bool operator==(const double other) const noexcept { + return Eq(real_, other) && Eq(imag_, 0.0); + } + bool operator!=(const double other) const noexcept { + return !(*this == other); + } + + Phasor operator+(const double other) const noexcept { + return Phasor(Real() + other, Imag(), AlgTag{}); + } + Phasor operator-(const double other) const noexcept { + return Phasor(Real() - other, Imag(), AlgTag{}); + } + Phasor operator*(const double other) const noexcept { + return Phasor(Magnitude() * other, Phase()); + } + Phasor operator/(const double other) const noexcept { + return Phasor(Magnitude() / other, Phase()); + } + + friend Phasor operator+(const double lhs, const Phasor& rhs) noexcept { + return rhs + lhs; + } + friend Phasor operator-(const double lhs, const Phasor& rhs) noexcept { + return Phasor(lhs - rhs.Real(), -rhs.Imag(), AlgTag{}); + } + friend Phasor operator*(const double lhs, const Phasor& rhs) noexcept { + return rhs * lhs; + } + friend Phasor operator/(const double lhs, const Phasor& rhs) noexcept { + return Phasor(lhs / rhs.Magnitude(), -rhs.Phase()); + } + + Phasor operator+(const Phasor& other) const noexcept { + return Phasor(Real() + other.Real(), Imag() + other.Imag(), AlgTag{}); + } + Phasor operator-(const Phasor& other) const noexcept { + return Phasor(Real() - other.Real(), Imag() - other.Imag(), AlgTag{}); + } + Phasor operator*(const Phasor& other) const noexcept { + return Phasor(Magnitude() * other.Magnitude(), Phase() + other.Phase()); + } + Phasor operator/(const Phasor& other) const noexcept { + return Phasor(Magnitude() / other.Magnitude(), Phase() - other.Phase()); + } + + Phasor& operator+=(const double other) noexcept { + SetCartesian(Real() + other, Imag()); + return *this; + } + Phasor& operator-=(const double other) noexcept { + SetCartesian(Real() - other, Imag()); + return *this; + } + Phasor& operator*=(const double other) noexcept { + SetPolar(Magnitude() * other, Phase()); + return *this; + } + Phasor& operator/=(const double other) noexcept { + SetPolar(Magnitude() / other, Phase()); + return *this; + } + + Phasor& operator+=(const Phasor& other) noexcept { + SetCartesian(Real() + other.Real(), Imag() + other.Imag()); + return *this; + } + Phasor& operator-=(const Phasor& other) noexcept { + SetCartesian(Real() - other.Real(), Imag() - other.Imag()); + return *this; + } + Phasor& operator*=(const Phasor& other) noexcept { + SetPolar(Magnitude() * other.Magnitude(), Phase() + other.Phase()); + return *this; + } + Phasor& operator/=(const Phasor& other) noexcept { + SetPolar(Magnitude() / other.Magnitude(), Phase() - other.Phase()); + return *this; + } + /// @} + + /// @name Unary operators + /// @{ + Phasor operator-() const noexcept { + return Phasor(-Real(), -Imag(), AlgTag{}); + } + Phasor operator+() const noexcept { + return *this; + } + /// @} + +private: + double real_{0.0}; + double imag_{0.0}; }; + +Phasor MakePhasorPolar(const double magnitude, const double phase_rad) { + return Phasor(magnitude, phase_rad, ExpTag{}); +} + +Phasor MakePhasorPolarDeg(const double magnitude, const double phase_deg) { + return Phasor(magnitude, phase_deg, DegTag{}); +} + +Phasor MakePhasorCartesian(const double real, const double imag) { + return Phasor(real, imag, AlgTag{}); +} + +std::ostream& operator<<(std::ostream& os, const Phasor& phasor) { + os << std::dec << std::fixed << std::setprecision(3) + << phasor.Magnitude() << "*e(j*" << phasor.PhaseDeg() << ")" + << " [" << phasor.Real() << " + j*" << phasor.Imag() << "]"; + return os; +} \ No newline at end of file diff --git a/04_week/tasks/queue/queue.cpp b/04_week/tasks/queue/queue.cpp index 2a9f8493..557adfca 100644 --- a/04_week/tasks/queue/queue.cpp +++ b/04_week/tasks/queue/queue.cpp @@ -1,6 +1,153 @@ #include +#include +#include + class Queue { +public: + Queue() = default; + + Queue(std::stack s) { + while (!s.empty()) { + input_.push_back(s.top()); + s.pop(); + } + std::reverse(input_.begin(), input_.end()); + } + + Queue(const std::vector& vec) + : input_(vec) + {} + + Queue(const std::initializer_list& init) + : input_(init.begin(), init.end()) + {} + + Queue(std::size_t capacity) { + input_.reserve(capacity); + } + + ~Queue() = default; + + + bool Empty() const noexcept { + return Size() == 0; + } + auto Size() const noexcept -> std::size_t { + return input_.size() + output_.size(); + } + + /// @name Modifiers + /// @{ + void Push(const int value) noexcept { + input_.push_back(value); + } + bool Pop() noexcept { + if (output_.empty()) { + if (input_.empty()) { + return false; + } + std::reverse(input_.begin(), input_.end()); + std::swap(input_, output_); + } + output_.pop_back(); + return true; + } + void Swap(Queue& other) noexcept { + std::swap(input_, other.input_); + std::swap(output_, other.output_); + } + void Clear() noexcept { + input_.clear(); + output_.clear(); + } + /// @} + + /// @name Front/Back + /// @{ + auto Front() -> int&; + auto Front() const -> const int&; + auto Back() -> int&; + auto Back() const -> const int&; + /// @} + /// @name Comparison operators + /// @{ + bool operator==(const Queue& other) const noexcept; + bool operator!=(const Queue& other) const noexcept { + return !(*this == other); + } + /// @} + +private: + template + static auto& FrontImpl(Self& self); + template + static auto& BackImpl(Self& self); + +private: + std::vector input_ {}; + std::vector output_{}; }; + +template +auto& Queue::FrontImpl(Self& self) { + if (self.output_.empty()) { + return self.input_.front(); + } + return self.output_.back(); +} +auto Queue::Front() -> int& { + return FrontImpl(*this); +} +auto Queue::Front() const -> const int& { + return FrontImpl(*this); +} + + +template +auto& Queue::BackImpl(Self& self) { + if (self.input_.empty()) + return self.output_.front(); + return self.input_.back(); +} +auto Queue::Back() -> int& { + return BackImpl(*this); +} +auto Queue::Back() const -> const int& { + return BackImpl(*this); +} + +bool Queue::operator==(const Queue& other) const noexcept { + if (Size() != other.Size()) { + return false; + } + + const auto sz { Size() }; + for (std::size_t i = 0; i < sz; ++i) { + if (output_.size() > i && other.output_.size() > i) { + if ( output_[ output_.size() - 1 - i] != + other.output_[other.output_.size() - 1 - i]) + { + return false; + } + } else if (output_.size() > i) { + if (output_[output_.size() - 1 - i] != other.input_[i - other.output_.size()]) { + return false; + } + } else if (other.output_.size() > i) { + if (input_[i - output_.size()] != other.output_[other.output_.size() - 1 - i]) { + return false; + } + } else { + if ( input_[i - output_.size()] != + other.input_[i - other.output_.size()]) + { + return false; + } + } + } + + return true; +} \ No newline at end of file diff --git a/04_week/tasks/ring_buffer/ring_buffer.cpp b/04_week/tasks/ring_buffer/ring_buffer.cpp index e2b57ba2..8beba010 100644 --- a/04_week/tasks/ring_buffer/ring_buffer.cpp +++ b/04_week/tasks/ring_buffer/ring_buffer.cpp @@ -1,6 +1,216 @@ +#include #include +static constexpr const std::size_t MINIMAL_CAPACITY { 1 }; + +/// @brief Вспомогательная функция для обеспечения минимальной емкости буфера +static auto ValidCapacity(const std::size_t capacity) noexcept { + return capacity >= MINIMAL_CAPACITY ? capacity : MINIMAL_CAPACITY; +} class RingBuffer { +public: + RingBuffer() = default; + RingBuffer(const std::size_t capacity) { + buffer_.reserve(ValidCapacity(capacity)); + } + + RingBuffer(const std::size_t capacity, int initial_value) + : buffer_(ValidCapacity(capacity), initial_value) + {} + + RingBuffer(const std::initializer_list& init) + : buffer_(init.begin(), init.end()) + { + buffer_.reserve(ValidCapacity(init.size())); + } + + ~RingBuffer() = default; + + /// @name Copy and move semantics + /// @{ + RingBuffer(const RingBuffer& other); + RingBuffer& operator=(const RingBuffer& other); + + RingBuffer(RingBuffer&& other) noexcept; + RingBuffer& operator=(RingBuffer&& other) noexcept; + /// @} + + /// @{ + auto Empty() const noexcept { + return buffer_.empty(); + } + auto Full() const noexcept { + return buffer_.size() == buffer_.capacity(); + } + auto Size() const noexcept -> std::size_t { + return buffer_.size(); + } + auto Capacity() const noexcept -> std::size_t { + return buffer_.capacity(); + } + /// @} + + /// @name Element access + /// @{ + auto Vector() const noexcept -> std::vector; + auto operator[](const std::size_t index) noexcept -> int&; + auto operator[](const std::size_t index) const noexcept -> const int&; + /// @} + + /// @name Front/Back + /// @{ + auto Front() -> int&; + auto Front() const -> const int&; + auto Back() -> int&; + auto Back() const -> const int&; + /// @} + + /// @name Modifiers + /// @{ + void Clear() noexcept; + + void Pop(); + bool TryPop(int& value); + + void Push(int value); + bool TryPush(int value); + + void Resize(const std::size_t new_capacity); + /// @} + +private: + template + static auto& FrontImpl(Self& self); + template + static auto& BackImpl(Self& self); + /** + * @brief Метод для получения корректного индекса в кольцевом буфере + * + * @param[in] index Индекс относительно начала буфера (самого старого элемента) + * @return std::size_t Корректный индекс в векторе хранения элементов + */ + auto ValidIndex(const std::size_t& index) const noexcept { + return (head_ + index) % Size(); + } + +private: + std::vector buffer_ {}; ///< Вектор для хранения элементов буфера + std::size_t head_ {}; ///< Индекс самого старого элемента в буфере +}; + +RingBuffer::RingBuffer(const RingBuffer& other) { + buffer_.reserve(other.Capacity()); + buffer_ = other.buffer_; + head_ = other.head_; }; +RingBuffer& RingBuffer::operator=(const RingBuffer& other) { + if (this != &other) { + buffer_.reserve(other.Capacity()); + buffer_ = other.buffer_; + head_ = other.head_; + } + return *this; +} +RingBuffer::RingBuffer(RingBuffer&& other) noexcept { + buffer_.reserve(other.Capacity()); + buffer_ = std::move(other.buffer_); + head_ = other.head_; +} +RingBuffer& RingBuffer::operator=(RingBuffer&& other) noexcept { + if (this != &other) { + buffer_.reserve(other.Capacity()); + buffer_ = std::move(other.buffer_); + head_ = other.head_; + } + return *this; +}; + +template +auto& RingBuffer::FrontImpl(Self& self) { + return self[self.Size() - 1]; +} +auto RingBuffer::Front() -> int& { + return FrontImpl(*this); +} +auto RingBuffer::Front() const -> const int& { + return FrontImpl(*this); +} + +template +auto& RingBuffer::BackImpl(Self& self) { + return self[0]; +} +auto RingBuffer::Back() -> int& { + return BackImpl(*this); +} +auto RingBuffer::Back() const -> const int& { + return BackImpl(*this); +} + +auto RingBuffer::Vector() const noexcept -> std::vector { + std::vector buffer; + buffer.reserve(Size()); + for (std::size_t i = 0; i < Size(); ++i) { + buffer.push_back((*this)[i]); + } + return buffer; +} + +auto RingBuffer::operator[](const std::size_t index) noexcept -> int& { + return buffer_[ValidIndex(index)]; +} +auto RingBuffer::operator[](const std::size_t index) const noexcept -> const int& { + return buffer_[ValidIndex(index)]; +} + +void RingBuffer::Clear() noexcept { + buffer_.clear(); + head_ = 0; +} + +void RingBuffer::Pop() { + if (!Empty()) { + buffer_.erase(buffer_.begin() + ValidIndex(0)); + head_ = Empty() ? 0 : head_ % Size(); + } +} +bool RingBuffer::TryPop(int& value) { + if (Empty()) { + return false; + } + value = Back(); + Pop(); + return true; +} + +void RingBuffer::Push(int value) { + if (Full()) { + Back() = value; + head_ = ValidIndex(1); // Сдвигаем голову вперед по кольцу на один элемент + } else { + buffer_.push_back(value); + } +} +bool RingBuffer::TryPush(int value) { + if (Full()) { + return false; + } + Push(value); + return true; +} + +void RingBuffer::Resize(const std::size_t new_capacity) { + const auto valid_capacity { ValidCapacity(new_capacity) }; + if (valid_capacity < Size()) { + if (head_ + valid_capacity <= Size()) { + buffer_.erase( + buffer_.begin() + ValidIndex(0), + buffer_.begin() + ValidIndex(Size() - valid_capacity)); + } + head_ = head_ % valid_capacity; + } + buffer_.shrink_to_fit(); + buffer_.reserve(valid_capacity); +} \ No newline at end of file diff --git a/04_week/tasks/stack/stack.cpp b/04_week/tasks/stack/stack.cpp index 222e4ffc..50571c31 100644 --- a/04_week/tasks/stack/stack.cpp +++ b/04_week/tasks/stack/stack.cpp @@ -2,5 +2,78 @@ class Stack { + using StackType = std::vector; +public: + Stack() = default; + + ~Stack() = default; + + /// @name Copy and move semantics + /// @{ + Stack(const Stack& other) = default; + Stack& operator=(const Stack& other) = default; + Stack(Stack&& other) noexcept = default; + Stack& operator=(Stack&& other) noexcept = default; + /// @} + + auto Empty() const noexcept { + return stack_.empty(); + } + auto Size() const noexcept { + return stack_.size(); + } + + /// @name Modifiers + /// @{ + void Push(int value) noexcept { + stack_.push_back(value); + } + bool Pop() noexcept { + if (stack_.empty()) + return false; + stack_.pop_back(); + return true; + } + + void Swap(Stack& other) noexcept { + std::swap(stack_, other.stack_); + } + + void Clear() noexcept { + stack_.clear(); + } + /// @} + + auto Top() noexcept -> int&; + auto Top() const noexcept -> const int&; + + bool operator==(const Stack& other) const noexcept; + bool operator!=(const Stack& other) const noexcept; + +private: + template + static auto& TopImpl(Self& self) noexcept; + +private: + StackType stack_ {}; ///< Вектор для хранения элементов стека }; + +template +auto& Stack::TopImpl(Self& self) noexcept { + return self.stack_.back(); +} + +auto Stack::Top() noexcept -> int& { + return TopImpl(*this); +} +auto Stack::Top() const noexcept -> const int& { + return TopImpl(*this); +} + +bool Stack::operator==(const Stack& other) const noexcept { + return stack_ == other.stack_; +} +bool Stack::operator!=(const Stack& other) const noexcept { + return !(*this == other); +} \ No newline at end of file