diff options
| author | 2021-12-10 11:33:19 +0100 | |
|---|---|---|
| committer | 2021-12-10 11:33:19 +0100 | |
| commit | aa88c703f772ffb6412412d38c2de58dfce8f020 (patch) | |
| tree | 63d063f639e220cc5161202e186368eb134d82bf /day10/__init__.py | |
| parent | eabd21aa261f16ea3bec0e49816c3a980e68c17b (diff) | |
| download | 2021-aa88c703f772ffb6412412d38c2de58dfce8f020.tar.gz 2021-aa88c703f772ffb6412412d38c2de58dfce8f020.tar.bz2 2021-aa88c703f772ffb6412412d38c2de58dfce8f020.zip | |
Day 10
Diffstat (limited to 'day10/__init__.py')
| -rw-r--r-- | day10/__init__.py | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/day10/__init__.py b/day10/__init__.py new file mode 100644 index 0000000..b41ce55 --- /dev/null +++ b/day10/__init__.py | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | from collections import Counter | ||
| 2 | from functools import reduce | ||
| 3 | from math import floor | ||
| 4 | from typing import List, Iterator | ||
| 5 | |||
| 6 | from aoc import BaseAssignment | ||
| 7 | |||
| 8 | |||
| 9 | class IncompleteLine(Exception): | ||
| 10 | def __init__(self, missing: List[str]): | ||
| 11 | self.missing = missing | ||
| 12 | |||
| 13 | class CorruptedLine(Exception): | ||
| 14 | def __init__(self, got: str, expected: str, *args, **kwargs): | ||
| 15 | self.excpected = expected | ||
| 16 | self.got = got | ||
| 17 | |||
| 18 | pairs = { | ||
| 19 | '(': ')', | ||
| 20 | '[': ']', | ||
| 21 | '{': '}', | ||
| 22 | '<': '>', | ||
| 23 | } | ||
| 24 | |||
| 25 | |||
| 26 | class Assignment(BaseAssignment): | ||
| 27 | @classmethod | ||
| 28 | def parse_line(cls, line: str): | ||
| 29 | stack = [] | ||
| 30 | for character in line: | ||
| 31 | if character in pairs: | ||
| 32 | stack.append(character) | ||
| 33 | elif character == pairs[stack[-1]]: | ||
| 34 | stack.pop() | ||
| 35 | else: | ||
| 36 | raise CorruptedLine(character, pairs[stack[-1]]) | ||
| 37 | |||
| 38 | if len(stack) > 0: | ||
| 39 | raise IncompleteLine(list(reversed([pairs[c] for c in stack]))) | ||
| 40 | |||
| 41 | |||
| 42 | class AssignmentOne(Assignment): | ||
| 43 | example_result = 26397 | ||
| 44 | |||
| 45 | penalties = { | ||
| 46 | ')': 3, | ||
| 47 | ']': 57, | ||
| 48 | '}': 1197, | ||
| 49 | '>': 25137, | ||
| 50 | } | ||
| 51 | |||
| 52 | def run(self, input: Iterator[str]) -> int: | ||
| 53 | invalid_characters = [] | ||
| 54 | for line in input: | ||
| 55 | try: | ||
| 56 | self.parse_line(line) | ||
| 57 | except CorruptedLine as c: | ||
| 58 | invalid_characters.append(c.got) | ||
| 59 | except IncompleteLine: | ||
| 60 | continue | ||
| 61 | |||
| 62 | counter = Counter(invalid_characters) | ||
| 63 | |||
| 64 | return sum(counter[k] * v for k, v in self.penalties.items()) | ||
| 65 | |||
| 66 | |||
| 67 | class AssignmentTwo(Assignment): | ||
| 68 | example_result = 288957 | ||
| 69 | |||
| 70 | penalties = { | ||
| 71 | ')': 1, | ||
| 72 | ']': 2, | ||
| 73 | '}': 3, | ||
| 74 | '>': 4, | ||
| 75 | } | ||
| 76 | |||
| 77 | def run(self, input: Iterator[str]): | ||
| 78 | scores = [] | ||
| 79 | for line in input: | ||
| 80 | try: | ||
| 81 | self.parse_line(line) | ||
| 82 | except CorruptedLine: | ||
| 83 | continue | ||
| 84 | except IncompleteLine as c: | ||
| 85 | scores.append(reduce( | ||
| 86 | lambda out, item: (out * 5) + self.penalties[item], | ||
| 87 | c.missing, | ||
| 88 | 0 | ||
| 89 | )) | ||
| 90 | |||
| 91 | return sorted(scores)[floor(len(scores) / 2)] | ||
