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())
|
||
|
|
||
|
|
||
|
|