81 lines
1.5 KiB
Python
81 lines
1.5 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 garbagesum(self):
|
|
gs = 0
|
|
for grp in self.groups:
|
|
gs += grp.garbagesum()
|
|
for grb in self.garbages:
|
|
gs += len(grb)
|
|
return gs
|
|
|
|
|
|
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
|
|
|
|
gstr = ''
|
|
|
|
escaped = False
|
|
while True:
|
|
if escaped:
|
|
escaped = False
|
|
elif data[pos] == '>':
|
|
return gstr, pos+1
|
|
elif data[pos] == '!':
|
|
escaped = True
|
|
else:
|
|
gstr += data[pos]
|
|
pos+=1
|
|
|
|
|
|
rawinput = aoc.read_input(9)
|
|
|
|
data, _ = read_group(rawinput)
|
|
|
|
print(data.garbagesum())
|
|
|
|
|
|
|