Скользящие окна Python: генерация кортежей без загрузки всего потока

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

Другие упражнения по этой теме: Itertools в Python: задачи на комбинации, groupby и ленивые потоки.

Скользящие окна вибромониторинга

Модуль мониторинга промышленного привода непрерывно принимает поток виброакустических замеров и передаёт их в анализатор перегрузок. Чтобы вовремя заметить опасные вибрации, данные группируют в скользящие окна фиксированной ширины со сдвигом ровно на один шаг.

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

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

Что уже дано

В среде выполнения уже определены вспомогательные инструменты для тестирования: WindowSource, make_window_source, observe_overlapping_iterator и observe_overlapping_memory. Реализовывать их заново не требуется: вам нужно написать только саму функцию overlapping_windows.

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

Реализуйте функцию overlapping_windows(source, width).

Функция принимает два аргумента:

  • source — однократный итерируемый объект с конечными числовыми замерами (int или float в диапазоне от -1 000 000 до 1 000 000). Поток может быть потенциально бесконечным, не поддерживает индексацию, вызов len() и перемотку назад;
  • width — целое число от 1 до 128, задающее ширину скользящего окна.

Функция должна вернуть ленивый однократный итератор (например, генератор), выдающий окна в виде неизменяемых кортежей tuple.

Правила формирования и выдачи окон:

  • Вызов overlapping_windows(source, width) не должен вычитывать элементы из source до первого явного запроса очередного элемента у возвращённого итератора.
  • Первое окно формируется из первых width замеров source. Каждое следующее окно сдвигается на один замер: старейший элемент отбрасывается, а в конец добавляется одно новое прочитанное значение с сохранением исходного порядка и повторов.
  • Каждое следующее запрашиваемое окно считывает из source ровно столько данных, сколько требуется для его построения: никаких упреждающих чтений сверх текущего окна производиться не должно.
  • Если поток завершился до того, как набралось полное окно шириной width, неполный хвост отбрасывается, и итератор останавливает работу.
  • Если вызывающий код прекращает запрашивать результаты или запрашивает лишь часть окон, фонового чтения оставшегося потока не происходит.
  • Запрещено материализовать входной поток целиком или хранить неограниченную историю значений. Дополнительный пик потребления памяти при итерации по замерам (за вычетом исходных структур вызывающей стороны) не должен превышать 1 048 576 байт (1 МиБ).

Ввод и вывод

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

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

source = make_window_source([1, 2, 3, 4, 5])
print(list(overlapping_windows(source, 3)))

Вывод:

[(1, 2, 3), (2, 3, 4), (3, 4, 5)]
РешениеPython

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

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

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