You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
3.4 KiB
68 lines
3.4 KiB
3 years ago
|
"""Модуль, содержащий функции для чистки интервалов.
|
||
|
Под 'чисткой' подразумевается:
|
||
|
- удаление меньших интервалов, полностью входящих в большие (поглощение)
|
||
|
- расширение пересекающихся интервалов (сумма интервалов)
|
||
|
"""
|
||
|
|
||
|
|
||
|
def absorb_small_included_intervals(intervals: list) -> list:
|
||
|
"""Возвращает список интервалов без вложенных интервалов.
|
||
|
|
||
|
Вложенный интервал - интервал меньшего размера, полностью входящий
|
||
|
в больший.
|
||
|
|
||
|
Стоит учитывать, что функция работает только если интервалы
|
||
|
совпадают по началу или концу, если интервалы входят друг в друга
|
||
|
частично (пересекаются) -- здесь мы их не обрабатываем.
|
||
|
|
||
|
"""
|
||
|
# запоминаем самый перевый интервал, раньше него интервалов не
|
||
|
# будет. Если текущий интервал входит в последний добавленный
|
||
|
# нами, т.е. он заканчивается раньше, чем тот который мы добавили,
|
||
|
# то мы его не добавляем в результат, так как он вложенный
|
||
|
big_intervals = [intervals[0]]
|
||
|
for i in range(1, len(intervals)):
|
||
|
if big_intervals[-1][1] >= intervals[i][1]:
|
||
|
continue
|
||
|
else:
|
||
|
big_intervals.append(intervals[i])
|
||
|
|
||
|
return big_intervals
|
||
|
|
||
|
|
||
|
def merge_intersected_intervals(intervals) -> list:
|
||
|
"""Возвращает расширенные интервалы.
|
||
|
|
||
|
Расширенные интервалы -- это интервалы, состоящие из суммы
|
||
|
частично пересекающихся интервалов."""
|
||
|
|
||
|
# запоминаем самый первый интервал. Проходимся по списку, и если
|
||
|
# начало текущего интервала меньше, чем конец последнего
|
||
|
# добавленного, то мы расширяем записанный интервал до конца
|
||
|
# текущего. В противном случае просто добавляем текущий интервал в
|
||
|
# итоговый список интервалов.
|
||
|
res = [intervals[0]]
|
||
|
for i in range(1, len(intervals)):
|
||
|
if res[-1][1] >= intervals[i][0]:
|
||
|
res[-1][1] = max(intervals[i][1], res[-1][1])
|
||
|
else:
|
||
|
res.append(intervals[i])
|
||
|
|
||
|
return res
|
||
|
|
||
|
|
||
|
def normilize_intervals(intervals) -> list:
|
||
|
"""Разбивает полученный список на пары, расширяет интервалы,
|
||
|
убирает вложенные интервалы."""
|
||
|
|
||
|
# из списка [1,2,3,4] формируем [[1,2], [3,4]]
|
||
|
intervals_ = [intervals[i : i + 2] for i in range(0, len(intervals), 2)]
|
||
|
|
||
|
# убираем вложенные интервалы
|
||
|
n_intervals = absorb_small_included_intervals(intervals_)
|
||
|
|
||
|
# расширяем пересекающиеся интервалы
|
||
|
result = merge_intersected_intervals(n_intervals)
|
||
|
|
||
|
return result
|