import aocd import math def parse(data): return sorted(tuple(map(int, r.split('-'))) for r in data.split('\n\n')[0].strip().split('\n')) def merge_overlapping(ranges): current_min = None current_max = -math.inf for new_min, new_max in ranges: if new_min > current_max: # Previous range is successfully merged if current_min is not None: # Previous range actually does exist yield (current_min, current_max) current_min = new_min current_max = new_max else: # Need to merge current range into previous # Use max() here to prevent (1, 10), (3, 7) from resolving to (1, 7), e.g. current_max = max(new_max, current_max) # Get the range that gets missed at the end yield (current_min, current_max) def range_length(low, high): return high - low + 1 def main(data): ranges = parse(data) return sum(range_length(*r) for r in merge_overlapping(ranges)) if __name__ == '__main__': solution = main(aocd.get_data(day=5, year=2025)) print(solution) aocd.submit(solution, part='b', day=5, year=2025)