In [56]:
with open('inputs/input12.txt') as f_input:
s = next(f_input).rstrip()
In [57]:
import re
def sum_numbers(s):
p = re.compile('[-]?[\d]+')
numbers = list(map(int, p.findall(s)))
return sum(numbers)
In [58]:
sum_numbers(s)
Out[58]:
In [59]:
def transform_reds(s):
q = re.compile('\"[\w]+\"\:\"red\"')
return q.sub('R', s)
Track the regions to ignore: when an 'R' is found at depth d we keep this information; we ignore the span between the last $[d-1,d]$ transition (sink down) and the next $[d,d-1]$ transition (float up). Those regions will be erased.
In [60]:
def regions_to_erase(s):
regions = []
curr_depth = 0
last_sink = {}
red = None
for i, c in enumerate(s):
if c == '{':
curr_depth += 1
if red is None:
last_sink[curr_depth] = i
elif c == 'R':
ignore = True
if red is None:
red = curr_depth
elif c == '}':
if red is not None:
if curr_depth == red:
regions.append([last_sink[curr_depth], i])
red = None
curr_depth -= 1
return regions
Regions to erase may come out nested. If one region to erase is included inside another, we will ignore the smaller one.
In [61]:
def nest_regions(regions):
nested = []
for i, bounds in enumerate(regions):
include = True
for a in regions[i + 1:]:
if a[0] < bounds[0]:
include = include & False
if include:
nested.append(bounds)
return nested
Gather all the functions into a main pruned_sum()
In [72]:
def pruned_sum(s):
t = transform_reds(s)
nested_regions = nest_regions(regions_to_erase(t))
last_bound = 0
pruned = ''
for i, bounds in enumerate(nested_regions):
pruned += t[last_bound: bounds[0]]
last_bound = bounds[1] + 1
pruned += t[last_bound:]
return sum_numbers(pruned)
In [74]:
def test():
assert(pruned_sum('[1,2,3]') == 6)
assert(pruned_sum('[1,{"c":"red","b":2},3]') == 4)
assert(pruned_sum('{"d":"red","e":[1,2,3,4],"f":5}') == 0)
assert(pruned_sum('[1,{"c":"red","b":2},3]') == 4)
assert(pruned_sum('[1,"red",5]') == 6)
test()
In [76]:
pruned_sum(s)
Out[76]: