commit dac96f74c8a89a6eeb12436d5dceb09d53536115 Author: Dmitry Belan Date: Tue Jul 14 12:46:00 2026 +0300 Added tasks for the control work diff --git a/OOP/task/1/TASK.md b/OOP/task/1/TASK.md new file mode 100644 index 0000000..dab7f38 --- /dev/null +++ b/OOP/task/1/TASK.md @@ -0,0 +1,5 @@ +**Постановка:** Напишите код из 3 взаимосвязанных функций для обработки вложенных структур данных. +**Задание:** +1. `is_numeric(val)` — проверяет, является ли значение числом. +2. `recursive_find_max(data)` — рекурсивно проходит по вложенным спискам и находит максимальное число. +3. `check_and_print(data)` — вызывает поиск максимума; если максимум больше 100, выводит "Найдено критическое значение", иначе "Данные в норме". \ No newline at end of file diff --git a/OOP/task/2/TASK.md b/OOP/task/2/TASK.md new file mode 100644 index 0000000..498bc0a --- /dev/null +++ b/OOP/task/2/TASK.md @@ -0,0 +1,5 @@ +**Постановка:** Напишите 3 функции для анализа текста. +**Задание:** +1. `get_valid_input()` — через `while` запрашивает ввод текста. Если ввод пустой или содержит цифры, выбрасывает `ValueError` и просит ввести снова. +2. `calculate_frequency(text)` — возвращает словарь с количеством повторений каждого слова. +3. `sort_and_display(freq_dict)` — сортирует словарь по значению и выводит топ-3 самых частых слов. \ No newline at end of file diff --git a/OOP/task/3/TASK.md b/OOP/task/3/TASK.md new file mode 100644 index 0000000..1cb43f7 --- /dev/null +++ b/OOP/task/3/TASK.md @@ -0,0 +1,5 @@ +**Постановка:** Напишите 3 функции для обработки числовых последовательностей. +**Задание:** +1. `is_prime(n)` — проверяет, является ли число простым. +2. `get_numbers(start, end)` — генерирует список чисел от `start` до `end`. +3. `filter_primes(numbers)` — возвращает список только тех чисел, которые прошли проверку `is_prime`. \ No newline at end of file diff --git a/OOP/task/4/TASK.md b/OOP/task/4/TASK.md new file mode 100644 index 0000000..6e76188 --- /dev/null +++ b/OOP/task/4/TASK.md @@ -0,0 +1,5 @@ +**Постановка:** Моделирование системы жизнеобеспечения. +**Задание:** +1. Класс `Compartment`: параметры `name`, `oxygen_level` (по умолчанию 50). Метод `add_oxygen(amount)` (не выше 100). +2. Класс `LifeSupport`: содержит список отсеков. Метод `boost_all()` пополняет кислород во всех отсеках. +3. Класс `Engineer`: метод `check_system(support_system)` выводит средний уровень кислорода. \ No newline at end of file diff --git a/OOP/task/5/TASK.md b/OOP/task/5/TASK.md new file mode 100644 index 0000000..dabd8d9 --- /dev/null +++ b/OOP/task/5/TASK.md @@ -0,0 +1,9 @@ +**Постановка:** Есть Книга, Абонемент и Библиотекарь. +**Задание:** +1. Класс `Book`: параметры `title`, `is_borrowed` (по умолчанию `False`). +2. Класс `Library`: содержит список объектов `Book`. Метод `find_book(title)` и `lend_book(title)`. +3. Класс `Librarian`: имеет имя. Метод `manage_checkout(library, title)` меняет статус книги на "выдана" и выводит подтверждение. +**Тесты:** +1. Создайте библиотеку с 3 книгами. +2. Создайте библиотекаря. +3. Выдайте одну книгу через метод библиотекаря и проверьте изменение статуса. \ No newline at end of file diff --git a/OOP/task/6/TASK.md b/OOP/task/6/TASK.md new file mode 100644 index 0000000..04487b7 --- /dev/null +++ b/OOP/task/6/TASK.md @@ -0,0 +1,9 @@ +**Постановка:** Есть Машина, Гараж и Механик. +**Задание:** +1. Класс `Car`: параметры `model`, `mileage`, `is_service_needed` (булево). +2. Класс `Garage`: содержит список объектов `Car`. Метод `get_needs_service()` возвращает список машин с `is_service_needed = True`. +3. Класс `Mechanic`: имеет метод `service_car(car)`. При обслуживании `mileage` не меняется, а `is_service_needed` становится `False`. +**Тесты:** +1. Создайте гараж с 3 машинами (у 2-х установите `is_service_needed = True`). +2. Создайте механика. +3. Отфильтруйте машины, требующие ремонта, и обслужите их через механика. \ No newline at end of file diff --git a/OOP/task/7/TASK.md b/OOP/task/7/TASK.md new file mode 100644 index 0000000..e3df38e --- /dev/null +++ b/OOP/task/7/TASK.md @@ -0,0 +1,52 @@ +Ограничение по времени: 3.0 с +Ограничение по памяти: 512 МБ + +Год 2142. Межзвездная колония на планете Эпсилон-9 столкнулась с невидимой смертью. Внешне безобидная флора планеты скрывает фатальную угрозу: питательный, спасающий от голода «Звездный Корень» и парализующая нервную систему «Теневая Лоза» визуально абсолютно неразличимы. Их выдают только биоэлектрические поля, которые сканируют наши харвестеры. + +До вчерашнего дня наш Центральный ИИ «Тензор-Оракул» успешно классифицировал растения. Но аномальная вспышка на местной звезде сожгла серверные стойки. Библиотеки машинного обучения расплавились в цифровом небытии. Остался только аварийный терминал жизнеобеспечения. Он принимает исключительно базовый, первобытный диалект языка Python. Использовать оператор `import` категорически запрещено — модулей просто не существует. Голод неминуем. Склады забиты смертельно опасным неклассифицированным урожаем. + +Командор колонии Лира врывается в ваш инженерный отсек. В её руках дымящийся кристалл памяти. + +— Инженер! — кричит она, смахивая пепел с терминала. — Я знаю, ты привык поднимать надежный бэкенд и обучать сложные модели, но сейчас от твоих навыков зависят наши жизни! Я вытащила из мертвых архивов концепты древнего алгоритма K-Ближайших Соседей. Мы должны воссоздать его с нуля, и нам нужна строгая архитектура, чтобы система не рухнула. Будем писать объектно-ориентированно. Слушай меня внимательно, я зачитаю спецификацию протокола прямо с поврежденных секторов, а ты переноси это в код! + +Лира подключает кристалл к вашему монитору, и аварийное освещение окрашивает отсек в красный цвет. + +— Разделим логику выживания на модули, — диктует Командор, глядя на бегущие строки. — Сначала создай класс `DataProcessor`. Харвестеры присылают нам сплошной текстовый мусор. Напиши в нем метод `parse_sensor_data(self, record)`. Он должен принимать сырую строку, где числа и класс разделены запятыми, и возвращать кортеж. Первым элементом в нем пойдет список чисел с плавающей точкой — сырые признаки. Вторым — строка класса растения. + +Она нервно стучит по экрану: +— Данные с сенсоров скачут! Чтобы алгоритм не сошел с ума от разницы в масштабах измерений, нужна калибровка. Добавь метод `calculate_statistics(self, dataset)`. Прогони через него размеченные данные и вычисли для каждого признака среднее арифметическое и стандартное отклонение. Верни это как список словарей с ключами `"mean"` и `"std"`. И помни, корень придется извлекать возведением в степень `0.5`, математических модулей у нас нет! + +— Как только получим статистическую базу, — продолжает Лира, — пиши метод `normalize_features(self, features, stats)`. Каждый сырой признак растения нужно очистить от шума, вычтя среднее и разделив на стандартное отклонение. Верни новый список идеальных, нормализованных чисел. + +Свет в отсеке мигает. Система охлаждения воет на пределе возможностей. + +— Теперь архитектура самого предсказателя! Создай класс `KNNClassifier`. При инициализации через `__init__(self, k)` он должен принимать и сохранять внутри себя количество соседей `k`. +Затем заложи в него геометрию выживания — метод `euclidean_distance(self, vector_a, vector_b)`. Он берет два нормализованных списка чисел и вычисляет дистанцию между ними в многомерном пространстве, возвращая одно число с плавающей точкой. + +Лира выводит на экран голограмму базы данных: +— Систему нужно обучить. Напиши метод `fit(self, train_features, train_labels)`, который просто сохранит нормализованную обучающую выборку и её классы внутри объекта. А чтобы найти сородичей, добавь метод `find_k_nearest(self, test_point)`. Он должен прочесать сохраненную базу `train_features` и найти `k` самых близких соседей для неизвестного растения, вернув список их классов-строк. + +— Но соседи могут расходиться во мнениях, — Лира хмурится. — Нам нужна логика большинства. Метод `majority_vote(self, neighbors)` примет этот список классов и вернет тот, который встречается чаще всего. Если будет ничья — возвращай любой из лидирующих классов. + +Она тяжело вздыхает, опираясь на стол: +— Оберни этот поиск и голосование в единый боевой интерфейс `predict_class(self, test_point)`. Этот метод примет одно неизвестное нормализованное растение и прогонит его через поиск соседей и голосование, чтобы сразу выдать итоговый класс-строку. +А для массовой проверки на архивах добавь метод `calculate_accuracy(self, predictions, true_labels)`. Сравни списки наших предсказаний с истинными классами и верни долю правильных ответов от `0.0` до `1.0`. Цена каждой ошибки — чья-то жизнь. + +Лира кладет руку вам на плечо. В её глазах отражается код аварийного терминала: +— И наконец, Инженер... Великий Синтез. Снаружи классов напиши финальную функцию `run_protocol(train_raw_lines, test_raw_lines, k)`. Она объединит весь пайплайн. Создай экземпляры `DataProcessor` и `KNNClassifier`. Распарси обе выборки. Затем вычисли статистику строго и только по обучающей базе, чтобы не было утечки данных из будущего. Нормализуй обе выборки. Скорми обучающие данные в метод `fit`. Пройдись циклом по тестовым растениям, собирая предсказания через `predict_class`, и рассчитай точность. В самом конце функция должна вернуть словарь с двумя ключами: `"accuracy"` с итоговой точностью и `"predictions"` со списком всех предсказанных классов. + +Терминал призывно мигает пустым курсором. Система охлаждения реактора издает последний предупреждающий гудок. Жизнь Эпсилон-9 зависит от чистоты твоей архитектуры. Приступайте. + +--- + +### Блок тестирования протокола (Чек-лист от Командора) + +Лира выводит на соседний экран строгую последовательность проверки модулей. +— Как только напишешь классы, прогони систему через этот алгоритм запуска. Никаких отклонений! + +1. **Запросите справку из архивов:** Вызовите документацию (`help()`) по классам `DataProcessor` или `KNNClassifier`, чтобы убедиться, что сектора памяти целы и спецификация ясна. +2. **Создайте объекты спасения:** Инициализируйте экземпляры классов `DataProcessor` и `KNNClassifier` (задайте нужное число соседей `k`). +3. **Откалибруйте систему:** Используя объект класса `DataProcessor`, обработайте сырые данные (рассчитайте статистику и нормализуйте базу). +4. **Попробуйте классифицировать:** Попробуйте прогнать через систему неизвестное растение (`predict_class`), чтобы проверить отклик пустой базы. +5. **Завершите обучение:** Если алгоритм еще не готов к бою (выдает ошибку или пустой ответ из-за отсутствия базы), загрузите в него нормализованную обучающую выборку (вызовите метод `fit`). +6. **Соберите "урожай":** Как только модель обучена, запустите финальное сканирование тестовой базы, классифицируйте все растения и выведите результат предсказаний. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..fd61a0f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,54 @@ +[tool.commitizen] +name = "cz_conventional_commits" +tag_format = "0" +version_scheme = "semver" +version = "0.0.1" +update_changelog_on_bump = true +major_version_zero = true + +[tool.ruff] +line-length = 80 +exclude = [ + ".git", + "__pycache__", + "build", + "dist", + ".venv", + "venv", + ".mypy_cache", + ".pytest_cache", +] + +[tool.ruff.lint] +select = ["E", "F", "W", "N", "I", "Q", "T20"] +ignore = ["N802", "T201", "T001"] + +[tool.ruff.lint.flake8-quotes] +inline-quotes = "double" +multiline-quotes = "double" +docstring-quotes = "double" + +# Аналог import-order-style = "google" +[tool.ruff.lint.isort] +known-first-party = [] + +[tool.flake8] +max-line-length = 80 +import-order-style = "google" +inline-quotes = "double" +multiline-quotes = "double" +docstring-quotes = "double" + +# Записываем ignore как строку, если их несколько, или список +ignore = "N802,T201,T001" + +exclude = [ + ".git", + "__pycache__", + "build", + "dist", + ".venv", + "venv", + ".mypy_cache", + ".pytest_cache" +] \ No newline at end of file diff --git a/requirements/test.txt b/requirements/test.txt new file mode 100644 index 0000000..e558028 --- /dev/null +++ b/requirements/test.txt @@ -0,0 +1,10 @@ +ruff +commitizen +flake8==7.1.1 +flake8-absolute-import==1.0.0.2 +flake8-commas==4.0.0 +flake8-import-order==0.18.2 +flake8-print==5.0.0 +flake8-quotes==3.4.0 +parameterized==0.9.0 +pep8-naming==0.14.1 \ No newline at end of file