def get_sections_boundaries(sections: str) -> tuple[int, int]: split = sections.split("-") return int(split[0]), int(split[1]) def parse_input(lines: list[str]) -> list[tuple[tuple[int, int], tuple[int, int]]]: output = [] for line in lines: stripped = line.strip() if not stripped.isspace(): split = stripped.split(",") output.append( (get_sections_boundaries(split[0]), get_sections_boundaries(split[1])) ) return output def contained(sections1: tuple[int, int], sections2: tuple[int, int]) -> bool: section1_contains_section2 = ( sections1[0] <= sections2[0] and sections1[1] >= sections2[1] ) section2_contains_section1 = ( sections2[0] <= sections1[0] and sections2[1] >= sections1[1] ) return section1_contains_section2 or section2_contains_section1 def overlaps(sections1: tuple[int, int], sections2: tuple[int, int]) -> bool: sections1_overlaps_section2 = sections2[0] <= sections1[1] <= sections2[1] sections2_overlaps_section1 = sections1[0] <= sections2[1] <= sections1[1] return sections1_overlaps_section2 or sections2_overlaps_section1 def part1(lines: list[str]) -> int: return sum(contained(*sections) for sections in parse_input(lines)) def part2(lines: list[str]) -> int: return sum(overlaps(*sections) for sections in parse_input(lines)) if __name__ == "__main__": with open("input.txt") as file: contents = file.readlines() print(f"Solution for part 1 is: {part1(contents)}") print(f"Solution for part 2 is: {part2(contents)}")