diff --git a/18/18.py b/18/18.py new file mode 100644 index 0000000..ca91aae --- /dev/null +++ b/18/18.py @@ -0,0 +1,245 @@ +from functools import reduce as freduce +from itertools import permutations + +class Regular: + __slots__ = ['data'] + def __init__(self, x): + self.data = x + def __str__(self): + return f'r{self.data}' + __repr__ = __str__ + def __eq__(self, other): + if isinstance(other, Regular): + return self.data == other.data + if isinstance(other, int): + return self.data == other + return False + +def load_file(filename='input'): + with open(filename) as f: + for line in f: + yield line.strip() + +def add(x, y): + return reduce(add_numbers(x, y)) + +def reduce(x): + while True: + if can_explode(x): + x = explode(x) + continue + if can_split(x): + x = split(x) + continue + break + return x + +def can_split(x): + try: + return next(filter(lambda k: k.data>=10, numbers(x))) + except StopIteration: + return False + +def is_int(x): + return isinstance(x, int) + +def is_regular(x): + return isinstance(x, Regular) + +def is_pair(x): + return isinstance(x, list) + +def magnitude(x): + if is_regular(x): + return x.data + return 3*magnitude(first(x)) + 2*magnitude(second(x)) + +def numbers(x): + if is_regular(x): + yield x + elif is_pair(x): + yield from numbers(first(x)) + yield from numbers(second(x)) + +def height(x, h=0): + if is_regular(first(x)) and is_regular(second(x)): + yield h, x + if is_pair(first(x)): + yield from height(first(x), h+1) + if is_pair(second(x)): + yield from height(second(x), h+1) + +def can_explode(x): + try: + return next(filter(lambda k: k[0]==4, height(x))) + except StopIteration: + return None + +def explode(where): + what = can_explode(where)[1] + replace_once(where, what, Regular(-1)) + k = list(numbers(where)) + i = k.index(Regular(-1)) + if i-1>=0: + k[i-1].data += what[0].data + if i+1