Advertisement
Guest User

Untitled

a guest
Dec 15th, 2022
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.69 KB | Source Code | 0 0
  1. import re
  2. from functional import seq
  3. import numpy as np
  4. import time
  5.  
  6. f = open("in15.txt", "r", encoding="utf-8")
  7. input = f.read().split("\n")
  8. f.close()
  9. input
  10.  
  11. start_time = time.time()
  12.  
  13. # Input formatting
  14. points = seq(input)\
  15.             .map(lambda line: re.findall("-?\d+", line))\
  16.             .flatten()\
  17.             .map(int)\
  18.             .grouped(2)\
  19.             .grouped(2)
  20.  
  21. man_distance = lambda p1,p2: abs(p1[0]-p2[0]) + abs(p1[1]-p2[1])
  22. distances = points.map(lambda pair: man_distance(pair[0], pair[1]))
  23.  
  24. # Returns the lower and upper bound of blocked indices for a given y
  25. def calculate_blocked_range(point, distance, y):
  26.     distance_to_row = abs(point[1]-y)
  27.     if distance_to_row > distance:
  28.         return []
  29.     remaining = distance-distance_to_row
  30.     return[point[0]-remaining, point[0]+remaining]
  31.  
  32. # Actual work being done
  33. find_blocked = lambda y: points\
  34.                             .map(lambda pair: pair[0])\
  35.                             .zip(distances)\
  36.                             .map(lambda x: calculate_blocked_range(x[0], x[1], y))\
  37.                             .filter(lambda x: len(x) != 0)
  38.  
  39. #Works because they overlap, too lazy to make a proper overlap combination
  40. blocked = find_blocked(2000000).reduce(lambda x, y: [min(x[0], y[0]), max(x[1], y[1])])
  41.  
  42. print(abs(blocked[0]-blocked[1]))
  43. print("--- %s seconds ---" % (time.time() - start_time))    
  44.  
  45.    
  46. start_time = time.time()
  47.  
  48. points_to_vector = lambda p1, p2: [p2[0]-p1[0], p2[1]-p1[1]]
  49.  
  50. # Build 4 vectors that run along the edges of the diamond-shaped areas
  51. # Attach a base point to the vectors to be able to solve line equations
  52. # [vector, solution]
  53. def build_vector_solutions(sensor, distance):
  54.     outer_edge_distance = distance+1
  55.     right = [sensor[0]+outer_edge_distance, sensor[1]]
  56.     left = [sensor[0]-outer_edge_distance, sensor[1]]
  57.     up = [sensor[0], sensor[1]-outer_edge_distance]
  58.     down = [sensor[0], sensor[1]+outer_edge_distance]
  59.     vectors = [[points_to_vector(right,up), right],
  60.                [points_to_vector(right,down),right],
  61.                [points_to_vector(left,up),left],
  62.                [points_to_vector(left,down),left]]
  63.     return vectors
  64.        
  65. vectors = points\
  66.     .map(lambda pair: pair[0])\
  67.     .zip(distances)\
  68.     .map(lambda s_d: build_vector_solutions(*s_d))
  69.  
  70.  
  71. # Solve matrix using linear algebra with numpy
  72. # Returns the intersection of two lines
  73. calculate_solution = lambda point, vector: vector[0]*point[0] + vector[1]*point[1]
  74. def solve(v_p1, v_p2):
  75.     [v1, p1] = v_p1
  76.     [v2, p2] = v_p2
  77.     s1 = calculate_solution(p1,v1)
  78.     s2 = calculate_solution(p2,v2)
  79.     solution = []
  80.     try:
  81.         solution = np.linalg.solve(np.array([v1,v2]), np.array([s1,s2]))
  82.     except:
  83.         pass
  84.     return solution
  85.  
  86.  
  87. check_limits = lambda x ,y:  0 <=x and x<=4000000 and 0<=y and y<=4000000
  88.  
  89. # Create the list of every line intersections
  90. #Keep only those within range and actual solutions
  91. intersections = vectors\
  92.     .flatten()\
  93.     .cartesian(vectors.flatten())\
  94.     .map(lambda p: solve(*p))\
  95.     .filter(lambda x: len(x) !=0 and check_limits(*x))\
  96.     .map(np.ndarray.tolist)
  97.  
  98. sensor_distances = points\
  99.                     .map(lambda pair: pair[0])\
  100.                     .zip(distances)
  101.  
  102. check_outside = lambda inter, sensor, distance: man_distance(inter, sensor) > distance
  103.  
  104. # For every intersection found, check if it's a solution
  105. for intersection in intersections:
  106.     is_outside = True
  107.     for s_d in sensor_distances:
  108.         is_outside = is_outside and check_outside(intersection, *s_d)
  109.     if is_outside:
  110.         print(intersection[0]*4000000+intersection[1])
  111.         break
  112. print("--- %s seconds ---" % (time.time() - start_time))
Tags: aoc
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement