# -*- coding: utf-8 -*- from abc import ABC from dataclasses import dataclass from typing import Tuple, Iterator, Any from aoc import BaseAssignment @dataclass class Section: start: int end: int def fully_contains(self, other: "Section") -> bool: return self.start <= other.start and self.end >= other.end def overlaps(self, other: "Section") -> bool: return ( self.start <= other.start <= self.end or self.start <= other.end <= self.end or self.fully_contains(other) or other.fully_contains(self) ) class Assignment(BaseAssignment, ABC): def parse_section(self, section: str) -> Section: start, end = section.split("-") return Section( start=int(start), end=int(end), ) def parse_sections(self, sections: str) -> Tuple[Section, Section]: section_1, section_2 = sections.split(",") return (self.parse_section(section_1), self.parse_section(section_2)) def check(self, section_1: Section, section_2: Section) -> bool: raise NotImplementedError() def run(self, input: Iterator) -> Any: overlapping = [] for sections in input: section_1, section_2 = self.parse_sections(sections) if self.check(section_1, section_2): overlapping.append((section_1, section_2)) return len(overlapping) class AssignmentOne(Assignment): example_result = 2 def check(self, section_1: Section, section_2: Section) -> bool: return section_1.fully_contains(section_2) or section_2.fully_contains( section_1 ) class AssignmentTwo(Assignment): example_result = 4 def check(self, section_1: Section, section_2: Section) -> bool: return section_1.overlaps(section_2)