illuminati229

AoC Day 14

Dec 14th, 2022
864
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.00 KB | None | 0 0
  1. from time import time
  2.  
  3.  
  4. def timer_func(func):
  5.     # This function shows the execution time of
  6.     # the function object passed
  7.     def wrap_func(*args, **kwargs):
  8.         t1 = time()
  9.         result = func(*args, **kwargs)
  10.         t2 = time()
  11.         print(f'Function {func.__name__!r} executed in {(t2 - t1):.4f}s')
  12.         return result
  13.  
  14.     return wrap_func
  15.  
  16.  
  17. class CaveObjects:
  18.     def __init__(self, floor):
  19.         self.objects = {}
  20.         self.floor = floor
  21.  
  22.     def add_object(self, coord):
  23.         x, y = coord
  24.         if not self.is_in(coord):
  25.             if x in self.objects:
  26.                 self.objects[x].append(y)
  27.             else:
  28.                 self.objects[x] = [self.floor]
  29.                 self.objects[x].append(y)
  30.  
  31.     def is_in(self, coord):
  32.         x, y = coord
  33.         if y == self.floor:
  34.             return True
  35.         if x in self.objects:
  36.             if y in self.objects[x]:
  37.                 return True
  38.  
  39.         return False
  40.  
  41.  
  42. def tuple_add(a, b):
  43.     return tuple(c + d for c, d in zip(a, b))
  44.  
  45.  
  46. def tuple_sub(a, b):
  47.     return tuple(c - d for c, d in zip(a, b))
  48.  
  49.  
  50. def tuple_direction(a, b):
  51.     return tuple(x // abs(x) if abs(x) > 0 else 0 for x in tuple_sub(b, a))
  52.  
  53.  
  54. @timer_func
  55. def day14(filepath, part2=False):
  56.     with open(filepath) as fin:
  57.         lines = [line.strip() for line in fin.readlines()]
  58.  
  59.     rocks = []
  60.     for line in lines:
  61.         for a, b in zip(line.split(' -> '), line.split(' -> ')[1:]):
  62.             a = tuple(int(x) for x in a.split(','))
  63.             b = tuple(int(x) for x in b.split(','))
  64.             direction = tuple_direction(a, b)
  65.             while a != b:
  66.                 rocks.append(a)
  67.                 a = tuple_add(a, direction)
  68.             rocks.append(b)
  69.     sand = []
  70.     start = (500, 0)
  71.     max_y = max([x for _, x in rocks])
  72.     cave_floor = max_y + 2
  73.     cave_objects = CaveObjects(cave_floor)
  74.     for rock in rocks:
  75.         cave_objects.add_object(rock)
  76.  
  77.     caught = True
  78.     while caught:
  79.         falling = True
  80.         cur = start
  81.         while falling:
  82.             step = tuple_add(cur, (0, 1))
  83.             if cave_objects.is_in(step):
  84.                 step = tuple_add(cur, (-1, 1))
  85.                 if cave_objects.is_in(step):
  86.                     step = tuple_add(cur, (1, 1))
  87.                     if cave_objects.is_in(step):
  88.                         falling = False
  89.                         sand.append(cur)
  90.                         cave_objects.add_object(cur)
  91.                         break
  92.             cur = step
  93.             if not part2:
  94.                 if cur[1] >= max_y:
  95.                     caught = False
  96.                     break
  97.         if (500, 0) in sand:
  98.             falling = False
  99.             caught = False
  100.             break
  101.  
  102.     return len(sand)
  103.  
  104.  
  105. def main():
  106.     # assert day14('test14') == 24
  107.     # print(f"Part 1: {day14('input14')}")
  108.  
  109.     assert day14('test14', True) == 93
  110.     print(f"Part 2: {day14('input14', True)}")
  111.  
  112.  
  113. if __name__ == '__main__':
  114.     main()
  115.  
Advertisement
Add Comment
Please, Sign In to add comment