Advertisement
illuminati229

AoC 2022 Day 18

Dec 19th, 2022
1,290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.91 KB | None | 0 0
  1. from time import time
  2. from math import prod
  3. import sys
  4.  
  5.  
  6. def timer_func(func):
  7.     # This function shows the execution time of
  8.     # the function object passed
  9.     def wrap_func(*args, **kwargs):
  10.         t1 = time()
  11.         result = func(*args, **kwargs)
  12.         t2 = time()
  13.         print(f'Function {func.__name__!r} executed in {(t2 - t1):.4f}s')
  14.         return result
  15.  
  16.     return wrap_func
  17.  
  18.  
  19. def tuple_add(a: tuple, b: tuple) -> tuple:
  20.     return tuple([c + d for c, d in zip(a, b)])
  21.  
  22.  
  23. def get_adjacent(x: tuple) -> list[tuple, ...]:
  24.     return [
  25.         tuple_add(x, tuple([
  26.             j if k == y else 0
  27.             for k in range(len(x))
  28.         ]))
  29.         for j in [-1, 1]
  30.         for y in range(len(x))
  31.     ]
  32.  
  33.  
  34. def find_air(current_point: tuple, air_points: set, rock_points, surface_area: int, valid_range):
  35.     air_points.add(current_point)
  36.     for point in get_adjacent(current_point):
  37.         if ((valid_range[0][0] <= point[0] <= valid_range[0][1] and
  38.              valid_range[1][0] <= point[1] <= valid_range[1][1]) and
  39.                 valid_range[2][0] <= point[2] <= valid_range[2][1]):
  40.             pass
  41.         else:
  42.             continue
  43.         if point in rock_points:
  44.             surface_area += 1
  45.         elif ((valid_range[0][0] > point[0] > valid_range[0][1] or
  46.               valid_range[1][0] > point[1] > valid_range[1][1]) or
  47.               valid_range[2][0] > point[2] > valid_range[2][1]):
  48.             continue
  49.         elif point in air_points:
  50.             continue
  51.         else:
  52.             air_points, surface_area = find_air(point, air_points, rock_points, surface_area, valid_range)
  53.  
  54.     return air_points, surface_area
  55.  
  56.  
  57. @timer_func
  58. def day18(filepath, part2=False):
  59.     with open(filepath) as fin:
  60.         lines = [line.strip() for line in fin.readlines()]
  61.  
  62.     rock_points = set()
  63.     surface_area = 0
  64.     for line in lines:
  65.         point = tuple(int(x) for x in line.split(','))
  66.         if not part2:
  67.             surface_area += 6
  68.             for adj in get_adjacent(point):
  69.                 if adj in rock_points:
  70.                     surface_area -= 2
  71.         rock_points.add(point)
  72.     if part2:
  73.         valid_range = [[min(point[0] for point in rock_points) - 1, max(point[0] for point in rock_points) + 1],
  74.                        [min(point[1] for point in rock_points) - 1, max(point[1] for point in rock_points) + 1],
  75.                        [min(point[2] for point in rock_points) - 1, max(point[2] for point in rock_points) + 1]]
  76.         sys.setrecursionlimit(max(1000, prod(x[1] for x in valid_range)))
  77.         _, surface_area = find_air(tuple(x[0] for x in valid_range), set(), rock_points, 0, valid_range)
  78.  
  79.     return surface_area
  80.  
  81.  
  82. def main():
  83.     assert day18('test18') == 64
  84.     print(f"Part 1: {day18('input18')}")
  85.  
  86.     assert day18('test18', True) == 58
  87.     print(f"Part 2: {day18('input18', True)}")
  88.  
  89.  
  90. if __name__ == '__main__':
  91.     main()
  92.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement