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 clean(text: str) -> str:
|
||||||
def _(*args):
|
out = ""
|
||||||
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 = []
|
|
||||||
i = 0
|
i = 0
|
||||||
cancellations = 0
|
garbage = False
|
||||||
while i < len(tokens):
|
while i < len(text):
|
||||||
t = tokens[i]
|
c = text[i]
|
||||||
if t == Token.Cancel:
|
if c == "!":
|
||||||
cancellations += 1
|
|
||||||
i += 2
|
i += 2
|
||||||
continue
|
continue
|
||||||
stack.append(t)
|
|
||||||
|
if garbage and c == ">":
|
||||||
|
garbage = False
|
||||||
|
elif garbage:
|
||||||
|
pass
|
||||||
|
elif c == "<":
|
||||||
|
garbage = True
|
||||||
|
else:
|
||||||
|
out += c
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
assert len(tokens) == len(stack) + 2*cancellations
|
assert not garbage, "All garbage must be closed"
|
||||||
|
return out
|
||||||
|
|
||||||
return stack
|
|
||||||
|
|
||||||
def clean(tokens):
|
def score(text: str) -> int:
|
||||||
stack = []
|
depth = 0
|
||||||
i = 0
|
points = 0
|
||||||
while i < len(tokens):
|
for c in text:
|
||||||
if tokens[i] == Token.GarbageStart:
|
if c == "{":
|
||||||
while tokens[i] != Token.GarbageEnd:
|
depth += 1
|
||||||
i += 1
|
if c == "}":
|
||||||
i += 1
|
points += depth
|
||||||
continue
|
depth -= 1
|
||||||
print('PUSH:', i, tokens[i])
|
|
||||||
stack.append(tokens[i])
|
|
||||||
i += 1
|
|
||||||
return stack
|
|
||||||
|
|
||||||
class Group:
|
assert depth == 0, "All groups must be closed"
|
||||||
def __init__(self):
|
return points
|
||||||
self.children = []
|
|
||||||
|
|
||||||
def append(self, child):
|
|
||||||
self.children.append(child)
|
|
||||||
|
|
||||||
def __repr__(self):
|
with open("input/day09.txt") as f:
|
||||||
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:
|
|
||||||
puzzle_input = f.read()
|
puzzle_input = f.read()
|
||||||
|
|
||||||
# print(solve('<{o"i!a,<{i<a>'))
|
print(part1(puzzle_input))
|
||||||
print(solve(puzzle_input))
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue