Генератор Python: ограничение скорости обработки команд
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Генератор send в Python: задачи на состояние и управление потоком.
Дозатор импульсов микрошагового привода
Контроллер микрошагового привода принимает команды перемещения, но двигатель не может безопасно отработать резкий рывок за один такт. Механика ограничена текущим пределом скорости, поэтому поступающие запросы необходимо сглаживать, выдавая импульсы дозированными частями. Эту задачу решает сопрограмма, которая начинает работу с положительным скоростным лимитом и ведёт внутренний баланс невыполненных шагов, изначально равный нулю.
Когда на вход поступает целое число шагов, оно добавляется к накопленному долгу. Затем генератор срезает максимально возможную величину, не превышающую по модулю активный предел скорости, списывает её из баланса и возвращает как реальный шаг мотора со своим знаком, а оставшуюся часть сохраняет на следующие такты.
Внешняя система может в любой момент прислать калибровочную команду с новым ограничением скорости. В этом случае лимит сразу обновляется без движения мотора, а сопрограмма сообщает в ответ текущую абсолютную величину оставшегося долга.
Реализуйте сопрограмму дозирования импульсов, которая распределяет нагрузку в рамках установленного скоростного лимита и подтверждает остаток долга при каждой калибровке.
Что уже дано
В редакторе представлена заготовка функции-генератора rate_debt(speed_limit) с заглушкой, которую предстоит реализовать.
Вспомогательные средства тестирования и проверки состояния генераторов уже доступны во время исполнения решения, реализовывать их заново не требуется.
Что нужно сделать
Реализуйте функцию-генератор rate_debt(speed_limit).
Функция принимает начальное положительное целочисленное ограничение скорости speed_limit (в диапазоне от 1 до 1 000 000) и возвращает неинициализированный генератор.
Правила работы генератора:
- Первый запуск через
next(generator)(илиgenerator.send(None)) приводит сопрограмму в состояние готовности и отдаёт0. - После прайминга генератор через метод
.send(message)принимает команды двух видов: целочисленные запросы шагов или кортеж калибровки. - При получении целого числа (от -1 000 000 до 1 000 000, включая совместимые целочисленные подклассы, такие как булевы значения):
- Значение добавляется к общему знаковому долгу (изначально долг равен
0). - Генератор вычисляет и отдаёт наружу максимально возможный шаг того же знака, что и текущий долг, модуль которого не превышает ни текущий лимит скорости, ни величину доступного долга.
- Только этот выданный шаг вычитается из накопленного долга, а остаток сохраняется на следующие вызовы.
- Запрос
0продолжает погашать ранее накопленный долг в пределах текущего лимита; запрос противоположного знака уменьшает баланс долга или может сменить его знак на противоположный.
- При получении кортежа вида
("calibrate", positive_new_limit)(или совместимого типа кортежа со строковым тегом и положительным целым лимитом):
- Ограничение скорости немедленно заменяется на
positive_new_limitи начинает действовать со следующей числовой команды. - Мотор не выполняет шагов, а баланс долга не изменяется.
- Генератор возвращает абсолютную величину текущего оставшегося долга (
abs(debt)).
- Каждый созданный генератор обладает независимым внутренним состоянием и штатно закрывается при вызове метода
.close(). Дробные округления или преобразования к числам с плавающей точкой не допускаются.
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля функцию верхнего уровня rate_debt и вызывает её с проверочными аргументами.
Пример использования
motor = rate_debt(3)
next(motor)
print(motor.send(8))
print(motor.send(0))
print(motor.send(-7))
print(motor.send(('calibrate', 1)))
print(motor.send(0))
motor.close()
Вывод:
3 3 -3 2 -1
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Send() до первого next(): ошибка запуска генератора Python
- Генератор с send() на Python: накопление порций и смена лимита
- Учёт трафика через генератор Python: сумма и динамический лимит
- Генератор Python: фильтрация выбросов с изменяемым порогом
- Генератор Python: центрирование данных в скользящем окне
- Генератор с состоянием Python: реализуйте переключатель с гистерезисом
