from lib import get_data from math import ceil, floor from itertools import combinations data = """[[[0,[5,8]],[[1,7],[9,6]]],[[4,[1,2]],[[1,4],2]]] [[[5,[2,8]],4],[5,[[9,9],0]]] [6,[[[6,2],[5,6]],[[7,6],[4,7]]]] [[[6,[0,7]],[0,9]],[4,[9,[9,0]]]] [[[7,[6,4]],[3,[1,3]]],[[[5,5],1],9]] [[6,[[7,3],[3,2]]],[[[3,8],[5,7]],4]] [[[[5,4],[7,7]],8],[[8,3],8]] [[9,3],[[9,9],[6,[4,9]]]] [[2,[[7,7],7]],[[5,8],[[9,3],[0,2]]]] [[[[5,2],5],[8,[3,7]]],[[5,[7,5]],[4,4]]]""" data = get_data(__file__) def parse(line): xs = list(line) for i in range(len(xs)): try: xs[i] = int(xs[i]) except ValueError: pass assert line == "".join(map(str, xs)) return xs def reduce(xs): reduced, nesting = False, 0 for i in range(len(xs)): c = xs[i] if c == "[" and nesting == 4 and not reduced: lhs, rhs = xs[i + 1], xs[i + 3] if not (type(lhs) is int and type(rhs) is int): continue xs = xs[:i] + [0] + xs[i + 5 :] for j in range(i - 1, -1, -1): if type(xs[j]) is int: xs[j] += lhs break for j in range(i + 1, len(xs)): if type(xs[j]) is int: xs[j] += rhs break reduced = True break elif c == "[": nesting += 1 elif c == "]": nesting -= 1 if not reduced: for i in range(len(xs)): c = xs[i] if type(c) is int and c >= 10: p = [floor(c / 2), ceil(c / 2)] xs = xs[:i] + ["[", p[0], ",", p[1], "]"] + xs[i + 1 :] reduced = True break return xs def restore(xs): return "".join(map(str, xs)) assert restore(reduce(parse("[[[[[9,8],1],2],3],4]"))) == "[[[[0,9],2],3],4]" assert restore(reduce(parse("[7,[6,[5,[4,[3,2]]]]]"))) == "[7,[6,[5,[7,0]]]]" assert ( restore(reduce(parse("[[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]]"))) == "[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]" ) assert ( restore(reduce(parse("[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]"))) == "[[3,[2,[8,0]]],[9,[5,[7,0]]]]" ) def add(a, b): s = ["["] + a + [","] + b + ["]"] while True: ns = reduce(s) if s == ns: break s = ns return s a = "[[[[4,3],4],4],[7,[[8,4],9]]]" b = "[1,1]" assert restore(add(parse(a), parse(b))) == "[[[[0,7],4],[[7,8],[6,0]]],[8,1]]" lines = list(data.splitlines()) s = parse(lines[0].strip()) for line in lines[1:]: s = add(s, parse(line.strip())) def get_mag(xs): if type(xs) is int: return xs return get_mag(xs[0]) * 3 + get_mag(xs[1]) * 2 print(get_mag(eval(restore(s)))) lines = list(data.splitlines()) m = 0 for a, b in combinations(lines, 2): m = max(m, get_mag(eval(restore(add(parse(a), parse(b)))))) m = max(m, get_mag(eval(restore(add(parse(b), parse(a)))))) print(m)