Если бы я понял это правильно, я бы упростил код, введя несколько более простых операций overlap
для вычисления перекрытия между двумя интервалами и duration
для вычисления (абсолютной) продолжительности интервала.
def overlap(interval1, interval2):
interval1 = sorted(interval1)
interval2 = sorted(interval2)
result = (
max([interval1[0], interval2[0]]),
min([interval1[1], interval2[1]]))
if result[0] > result[1]:
return (0, 0)
else:
return result
def duration(interval):
return abs(interval[1] - interval[0])
def efficiency_ratio(inquiry_interval, open_intervals):
assert(all(
duration(overlap(interval1, interval2)) == 0
for interval1, interval2 in itertools.combinations(open_intervals, 2)))
effective_duration = sum([
duration(overlap(inquiry_interval, open_interval))
for open_interval in open_intervals])
return effective_duration / duration(inquiry_interval)
Обратите внимание, что: - код имеет дополнительную логику для работы также для входных интервалов, где максимальная граница находится перед минимальной границей.Выходы всегда имеют формат (min_bound, max_bound)
.- open_intervals
должен быть не перекрывающимся, и в этом смысл дополнительной логики, реализованной внутри assert()
Чтобы проверить, что эта работа для вашего варианта использования, мы могли бы сделать:
print(efficiency_ratio((10, 18), [(10,12), (14, 16)]))
# 0.5
print(efficiency_ratio((10, 12), [(9, 14)]))
# 1.0
print(efficiency_ratio((8, 12), [(0, 10)]))
# 0.5
РЕДАКТИРОВАТЬ: добавлена дополнительная проверка ввода.