Advertisement
hhoppe

Advent of code 2021 day 22

Dec 22nd, 2021 (edited)
915
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 1.93 KB | None | 0 0
  1. def process1(s, part2=False):  # Using CSG of boxes.
  2.   # Adapted simpler logic of https://github.com/shaeberling/euler/blob/master/kotlin/src/com/s13g/aoc/aoc2021/Day22.kt.
  3.   lines = s.strip('\n').split('\n')
  4.   state_cuboids = []
  5.   for line in lines:
  6.     state = line[:3].strip()
  7.     cuboid = tuple(tuple(map(int, range_[2:].split('..')))
  8.                    for range_ in line[3:].strip().split(','))
  9.     if all(-50 <= c <= 50 for range_ in cuboid for c in range_) or part2:
  10.       state_cuboids.append((state == 'on', cuboid))
  11.  
  12.   def inside(a, b):
  13.     (ax, ay, az), (bx, by, bz) = a, b
  14.     return (ax[0] >= bx[0] and ay[0] >= by[0] and az[0] >= bz[0] and
  15.             ax[1] <= bx[1] and ay[1] <= by[1] and az[1] <= bz[1])
  16.  
  17.   def outside(a, b):
  18.     (ax, ay, az), (bx, by, bz) = a, b
  19.     return (ax[0] > bx[1] or ay[0] > by[1] or az[0] > bz[1] or
  20.             ax[1] < bx[0] or ay[1] < by[0] or az[1] < bz[0])
  21.  
  22.   def subdivide_a_subtracting_b(a, b):  # Slow because up to 27 subcells.
  23.     coords = [sorted((a[c][0], a[c][1], b[c][0], b[c][1])) for c in range(3)]
  24.     intervals = [[(c1, c2) for c1, c2 in ((x0, x1 - 1), (x1, x2), (x2 + 1, x3))
  25.                   if c1 <= c2]
  26.                  for x0, x1, x2, x3 in coords]
  27.     for subcell in itertools.product(*intervals):
  28.       if inside(subcell, a) and not inside(subcell, b):
  29.         yield subcell
  30.  
  31.   cells = set()  # Disjoint union of "on" cubes.
  32.  
  33.   # Subtract each cuboid from existing cells (potentially subdividing them).
  34.   for state, cuboid in state_cuboids:
  35.     cells_to_add, cells_to_delete = set(), set()
  36.     for cell in cells:
  37.       if outside(cell, cuboid):
  38.         continue
  39.       cells_to_delete.add(cell)
  40.       if not inside(cell, cuboid):
  41.         cells_to_add.update(subdivide_a_subtracting_b(cell, cuboid))
  42.  
  43.     if state:
  44.       cells_to_add.add(cuboid)
  45.     cells = (cells - cells_to_delete) | cells_to_add
  46.  
  47.   return sum((np.diff(cell).T[0] + 1).prod() for cell in cells)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement