""" Advent of Code 2021 - Day 10 Run with: python puzzles/day10.py inputs/day10.txt """ import pathlib import sys from typing import Dict, List, Tuple from statistics import median class Subsystem: nav_data = None open_chars = ["(", "[", "{", "<"] close_chars = [")", "]", "}", ">"] def __init__(self, inputs: List[str]) -> None: self.nav_data = inputs self.validate() def validate(self) -> None: chunks = {"corrupted": [], "incomplete": [], "complete": []} corrupted_chars = [] incomplete_chunks = [] for line in self.nav_data: corrupted = False opens = [] for char in line: if char in self.open_chars: opens.append(char) continue open_char = self.open_chars[self.close_chars.index(char)] if opens[-1] != open_char: corrupted = True corrupted_chars.append(char) break del opens[-1] # Clear the open bracket if corrupted: chunks["corrupted"].append(line) elif len(opens) != 0: chunks["incomplete"].append(line) incomplete_chunks.append(opens) else: chunks["complete"].append(line) self.chunks = chunks self.corrupted_chars = corrupted_chars self.incomplete_chunks = incomplete_chunks def score_corrupted(self) -> int: scores = {")": 3, "]": 57, "}": 1197, ">": 25137,} return sum([scores[char] for char in self.corrupted_chars]) def score_incomplete(self) -> int: scores = {")": 1, "]": 2, "}": 3, ">": 4,} total_scores = [] for chunk in self.incomplete_chunks: total_score = 0 for char in reversed(chunk): close_char = self.close_chars[self.open_chars.index(char)] total_score = total_score * 5 + scores[close_char] total_scores.append(total_score) return median(total_scores) def part1(inputs: List[int]) -> int: s = Subsystem(inputs) return s.score_corrupted() def part2(inputs: List[int]) -> int: s = Subsystem(inputs) return s.score_incomplete() def parse(inputs: str) -> List[int]: """Parse the input string""" return inputs.split() def solve(path: str) -> Tuple[int, int]: """Solve the puzzle""" puzzle_input = parse(pathlib.Path(path).read_text().strip()) part1_result = part1(puzzle_input) part2_result = part2(puzzle_input) return part1_result, part2_result def main() -> None: for path in sys.argv[1:]: print(f"Input File: {path}") part1_result, part2_result = solve(path) print(f"Part 1 Result: {part1_result}") print(f"Part 2 Result: {part2_result}") if __name__ == "__main__": main()