Генератор Python: сравнение показаний двух датчиков с допуском
Напишите решение на Python и проверьте его на странице.
Другие упражнения по этой теме: Генератор send в Python: задачи на состояние и управление потоком.
Арбитраж показаний датчиков
Модуль резервирования следит за показаниями двух независимых телеметрических линий, принимая на каждом шаге пару чисел (val_a, val_b). Чтобы сглаживать мелкие расхождения и отсекать ненадёжные данные, за обработку отвечает специальная сопрограмма. При создании она настраивается на допустимую погрешность и критический лимит подряд идущих сбоев, а внутренний счётчик расхождений изначально равен нулю.
Пока показания согласованы — разность значений в паре по модулю не превышает установленную погрешность, — генератор возвращает их среднее арифметическое, сохраняет его как опорное и обнуляет счётчик расхождений. Если же разность оказывается строго больше допуска, счётчик расхождений тут же увеличивается на единицу. В этой ситуации генератор продолжает отдавать последнее сохранённое опорное среднее (или None, если успешных измерений ещё не было), пока число сбоев подряд не превысит критический лимит. Как только счётчик становится строго больше лимита, генератор вместо числа возвращает метку тревоги 'DESYNC'.
В любой момент модуль может получить калибровочную директиву с новой допустимой погрешностью. При такой настройке порог обновляется, счётчик расхождений принудительно сбрасывается в ноль, а генератор возвращает текущее опорное среднее либо None.
Реализуйте сопрограмму арбитража, которая вычисляет согласованное среднее, отслеживает череду сбоев и обновляет параметры допуска по внешней команде.
Что уже дано
В заготовке объявлена функция-генератор sensor_consensus(tolerance, critical_limit), тело которой вам предстоит реализовать.
Вспомогательные средства тестирования и отслеживания генераторов доступны при запуске тестов и не требуют отдельной реализации.
Что нужно сделать
Реализуйте функцию sensor_consensus(tolerance, critical_limit).
Параметры функции:
tolerance— конечное неотрицательное число (intилиfloatот0до1 000 000), определяющее допустимую погрешность расхождения;critical_limit— целое положительное число (intот1до1000), задающее предельное количество подряд идущих расхождений.
Функция должна возвращать ненастроенный нативный генератор (сопрограмму), находящийся в начальном состоянии до первого шага.
Правила работы сопрограммы:
- После первого вызова
next(generator)(илиgenerator.send(None)) сопрограмма выполняет прайминг, отдаёт вызывающей сторонеNoneи переходит в режим ожидания сообщений. - Сообщения передаются через метод
generator.send(message)(от0до1000сообщений за сессию). Сообщение может быть одного из двух видов:
- Кортеж
(a, b)из двух конечных вещественных или целых чисел по модулю до1 000 000(включая совместимые подклассы чисел и кортежей) — замеры датчиков. - Кортеж
("calibrate", new_tolerance)— команда калибровки, гдеnew_tolerance— новое неотрицательное число допуска.
- Начальное состояние: счётчик подряд идущих сбоев равен
0, опорное среднее отсутствует (None). - Обработка замеров
(a, b): - Если
abs(a - b) <= tolerance, замеры согласованы. Сопрограмма вычисляет и сохраняет новое опорное среднее(a + b) / 2, обнуляет счётчик расхождений и возвращает это среднее значение. - Если
abs(a - b) > tolerance, зафиксирован сбой. Счётчик подряд идущих расхождений увеличивается на1. Если счётчик не превышаетcritical_limit(то естьcount <= critical_limit), генератор возвращает последнее сохранённое опорное среднее (илиNone, если успешных согласований ещё не происходило). Если счётчик становится строго больше лимита (count > critical_limit), генератор возвращает строку'DESYNC'. - Если после череды сбоев или тревоги
'DESYNC'поступает согласованная пара, нормальная работа восстанавливается: вычисляется новое опорное среднее, а счётчик сбоев сбрасывается в0. - Обработка калибровки
("calibrate", new_tolerance): - Значение
toleranceзаменяется наnew_tolerance. - Счётчик подряд идущих сбоев сбрасывается в
0. - Опорное среднее не изменяется и не сбрасывается: генератор возвращает текущее сохранённое среднее (или
None, если его не было). - Завершение работы генератора выполняется вызывающей стороной через метод
generator.close(). - Каждый созданный генератор обладает независимым внутренним состоянием.
Ввод и вывод
Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля функцию верхнего уровня sensor_consensus и вызывает её с проверочными аргументами.
Пример использования
arbiter = sensor_consensus(2, 1)
next(arbiter)
print(arbiter.send((10, 12)))
print(arbiter.send((0, 5)))
print(arbiter.send((0, 5)))
print(arbiter.send(('calibrate', 5)))
print(arbiter.send((0, 5)))
arbiter.close()
Вывод:
11.0 11.0 DESYNC 11.0 2.5
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Связанные задачи
- Send() до первого next(): ошибка запуска генератора Python
- Генератор с send() на Python: накопление порций и смена лимита
- Учёт трафика через генератор Python: сумма и динамический лимит
- Генератор Python: фильтрация выбросов с изменяемым порогом
- Генератор Python: центрирование данных в скользящем окне
- Генератор с состоянием Python: реализуйте переключатель с гистерезисом
