2017 Day 9 Part 1
This commit is contained in:
parent
72c469ee79
commit
63093277b0
1 changed files with 31 additions and 79 deletions
112
2017/day09.py
112
2017/day09.py
|
|
@ -1,94 +1,46 @@
|
|||
import enum
|
||||
def part1(text):
|
||||
return score(clean(text))
|
||||
|
||||
@enum.unique
|
||||
class Token(enum.Enum):
|
||||
GroupStart = '{'
|
||||
GroupEnd = '}'
|
||||
GarbageStart = '<'
|
||||
GarbageEnd = '>'
|
||||
Cancel = '!'
|
||||
|
||||
def log(f):
|
||||
def _(*args):
|
||||
ret = f(*args)
|
||||
print(*args, '->', ret)
|
||||
return ret
|
||||
return _
|
||||
|
||||
def tokenize(stream):
|
||||
tokens = {t.value: t for t in Token}
|
||||
return [tokens[c] for c in stream if c in tokens]
|
||||
|
||||
def cancel(tokens):
|
||||
stack = []
|
||||
def clean(text: str) -> str:
|
||||
out = ""
|
||||
i = 0
|
||||
cancellations = 0
|
||||
while i < len(tokens):
|
||||
t = tokens[i]
|
||||
if t == Token.Cancel:
|
||||
cancellations += 1
|
||||
garbage = False
|
||||
while i < len(text):
|
||||
c = text[i]
|
||||
if c == "!":
|
||||
i += 2
|
||||
continue
|
||||
stack.append(t)
|
||||
|
||||
if garbage and c == ">":
|
||||
garbage = False
|
||||
elif garbage:
|
||||
pass
|
||||
elif c == "<":
|
||||
garbage = True
|
||||
else:
|
||||
out += c
|
||||
i += 1
|
||||
|
||||
assert len(tokens) == len(stack) + 2*cancellations
|
||||
assert not garbage, "All garbage must be closed"
|
||||
return out
|
||||
|
||||
return stack
|
||||
|
||||
def clean(tokens):
|
||||
stack = []
|
||||
i = 0
|
||||
while i < len(tokens):
|
||||
if tokens[i] == Token.GarbageStart:
|
||||
while tokens[i] != Token.GarbageEnd:
|
||||
i += 1
|
||||
i += 1
|
||||
continue
|
||||
print('PUSH:', i, tokens[i])
|
||||
stack.append(tokens[i])
|
||||
i += 1
|
||||
return stack
|
||||
def score(text: str) -> int:
|
||||
depth = 0
|
||||
points = 0
|
||||
for c in text:
|
||||
if c == "{":
|
||||
depth += 1
|
||||
if c == "}":
|
||||
points += depth
|
||||
depth -= 1
|
||||
|
||||
class Group:
|
||||
def __init__(self):
|
||||
self.children = []
|
||||
assert depth == 0, "All groups must be closed"
|
||||
return points
|
||||
|
||||
def append(self, child):
|
||||
self.children.append(child)
|
||||
|
||||
def __repr__(self):
|
||||
return '{{}}'.format(''.join(repr(c) for c in self.children))
|
||||
|
||||
__str__ = __repr__
|
||||
|
||||
def parse(tokens):
|
||||
stack = []
|
||||
outer = Group()
|
||||
last = None
|
||||
tokens = list(clean(cancel(tokens)))
|
||||
print(len([t for t in tokens if t == Token.GroupStart]), len([t for t in tokens if t == Token.GroupEnd]))
|
||||
assert len([t for t in tokens if t == Token.GroupStart]) == len([t for t in tokens if t == Token.GroupEnd])
|
||||
for t in tokens:
|
||||
if t == Token.GroupStart:
|
||||
g = Group()
|
||||
if stack:
|
||||
stack[-1].append(g)
|
||||
stack.append(g)
|
||||
elif t == Token.GroupEnd:
|
||||
last = stack.pop(-1)
|
||||
return last
|
||||
|
||||
def score(group, depth=1):
|
||||
return depth + sum(score(c, depth+1) for c in group.children)
|
||||
|
||||
def solve(stream):
|
||||
stuff = parse(tokenize(stream))
|
||||
if stuff is None: return 0
|
||||
return score(stuff)
|
||||
|
||||
with open('input/day9') as f:
|
||||
with open("input/day09.txt") as f:
|
||||
puzzle_input = f.read()
|
||||
|
||||
# print(solve('<{o"i!a,<{i<a>'))
|
||||
print(solve(puzzle_input))
|
||||
print(part1(puzzle_input))
|
||||
|
|
|
|||
Loading…
Reference in a new issue