#!/usr/bin/env python3 import re def yield_spans(gs: dict): for g in gs.values(): yield g[:2] yield g[2:] def in_spans(x, spans): for span in spans: if span[0] <= x <= span[1]: return True return False lines = (x.strip() for x in open("input.txt")) REGEX_RANGES = re.compile(r"^([a-z ]+): (\d+)-(\d+) or (\d+)-(\d+)$") groups = {} your = () nearby = [] read_step = 0 for line in lines: if read_step == 0: if line == "": read_step = 1 continue match = REGEX_RANGES.match(line) groups[match[1]] = list(map(int, match.groups()[1:])) elif read_step == 1: if line == "": read_step = 2 continue if line.startswith("your"): continue your = list(map(int, line.split(','))) elif read_step == 2: if line.startswith("nearby"): continue nearby.append(list(map(int, line.split(',')))) valid_spans = [] for span in yield_spans(groups): start_idx = next((i for i, v in enumerate(valid_spans) if span[0] <= v[1]), len(valid_spans)) end_idx = next((len(valid_spans)-i for i, v in enumerate(valid_spans[::-1]) if span[1] >= v[0]), 0) for idx in range(start_idx, end_idx): popped = valid_spans.pop(start_idx) span = (min(popped[0], span[0]), max(popped[1], span[1])) valid_spans.insert(start_idx, tuple(span)) print("Valid Spans:", valid_spans) invalid_sum = sum(x for n in nearby for x in n if not in_spans(x, valid_spans)) print(invalid_sum)