Итераторы Python: сборка кадра из двух потоков без лишнего чтения

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

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

Атомарные кадры телеметрии

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

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

Постройте ленивый генератор кадров, который порционно связывает оба источника и обеспечивает выдачу только полностью закрытых пакетов.

Что уже дано

В редакторе представлена заготовка функции atomic_frames(data, markers, frame_size) с заглушкой NotImplementedError. Готовые вспомогательные фабрики зондов доступны при тестировании, реализовывать их самостоятельно не требуется.

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

Реализуйте функцию atomic_frames(data, markers, frame_size).

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

  • data — произвольный независимый итератор объектов полезных данных;
  • markers — произвольный независимый итератор сервисных маркеров;
  • frame_size — положительное целое число от 1 до 1000 (включая пользовательские подклассы int), определяющее размер блока данных .

Функция должна возвращать нативный ленивый генератор исходных объектов.

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

  • Входные итераторы содержат от 0 до 10000 элементов каждый, а потребитель запрашивает от 0 до 10000 значений. Чтение из источников выполняется строго по требованию потребителя.
  • Создание генератора не должно считывать ни одного элемента из data или markers.
  • Для каждого кадра генератор сначала вычитывает из data ровно frame_size элементов, и только после успешного набора полной порции запрашивает ровно один элемент из markers.
  • Элементы текущего кадра выдаются потребителю только после того, как маркер успешно получен: сначала frame_size объектов данных в исходном порядке, затем полученный маркер. Все объекты должны сохранять свою идентичность.
  • Пока генератор не выдал все элементы текущего сформированного кадра, чтение элементов следующего кадра из входных потоков запрещено.
  • Если поток data исчерпался до того, как набрались frame_size элементов (включая ситуацию, когда данных не осталось вовсе), неполный остаток отбрасывается, маркер для него не запрашивается, а генерация завершается.
  • Если порция из frame_size элементов успешно набрана, но при попытке получить маркер поток markers оказался исчерпан, эти собранные данные отбрасываются и не выдаются.
  • Управление временем жизни или закрытием переданных итераторов в функции не требуется.

Ввод и вывод

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

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

print(list(atomic_frames(iter([1, 2, 3, 4, 5]), iter(['A', 'B']), 2)))

Вывод:

[1, 2, 'A', 3, 4, 'B']
РешениеPython

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

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

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