-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday10.py
115 lines (100 loc) · 3.32 KB
/
day10.py
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
with open("day10-input.txt", "r") as f:
data = f.readlines()
data = [x.strip() for x in data]
openingChars = ["(", "[", "{", "<"]
closingChars = [")", "]", "}", ">"]
charsMap = {"(": ")", "[": "]", "{": "}", "<": ">"}
autoCompletePoints = {")": 1, "]": 2, "}": 3, ">": 4}
def separateIncompleteCorrupt(data: list[str]) -> tuple[list[str], list[str]]:
incompleteLines: list[str] = []
corruptLines: list[str] = []
for line in data:
isCorrupt = False
stack: list[str] = []
for char in line:
if char in openingChars:
stack.append(char)
if char in closingChars:
openedWith = stack.pop()
if openingChars.index(openedWith) != closingChars.index(char):
isCorrupt = True
if isCorrupt:
corruptLines.append(line)
else:
incompleteLines.append(line)
return incompleteLines, corruptLines
# first illegal character
# ): 3 points.
# ]: 57 points.
# }: 1197 points.
# >: 25137 points.
def corruptLineScore(line: str) -> tuple[int, str, str]:
score = 0
expectedChar = "a"
badChar = "*"
stack: list[str] = []
for char in line:
if char in openingChars:
stack.append(char)
if char in closingChars:
openedWith: str = stack.pop()
if openingChars.index(openedWith) != closingChars.index(char):
expectedChar = closingChars[openingChars.index(openedWith)]
badChar = char
break
if badChar == ")":
score = 3
if badChar == "]":
score = 57
if badChar == "}":
score = 1197
if badChar == ">":
score = 25137
return score, expectedChar, badChar
def day10a(data: list[str]) -> int:
corrupt: list[str] = separateIncompleteCorrupt(data)[1]
scores: list[int] = []
for line in corrupt:
scores.append(corruptLineScore(line)[0])
return sum(scores)
def closingCharacters(line: str) -> str:
# [({(<(())[]>[[{[]{<()<>> -> }}]])})]
stack: list[str] = []
unpaired: list[str] = []
for char in line:
if char in charsMap.keys():
stack.append(charsMap[char])
else:
if char == stack[-1]:
stack.pop()
else:
unpaired.append(charsMap[char])
stack.reverse()
return "".join(stack)
# for each character, multiply the total score by 5 and
# then increase the total score by the point value given
# for the character in the following table:
# ): 1 point.
# ]: 2 points.
# }: 3 points.
# >: 4 points.
def autoCompleteScore(scorestring: str) -> int:
score: int = 0
for char in scorestring:
score *= 5
score += autoCompletePoints[char]
return score
def day10b(data: list[str]) -> int:
incomplete: list[str] = separateIncompleteCorrupt(data)[0]
scores: list[int] = [
autoCompleteScore(closingCharacters(line)) for line in incomplete
]
# sort all of the scores and then take the middle score
scores.sort()
middleScore: int = scores[len(scores) // 2]
return middleScore
if __name__ == "__main__":
# What is the total syntax error score for those errors?
print(f"Day10a: {day10a(data)}") # 369105
# What is the middle autocomplete score?
print(f"Day10b: {day10b(data)}") # 3999363569