Генератор с состоянием Python: реализуйте переключатель с гистерезисом

Напишите решение на Python и проверьте его на странице.

Другие упражнения по этой теме: Генератор send в Python: задачи на состояние и управление потоком.

Компаратор гистерезиса

Терморегулятор промышленной печи управляет нагревателем с помощью гистерезиса, защищающего систему от постоянных переключений из-за колебаний показаний. Изначально нагреватель выключен. Его статус меняется только при выходе за пределы рабочего диапазона: если температура падает строго ниже нижнего порога, включается нагрев, а когда поднимается строго выше верхнего — нагреватель выключается. Любые значения внутри диапазона, а также равенство пороговым отметкам сохраняют прежнее состояние системы без изменений.

В процессе работы компаратор может принимать калибровочные сообщения с новой парой температурных границ. Новые пороги вступают в силу немедленно, если нижняя граница строго меньше верхней; при этом текущее состояние нагревателя сразу не пересчитывается и остаётся прежним. Если же предложенная нижняя граница оказалась больше либо равна верхней, калибровка отклоняется с сигналом ошибки, а регулятор продолжает работу со старыми порогами.

Реализуйте сопрограмму компаратора, которая сообщает актуальное состояние нагревателя в ответ на замеры температуры и подтверждает либо отклоняет применение порогов при получении калибровочных данных.

Что уже дано

В заготовке объявлена функция-генератор hysteresis_switch(lower, upper), тело которой вам предстоит написать. Во время исполнения решения доступна вспомогательная функция observe_coroutine_calls(generators, actions), используемая проверяющей системой для контроля состояния сопрограмм.

Что нужно сделать

Реализуйте функцию-сопрограмму hysteresis_switch(lower, upper).

Функция принимает начальные числовые пороги lower и upper (вещественные или целые числа в диапазоне от -1 000 000 до 1 000 000, гарантируется lower < upper). Функция возвращает нативный неинициализированный генератор (сопрограмму).

Правила работы сопрограммы:

  • Инициализация: первый вызов next() или send(None) запускает генератор и возвращает None. Автоматической инициализации внутри функции быть не должно.
  • Начальное состояние нагревателя — False (выключен).
  • Числовые измерения: если через метод .send(temperature) передано число (в диапазоне от -1 000 000 до 1 000 000):
  • при значении строго меньше текущего lower нагреватель включается (True);
  • при значении строго больше текущего upper нагреватель выключается (False);
  • при значении внутри диапазона или равном любой из границ сохраняется текущее состояние нагревателя;
  • генератор возвращает текущее состояние нагревателя в виде булева значения (True или False).
  • Сообщения калибровки: передаются в виде кортежа ("calibrate", new_lower, new_upper) с числовыми порогами из того же диапазона:
  • если new_lower < new_upper, калибровка считается успешной: пороги немедленно обновляются, генератор возвращает True. Текущее состояние нагревателя при этом не меняется и заново по предыдущим замерам не пересчитывается;
  • если new_lower >= new_upper, калибровка отклоняется: сохраняются прежние пороги и текущее состояние нагревателя, генератор возвращает False и продолжает обычную работу без возбуждения исключений.
  • Каждая созданная сопрограмма независима от других и корректно поддерживает штатное завершение методом .close() без выдачи дополнительных значений.
  • В тестах на каждую сопрограмму приходится от 0 до 1000 операций, а количество одновременно работающих сопрограмм составляет от 1 до 3.

Ввод и вывод

Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля функцию верхнего уровня hysteresis_switch и вызывает её с проверочными аргументами.

Пример использования

control = hysteresis_switch(10, 20)
print(next(control))
print(control.send(9))
print(control.send(20))
print(control.send(21))
print(control.send(('calibrate', 30, 40)))
print(control.send(35))
print(control.send(('calibrate', 40, 30)))
print(control.send(29))
control.close()

Вывод:

None
True
True
False
True
False
False
True
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи