Генератор Python: пиковое значение и изменение порога тревоги

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

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

Регистратор пиковых амплитуд

Виброакустический регистратор следит за нагрузками на подшипник и принимает непрерывный поток неотрицательных амплитуд вибрации. За обработку отвечает сопрограмма: она запускается с заданным начальным порогом тревоги и начинает отсчёт с нулевого зафиксированного пика.

При получении очередного замера генератор обновляет накопленный максимум, только если новое значение строго больше текущего пика. В ответ он сообщает кортеж из актуального пика и флага тревоги, который становится истинным, когда этот пик строго превышает действующий порог.

Регистратор также поддерживает команды калибровки. Каждая такая команда передаёт новый порог и признак сброса: если сброс подтверждён, пик обнуляется, а сопрограмма возвращает нулевой максимум вместе с ложным флагом тревоги; если же сброс не требуется, прежний пик сохраняется, а генератор заново оценивает статус тревоги уже при новом пороге.

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

Что уже дано

В редакторе объявлена заготовка функции peak_alarm(threshold). Вспомогательные функции наблюдения, присутствующие в среде исполнения, доступны при тестировании, реализовывать их самостоятельно не нужно.

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

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

Функция принимает начальный порог threshold — конечное число int или float (включая числовые подклассы) в диапазоне от -1 000 000 до 1 000 000 — и возвращает нативный неинициализированный генератор.

Правила работы генератора:

  • Инициализация: первый вызов next(g) или g.send(None) выполняет запуск сопрограммы (прайминг) и возвращает None. Сама функция-фабрика не должна инициализировать генератор заранее.
  • Начальное состояние: пик начинает отсчёт строго с 0. Каждая сопрограмма хранит своё независимое состояние; скользящих окон или гистерезиса нет.
  • Приём замеров: через g.send(reading) передаётся неотрицательное конечное числовое значение reading (типа int или float, включая подклассы чисел) не больше 1 000 000. Накопленный пик обновляется, только если reading строго больше текущего максимума. В ответ возвращается пара вида (peak, alarm), где peak — актуальный максимум, а булев флаг alarm равен True, если peak > threshold, иначе False.
  • Калибровка: через g.send(('calibrate', new_threshold, reset)) передаётся кортеж из трёх элементов, где new_threshold — число в тех же границах от -1 000 000 до 1 000 000, а reset — булево значение (bool). Калибровка заменяет действующий порог на new_threshold:
  • если reset равен False, накопленный пик сохраняется, статус тревоги пересчитывается по новому порогу (peak > new_threshold), а генератор возвращает пару (peak, alarm);
  • если reset равен True, накопленный пик сбрасывается в 0, а генератор возвращает пару (0, False), даже если новый порог отрицателен.
  • Стандартное поведение нативных методов close() и throw() сохраняется.

Один генератор может обработать от 0 до 1000 сообщений. Тестирующая система может параллельно запускать от 1 до 3 независимых генераторов с чередованием запросов к ним.

Ввод и вывод

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

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

g = peak_alarm(5)
print(next(g))
print(g.send(7))
print(g.send(('calibrate', 8, False)))
print(g.send(('calibrate', 3, True)))
g.close()

Вывод:

None
(7, True)
(7, False)
(0, False)
РешениеPython

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

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

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