text: #!/usr/bin/env python
  
  import sys
  sys.path.append('..')
  from libs.helpers import get_input
  
  
  def add(n1, n2):
      return f'[{n1},{n2}]'
  
  
  def reduce(n):
      new_n = explode(n)
      if new_n != n:
          return reduce(new_n)
      n = new_n
      new_n = split(n)
      if new_n != n:
          return reduce(new_n)
      return new_n
  
  
  def explode(n):
      open_braces = 0
      for i in range(len(n)):
          c = n[i]
          if c == '[':
              open_braces += 1
          elif c == ']':
              open_braces -= 1
          if open_braces >= 5:
              x, y = get_numbers(n[i+1:])
              l = add_left(n[:i], x)
              r = add_right(n[i+2+len(f'{x},{y}'):], y)
              return f'{l}0{r}'
      return n
  
  
  def get_numbers(n):
      idx_comma = n.index(',')
      idx_bracket = n.index(']')
      return (int(n[:idx_comma]), int(n[idx_comma+1:idx_bracket]))
  
  
  def add_left(n, num):
      for i in range(len(n) - 1, -1, -1):
          if n[i] == '[' or n[i] == ']' or n[i] == ',':
              continue
  
          # The try block will determine if the range we're trying
          # to parse are consecutive digits or contain another
          # character.
          for j in range(i, -1, -1):
              try:
                  x = int(n[j:i+1])
              except:
                  x = int(n[j+1:i+1]) + num
                  return f'{n[0:j+1]}{x}{n[i+1:]}'
      return n
  
  
  def add_right(n, num):
      for i in range(0, len(n)):
          if n[i] == '[' or n[i] == ']' or n[i] == ',':
              continue
          for j in range(i+1, len(n)):
              try:
                  x = int(n[i:j])
              except:
                  x = int(n[i:j-1]) + num
                  return f'{n[0:i]}{x}{n[j-1:]}'
      return n
  
  
  def split(n):
      nums = [int(x) for x in n.replace('[', '').replace(']', '').split(',')]
      for x in nums:
          if x > 9:
              idx = n.index(str(x))
              l = int(x/2)
              r = x - l
              return f'{n[0:idx]}[{l},{r}]{n[idx+len(str(x)):]}'
      return n
  
  
  def magnitude(n):
      if n.find(',') >= 0:
          x, y = get_parts(n)
          return 3 * magnitude(x) + 2 * magnitude(y)
      else:
          return int(n)
  
  
  def get_parts(n):
      n = n[1:len(n)-1]
      if n[0] == '[':
          brackets = 1
          for i in range(1, len(n)):
              if n[i] == '[':
                  brackets += 1
              elif n[i] == ']':
                  brackets -= 1
              if brackets == 0 and n[i] == ',':
                  return (n[:i], n[i+1:])
      else:
          s = n.split(',')
          return (s[0], ','.join(s[1:]))
  
  
  if __name__ == '__main__':
      lines = get_input('./input.txt')
      n = lines[0]
      for l in lines[1:]:
          n = add(n, l)
          n = reduce(n)
      print(n)
      print(magnitude(n))
  
      possible_values = [reduce(add(x, y)) for x in lines for y in lines]
      max_magnitude = max(magnitude(p) for p in possible_values)
      print(max_magnitude)
  