/ Python / 2022 / 18.py
18.py
 1  from lib import *
 2  
 3  input = read_input(2022, 18)
 4  
 5  
 6  cubes = [(x, y, z) for x, y, z in map(ints, input.splitlines())]
 7  
 8  
 9  out = 0
10  for i, x in enumerate(cubes):
11      out += 6
12      for y in cubes[:i]:
13          if abs(x[0] - y[0]) + abs(x[1] - y[1]) + abs(x[2] - y[2]) == 1:
14              out -= 2
15  print(out)
16  
17  
18  out = 0
19  (minx, miny, minz) = (maxx, maxy, maxz) = cubes[0]
20  for i, x in enumerate(cubes):
21      out += 6
22      for y in cubes[:i]:
23          if abs(x[0] - y[0]) + abs(x[1] - y[1]) + abs(x[2] - y[2]) == 1:
24              out -= 2
25      minx = min(x[0], minx)
26      miny = min(x[1], miny)
27      minz = min(x[2], minz)
28      maxx = max(x[0], maxx)
29      maxy = max(x[1], maxy)
30      maxz = max(x[2], maxz)
31  
32  checked = set()
33  candidates = [
34      (i, j, k)
35      for x, y, z in cubes
36      for i, j, k in [(x, y, z - 1), (x, y, z + 1), (x, y - 1, z), (x, y + 1, z), (x - 1, y, z), (x + 1, y, z)]
37      if (i, j, k) not in cubes
38  ]
39  while candidates:
40      queue = [candidates.pop()]
41      if queue[0] in checked:
42          continue
43      visited = set()
44      while queue:
45          x, y, z = queue.pop(0)
46          if x not in range(minx, maxx + 1) or y not in range(miny, maxy + 1) or z not in range(minz, maxz + 1):
47              break
48          if (x, y, z) in visited:
49              continue
50          visited.add((x, y, z))
51          for q in [(x, y, z - 1), (x, y, z + 1), (x, y - 1, z), (x, y + 1, z), (x - 1, y, z), (x + 1, y, z)]:
52              if q not in cubes and q not in visited:
53                  queue.append(q)
54      else:
55          for x, y, z in visited:
56              for q in [(x, y, z - 1), (x, y, z + 1), (x, y - 1, z), (x, y + 1, z), (x - 1, y, z), (x + 1, y, z)]:
57                  if q in cubes:
58                      out -= 1
59  
60      checked.update(visited)
61  
62  print(out)