Add day10

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2021-12-10 11:46:02 -08:00
parent 492c2408cf
commit c261d43bc9
3 changed files with 259 additions and 0 deletions

147
day10/day10.py Executable file
View File

@@ -0,0 +1,147 @@
#!/usr/bin/env python3
import sys
from typing import Sequence
class ParseError(Exception):
def __init__(self, got: str, expected: str):
self.got = got
self.expected = expected
super().__init__(f"expected {repr(expected)} but got {repr(got)} instead")
CLOSING = ")]}>"
class Parser:
def __init__(self, text: str):
self.text = text
self.ptr = 0
def reset(self):
self.ptr = 0
@property
def is_eof(self) -> bool:
return self.ptr >= len(self.text)
@property
def c(self) -> str:
if self.is_eof:
return ""
else:
return self.text[self.ptr]
def adv(self):
if self.ptr >= len(self.text):
self.ptr = len(self.text)
else:
self.ptr += 1
def expect(self, c: str):
if c == self.c:
self.adv()
else:
raise ParseError(self.c, c)
def parse(self):
if self.c == "(":
self.parse_paren()
elif self.c == "[":
self.parse_bracket()
elif self.c == "{":
self.parse_brace()
elif self.c == "<":
self.parse_angle()
def parse_paren(self):
self.expect("(")
while self.c not in CLOSING:
self.parse()
self.expect(")")
def parse_bracket(self):
self.expect("[")
while self.c not in CLOSING:
self.parse()
self.expect("]")
def parse_brace(self):
self.expect("{")
while self.c not in CLOSING:
self.parse()
self.expect("}")
def parse_angle(self):
self.expect("<")
while self.c not in CLOSING:
self.parse()
self.expect(">")
def part1(lines: Sequence[str]):
scores = {
")": 3,
"]": 57,
"}": 1197,
">": 25137,
"": 0,
}
points = 0
for line in lines:
try:
parser = Parser(line)
while not parser.is_eof:
parser.parse()
except ParseError as e:
points += scores[e.got]
print(points)
def part2(lines: Sequence[str]):
scores = {
")": 1,
"]": 2,
"}": 3,
">": 4,
}
all_points = []
for line in lines:
completion = ""
try:
parser = Parser(line)
while not parser.is_eof:
parser.parse()
except ParseError as e:
if e.got != "":
continue
# Try to complete the parse using exceptions :^)
parser.text += e.expected
completion += e.expected
while True:
parser.reset()
try:
while not parser.is_eof:
parser.parse()
break
except ParseError as e:
assert e.expected != ""
parser.text += e.expected
completion += e.expected
# Calculate points using the completion
points = 0
for c in completion:
points *= 5
points += scores[c]
all_points += [points]
all_points = sorted(all_points)
print(all_points[len(all_points) // 2])
lines = list(map(str.strip, sys.stdin))
print("Part 1")
part1(lines)
print("Part 2")
part2(lines)