Merging line segments

Problem: Given a collection of intervals, write a function that returns the total non-overlapping range covered.

Input: [(0, 15), (11, 17), (10, 20), (45, 50)]
Output: [(0, 20), (45, 50)]

Visualization

(0,15) ---------------
(11,17)           -------
(10,20)          -------------------
(45,50)                                                   -----
                                                
result  ----------------------------                      -----
       0                          20                     45   50

When presented with this problem I wrote the following to solve it

My Solution

def find_overlaps(segments: list[tuple[int, int]]) -> list[tuple[int, int]]:
    simplified_segments = []
    for segment in segments:
        merged = False
        start, end = segment[0], segment[1]
        for i, current in enumerate(simplified_segments):
            current_start, current_end = current[0], current[1]
            if max(start, current_start) <= min(end, current_end):
                overlap = min(end, current_end) - max(start, current_start)
                simplified_segments[i] = (min(start, current_start), max(end, current_end))
                merged = True
                break
        if not merged:
            simplified_segments.append(segment)
    return simplified_segments

The core part is the check for overlapping done by the line max(start, current_start) <= min(end, current_end) Here I check for the start pair is before the lowest end point and if so then there is an overlap as in given two segments

  • Segment 1: (0, 5)
  • Segment 2: (4, 10)

That means max(0, 4) = 4 and min (5,10) = 5 and therefore Segment 2 starts before the end of Segment 1 and so the segment bounds can be combined. The amount of overlap between the two segments can be calculate with overlap = min(end, current_end) - max(start, current_start) using the example segments above that would be min(5, 10) = 5 - max(0, 4) = 4 giving an overlap of 1

Comparing with large language model (LLM) generated code which gave this back

LLM Solution

def merge_intervals(intervals: list[tuple[int, int]]) -> list[tuple[int, int]]:
    # Sort intervals by their starting point
    intervals.sort(key=lambda x: x[0])
    merged = []

    for start, end in intervals:
        if not merged or merged[-1][1] < start:
            # No overlap, add the interval
            merged.append((start, end))
        else:
            # Overlap, merge the intervals
            merged[-1] = (merged[-1][0], max(merged[-1][1], end))

    return merged

There is a sort of the elements to start with which I didn't do and the in place movement of is a bit odd to me, but it works. Working it out it seems the dependency on the sort is the key difference between what I wrote as I do in place range expansion with the inner for loop and the generated code assumes sorted start points so it can slowly build the intervals in order. Interesting approach I am curious where this was copied from though because missing some context here obviously.