day 07
recursive circus
approach
each line is parsed with a regex into a name, a weight and a list of children. part 1 builds a child → parent map and climbs from any program until it reaches one with no parent: that's the root.
part 2 runs a post-order dfs that returns each subtree's total weight. at every node it looks at its children's totals, takes the most common one as the expected value, and flags the child that differs along with how far off it is. once a flag is set deeper down it's passed straight up, so the reported program is the deepest one that is wrong. the answer is its own weight plus the offset.
the trick
the majority weight among siblings tells you both which child is wrong and by how much.
python
c, _ = Counter(sizes.values()).most_common(1).pop()
odds = [nn for nn in sizes if sizes[nn] != c]
if odds:
odd = odds.pop()
off = c - sizes[odd]
return total, odd, off