Advertisement
illuminati229

AoC 2023 Day 18

Dec 18th, 2023
887
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.39 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. def shoelace_area(points):
  18.     # points is a list of tuples (x, y) representing the vertices of the polygon
  19.     x = [p[0] for p in points]
  20.     y = [p[1] for p in points]
  21.     return abs(sum([x[i] * (y[(i + 1) % len(y)] - y[i - 1]) for i in range(len(x))])) // 2
  22.  
  23.  
  24. @timer_func
  25. def day18(filepath, part2=False):
  26.     with open(filepath) as fin:
  27.         lines = [line.strip() for line in fin.readlines()]
  28.  
  29.     points = [(0, 0)]
  30.     for line in lines:
  31.         if not part2:
  32.             d, l, c = line.split()
  33.             p = points[-1]
  34.             if d == 'U':
  35.                 points.append((p[0] - int(l), p[1]))
  36.             elif d == 'D':
  37.                 points.append((p[0] + int(l), p[1]))
  38.             elif d == 'R':
  39.                 points.append((p[0], p[1] + int(l)))
  40.             elif d == 'L':
  41.                 points.append((p[0], p[1] - int(l)))
  42.         else:
  43.             _, _, h = line.split()
  44.             p = points[-1]
  45.             d = h[-2]
  46.             length = int(h[2:-2], 16)
  47.             # 0 means R, 1 means D, 2 means L, and 3 means U
  48.             if d == '3':
  49.                 points.append((p[0] - length, p[1]))
  50.             elif d == '1':
  51.                 points.append((p[0] + length, p[1]))
  52.             elif d == '0':
  53.                 points.append((p[0], p[1] + length))
  54.             elif d == '2':
  55.                 points.append((p[0], p[1] - length))
  56.     # find the points on the boundary
  57.     if part2:
  58.         c = [int(line.split()[2][2:-2], 16) for line in lines]
  59.         b = sum(c)
  60.     else:
  61.         b = sum([int(line.split()[1]) for line in lines])
  62.     # shoelace formula to get the polygon area
  63.     a = shoelace_area(points)
  64.     # picks theorem to get the interior points
  65.     i = a - (b // 2) + 1
  66.     # return interior plus boundary points
  67.     return int(i + b)
  68.  
  69.  
  70. def main():
  71.     assert day18('test18') == 62
  72.     print(f"Part 1: {day18('input18')}")
  73.  
  74.     assert day18('test18', True) == 952408144115
  75.     print(f"Part 2: {day18('input18', True)}")
  76.  
  77.  
  78. if __name__ == '__main__':
  79.     main()
  80.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement