123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- #!/usr/bin/env python3
- import sys
- import re
- class Node:
- def __init__(self, left = None, right = None, value = None):
- self.left = left
- self.right = right
- self.value = value
- self.parent = None
-
- def __str__(self):
- return str(self.value) if self.value != None else f"[{str(self.left)}, {str(self.right)}]"
-
- def insert(self, node):
- if not self.left:
- self.left = node
- self.left.parent = self
- else:
- self.right = node
- self.right.parent = self
-
- def is_leaf(self):
- return self.left == None and self.right == None
-
- def is_left(self):
- return self.parent and self.parent.left == self
- def is_right(self):
- return self.parent and self.parent.right == self
- def parse_snailfishes(str):
- stack = [Node()]
- for c in str:
- if c == '[':
- stack.append(Node())
- continue
- if c == ']':
- node = stack.pop()
- stack[-1].insert(node)
- continue
- if c == ',':
- continue
- # if none apply insert as number
- stack[-1].insert(Node(value=int(c)))
- return stack.pop()
- def explode(node, value, left):
- #print(f'@ {node}')
- #print(f'@ {node.parent}')
- current = node
- while current.parent != None and ((current.is_left() and current.parent.right.value != None) or (current.is_right() and current.parent.left.value != None)):
- current = current.parent
- current = current.left if left else current.right
- while current.right if left else current.left != None:
- current = current.right if left else current.left
- #print(f'reached node {current} ({"left" if left else "right"})')
- if current.value != None:
- current.value += value
- return True
- def reduce_snailfishes(node, level = 1):
- current = node
- reduced = False
- #print(f'level {level}')
- if level > 3 and current.left.is_leaf() and current.right.is_leaf():
- print(f'exploding {current} distributing {current.left} and {current.right}')
- # search left spot
- reduced = reduced or explode(current, current.left.value, True)
- reduced = reduced or explode(current, current.right.value, False)
- # search right spot
- if current.is_left():
- current.parent.left = Node(value=0)
- if current.is_right():
- current.parent.right = Node(value=0)
- #explode_right(current, current.right)
- return reduced
- if not current.left.is_leaf():
- reduced = reduced or reduce_snailfishes(current.left, level + 1)
- if not current.right.is_leaf():
- reduced = reduced or reduce_snailfishes(current.right, level + 1)
- return reduced
- def add_snailfishes(node1, node2):
- print(f'adding {node1} and {node2}')
- node = Node(node1, node2)
- node.left.parent = node
- node.right.parent = node
- print(f'into {node}')
- while reduce_snailfishes(node):
- print(f'reducing again {node}')
- print(f'reduced to {node}')
- numbers = []
- for line in sys.stdin:
- print(f"new line: ", line.rstrip('\n'))
- numbers.append(parse_snailfishes(line.rstrip('\n')[1:-1]))
- print([str(n) for n in numbers])
- node1 = numbers[0]
- for i in range(1, len(numbers) * 0):
- node2 = numbers[i]
- add_snailfishes(node1, node2)
- node1 = node2
- add_snailfishes(numbers[3], numbers[4])
|