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.
67 lines
3.4 KiB
67 lines
3.4 KiB
"""Модуль, содержащий функции для чистки интервалов. |
|
Под 'чисткой' подразумевается: |
|
- удаление меньших интервалов, полностью входящих в большие (поглощение) |
|
- расширение пересекающихся интервалов (сумма интервалов) |
|
""" |
|
|
|
|
|
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
|
|
|