69 lines
1.3 KiB
Python
69 lines
1.3 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import aoc
|
|
import re
|
|
|
|
class Group:
|
|
|
|
def __init__(self):
|
|
self.groups = []
|
|
self.garbages = []
|
|
|
|
def fullscore(self, depth):
|
|
fs = depth
|
|
for grp in self.groups:
|
|
fs += grp.fullscore(depth+1)
|
|
return fs
|
|
|
|
|
|
def read_group(data: str):
|
|
|
|
assert data[0] == '{'
|
|
|
|
pos = 1
|
|
|
|
result = Group()
|
|
|
|
while True:
|
|
if data[pos] == '}':
|
|
return result, pos+1
|
|
elif data[pos] == '<':
|
|
grb, npos = read_garbage(data[pos:])
|
|
result.garbages.append(grb)
|
|
pos += npos
|
|
if data[pos] == ',':
|
|
pos += 1
|
|
elif data[pos] == '{':
|
|
grp, npos = read_group(data[pos:])
|
|
result.groups.append(grp)
|
|
pos += npos
|
|
if data[pos] == ',':
|
|
pos += 1
|
|
else:
|
|
assert False
|
|
|
|
|
|
def read_garbage(data: str):
|
|
assert data[0] == '<'
|
|
pos = 1
|
|
|
|
escaped = False
|
|
while True:
|
|
if escaped:
|
|
escaped = False
|
|
elif data[pos] == '>':
|
|
return data[1:pos-1], pos+1
|
|
elif data[pos] == '!':
|
|
escaped = True
|
|
pos+=1
|
|
|
|
|
|
rawinput = aoc.read_input(9)
|
|
|
|
data, _ = read_group(rawinput)
|
|
|
|
print(data.fullscore(1))
|
|
|
|
|
|
|