Сегодня реализуем алгоритм сжатия строк с помощью RLE (Run-Length Encoding), а также восстановление строки из сжатого представления.
В этой задаче:
• Считаем длину последовательностей одинаковых символов и сразу добавляем в результат
• При распаковке парсим число и столько раз добавляем следующий символ.
• Проверяем корректность: сжимаем → распаковываем → сравниваем строки.
Такой приём особенно полезен для логов, графики и повторяющихся данных, где он экономит место.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍4❤3
Быстро тестируем код через assert.
Сейчас научимся добавлять простые проверки прямо в код, чтобы убедиться, что функции работают правильно. Это особенно удобно на этапе отладки и для мини-тестов без фреймворков.
Подключим нужную библиотеку:
Предположим, у нас есть функция, которая должна возвращать квадрат числа. Реализуем её так:
Теперь напишем несколько простых тестов с помощью assert, чтобы проверить, что функция работает правильно на базовых примерах:
Если проверка не пройдёт — программа остановится и покажет, где ошибка.
Вот как может выглядеть ошибка, если ожидание не совпадает с результатом:
🔥 Таким образом ты можешь быстро проверять поведение функций — без сторонних библиотек и с минимальным кодом.
📣 C++ Ready | #практика
Сейчас научимся добавлять простые проверки прямо в код, чтобы убедиться, что функции работают правильно. Это особенно удобно на этапе отладки и для мини-тестов без фреймворков.
Подключим нужную библиотеку:
#include <cassert>
#include <iostream>
Предположим, у нас есть функция, которая должна возвращать квадрат числа. Реализуем её так:
int square(int x) {
return x * x;
}Теперь напишем несколько простых тестов с помощью assert, чтобы проверить, что функция работает правильно на базовых примерах:
int main() {
assert(square(2) == 4);
assert(square(-3) == 9);
assert(square(0) == 0);
std::cout << "Все тесты пройдены!\n";
return 0;
}Если проверка не пройдёт — программа остановится и покажет, где ошибка.
Вот как может выглядеть ошибка, если ожидание не совпадает с результатом:
Assertion failed: square(2) == 5, file main.cpp, line 10
🔥 Таким образом ты можешь быстро проверять поведение функций — без сторонних библиотек и с минимальным кодом.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍4❤3
В этой статье:
• Как формируется изображение через плоскость проекции, камеру и направление лучей• Почему пиксели можно представить как результат пересечения лучей со сценой• Базовая логика, с которой начинается построение собственного трассировщика лучей🔊 Продолжай читать на habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍6🔥4
Почему std::async иногда не делает код асинхронным?
На первый взгляд кажется, что задача просто запускается в фоне, а выполнение сразу идет дальше. Но у
Если этот
В итоге код выглядит как fire-and-forget, но на деле поток может заблокироваться уже на этой строке. То есть вместо фоновой работы ты случайно получаешь скрытую синхронизацию.
Из-за этого баг особенно неприятный: внешне все выглядит асинхронно, а по факту приложение тормозит в месте, где ты вообще не ждешь блокировки.
Если результат нужен позже,
А если тебе реально нужен отдельный поток жизни задачи, лучше использовать более явные инструменты, а не полагаться на такой неочевидный сценарий.
🔥 Не потеряй
📣 C++ Ready | #совет
На первый взгляд кажется, что задача просто запускается в фоне, а выполнение сразу идет дальше. Но у
std::async есть важная деталь: он возвращает std::future.Если этот
future не сохранить, он будет уничтожен в конце выражения. А для задачи, запущенной с std::launch::async, это может означать ожидание завершения прямо в деструкторе.В итоге код выглядит как fire-and-forget, но на деле поток может заблокироваться уже на этой строке. То есть вместо фоновой работы ты случайно получаешь скрытую синхронизацию.
Из-за этого баг особенно неприятный: внешне все выглядит асинхронно, а по факту приложение тормозит в месте, где ты вообще не ждешь блокировки.
Если результат нужен позже,
future надо сохранить и явно решить, когда именно его ждать.auto fut = std::async(std::launch::async, [] {
reindex();
});
std::cout << "after async\n";А если тебе реально нужен отдельный поток жизни задачи, лучше использовать более явные инструменты, а не полагаться на такой неочевидный сценарий.
future от std::async. Иначе “запустил в фоне” легко превращается в “случайно дождался здесь же”.Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥6❤5
1 миллион в год - именно столько я добавил к зарплате, просто составив грамотное резюме
Безусловно, уметь кодить - важный аспект, но на самом деле именно резюме решает, попадёте ли вы на собеседование или нет
Максим Аверин (Senior Python Dev) у себя в канале подробно разобрал вопросы, которыми тимлид мгновенно отсекает неопытных разработчиков и дал шаблон резюме, которое поможет тебе выбить более жирный оффер
Также для подписчиков есть бесплатный гайд «Как получить первую работу на Python с зарплатой от 150к»
Осень — самый горячий сезон найма. У тебя ещё есть возможность получить тот самый оффер, подписывайся: @maksim_python
Безусловно, уметь кодить - важный аспект, но на самом деле именно резюме решает, попадёте ли вы на собеседование или нет
Максим Аверин (Senior Python Dev) у себя в канале подробно разобрал вопросы, которыми тимлид мгновенно отсекает неопытных разработчиков и дал шаблон резюме, которое поможет тебе выбить более жирный оффер
Также для подписчиков есть бесплатный гайд «Как получить первую работу на Python с зарплатой от 150к»
Осень — самый горячий сезон найма. У тебя ещё есть возможность получить тот самый оффер, подписывайся: @maksim_python
👎11😁3🔥1
constexpr-парсинг enum в C++: без простыни из if-else
Строки из конфига, CLI и env-переменных почти всегда нужно переводить в enum. И очень быстро код зарастает однотипными ветками
Намного удобнее держать все соответствия в одной таблице. Тогда из неё можно сделать и парсинг строки в enum, и обратное преобразование enum в строку.
Сначала объявим сам enum:
Теперь добавим таблицу соответствий. Все значения лежат в одном месте, и это сразу упрощает поддержку.
После этого можно написать
Если строка неизвестна, вернём пустой результат. Это безопаснее, чем молча подставлять какое-то значение по умолчанию.
Из той же таблицы легко сделать обратное преобразование. Это удобно, когда нужно писать enum в логах, сообщениях об ошибках или конфиге.
Если значение не найдено, вернём запасной вариант.
Использование получается простым и читаемым:
Один mapping в одном месте убирает дублирование, сокращает код и делает добавление новых enum-значений намного спокойнее.
🔥 Один mapping лучше десятка
📣 C++ Ready | #практика
Строки из конфига, CLI и env-переменных почти всегда нужно переводить в enum. И очень быстро код зарастает однотипными ветками
if (s == "...").Намного удобнее держать все соответствия в одной таблице. Тогда из неё можно сделать и парсинг строки в enum, и обратное преобразование enum в строку.
Сначала объявим сам enum:
enum class log_level {
trace,
debug,
info,
error
};Теперь добавим таблицу соответствий. Все значения лежат в одном месте, и это сразу упрощает поддержку.
using namespace std::literals;
constexpr std::array mappings{
std::pair{"trace"sv, log_level::trace},
std::pair{"debug"sv, log_level::debug},
std::pair{"info"sv, log_level::info},
std::pair{"error"sv, log_level::error},
};
После этого можно написать
constexpr-парсер. Он просто проходит по таблице и ищет совпадение.constexpr std::optional<log_level>
parse_log_level(std::string_view s) {
for (auto [name, value] : mappings) {
if (name == s)
return value;
}
Если строка неизвестна, вернём пустой результат. Это безопаснее, чем молча подставлять какое-то значение по умолчанию.
return std::nullopt;
}
Из той же таблицы легко сделать обратное преобразование. Это удобно, когда нужно писать enum в логах, сообщениях об ошибках или конфиге.
constexpr std::string_view
to_string(log_level lvl) {
for (auto [name, value] : mappings) {
if (value == lvl)
return name;
}
Если значение не найдено, вернём запасной вариант.
return "unknown";
}
Использование получается простым и читаемым:
auto lvl = parse_log_level("debug")
.value_or(log_level::info);
std::cout << to_string(lvl) << '\n';Один mapping в одном месте убирает дублирование, сокращает код и делает добавление новых enum-значений намного спокойнее.
if-else веток.Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍5🔥3