advent_of_code_2024/day5/run.py

102 lines
2.5 KiB
Python

from typing import Callable, List
EXAMPLE = """
47|53
97|13
97|61
97|47
75|29
61|13
75|53
29|13
97|29
53|29
61|53
97|53
61|29
47|13
75|47
97|75
47|61
75|61
47|29
75|13
53|13
75,47,61,53,29
97,61,53,29,13
75,29,13
75,97,47,61,53
61,13,29
97,13,75,29,47
"""
class CheckManual:
def __init__(self, input: str) -> None:
self._input = input[1:]
sep = self._input.splitlines().index("")
self.rules = self.parse_rules(self._input.splitlines()[:sep])
self.pages = [val.split(",") for val in self._input.splitlines()[sep + 1 :]]
self.validity = self.check_page_order()
def __str__(self) -> str:
return f"Part1: {self._part1}\nPart2: {self._part2}"
@property
def _part1(self) -> int:
return sum(
[
int(val[len(val) // 2])
for val, check in zip(self.pages, self.validity)
if check
]
)
@property
def _part2(self) -> int:
return sum([int(val[len(val) // 2]) for val in self.fix_page_order()])
def parse_rules(
self, rules: List[str], sep: str = "|"
) -> List[Callable[[str], bool]]:
def make_rule(rule: str, sep: str = "|") -> Callable[[str], bool]:
left, right = rule.split(sep)
def check(pages: List[str]) -> bool:
try:
return pages.index(left) < pages.index(right)
except ValueError:
return True
return check
return [(rule, make_rule(rule)) for rule in rules]
def check_page_order(self) -> List[bool]:
return [all([rule[1](line) for rule in self.rules]) for line in self.pages]
def fix_page_order(self) -> List[str]:
to_fix = [page for page, check in zip(self.pages, self.validity) if not check]
fixed = []
for pages in to_fix:
while not all([rule[1](pages) for rule in self.rules]):
for rule in self.rules:
if not rule[1](pages):
break
r1, r2 = rule[0].split("|")
i1, i2 = pages.index(r1), pages.index(r2)
pages[i1], pages[i2] = pages[i2], pages[i1]
fixed.append(pages)
return fixed
if __name__ == "__main__":
example = CheckManual(EXAMPLE)
print(example)
assert example._part1 == 143
assert example._part2 == 123
with open("input.txt", "r") as f:
main = CheckManual(f.read())
print(main)