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