illuminati229

Aoc 2022 Day 15

Dec 15th, 2022
968
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.14 KB | None | 0 0
  1. from time import time
  2. from itertools import combinations
  3. import re
  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 man_dist(a: complex, b: complex = 0):
  20.     return int(sum([abs(a.real - b.real), abs(a.imag - b.imag)]))
  21.  
  22.  
  23. def valid_pos(x, y, max_x, max_y):
  24.     return 0 <= x <= max_x and 0 <= y <= max_y
  25.  
  26.  
  27. @timer_func
  28. def day15(filepath, inspect_row, part2=False):
  29.     with open(filepath) as fin:
  30.         lines = fin.read()
  31.  
  32.     coord_re = re.compile(r'x=(-?\d+), y=(-?\d+)')
  33.     matches = coord_re.findall(lines)
  34.     sensor_sets = []
  35.     for sensor, beacon in zip(matches[::2], matches[1::2]):
  36.         sensor_sets.append([complex(*[int(x) for x in sensor]), complex(*[int(x) for x in beacon])])
  37.  
  38.     for s_set in sensor_sets:
  39.         sensor, beacon = s_set
  40.         distance = man_dist(sensor, beacon)
  41.         s_set.append(distance)
  42.  
  43.     set_of_sensors = set([s for s, b, d in sensor_sets])
  44.     set_of_beacons = set([b for s, b, d in sensor_sets])
  45.     if not part2:
  46.         not_beacon = set()
  47.  
  48.         for s, b, d in sensor_sets:
  49.             if s.imag - d <= inspect_row <= s.imag + d:
  50.                 not_beacon.add(complex(s.real, inspect_row))
  51.                 for i in range(abs(int(abs(inspect_row - s.imag) - d))):
  52.                     not_beacon.add(complex(s.real + (i + 1), inspect_row))
  53.                     not_beacon.add(complex(s.real - (i + 1), inspect_row))
  54.  
  55.         return len(not_beacon) - len(not_beacon.intersection(set_of_beacons))
  56.     else:
  57.         # possible_points = set()
  58.         # for a, b in combinations(sensor_sets, 2):
  59.         #     sa, _, da = a
  60.         #     sb, _, db = b
  61.         #     if man_dist(a, b) > da + db + 2:
  62.         #         continue
  63.         #     # TODO Find the intersections....
  64.  
  65.         for sen in sensor_sets:
  66.             s, _, d = sen
  67.             d1 = set()
  68.             for dn in range(-(d + 1), d + 2):
  69.                 for f in [-1, 1]:
  70.                     step = complex(f * abs(d + 1 - dn), dn)
  71.                     nd1 = step + s
  72.                     if 0 <= nd1.real <= inspect_row * 2 and 0 <= nd1.imag <= inspect_row * 2:
  73.                         d1.add(nd1)
  74.             sen.append(d1)
  75.  
  76.         possible_points = set()
  77.         for a, b in combinations(sensor_sets, 2):
  78.             sa, _, _, d1a = a
  79.             sb, _, _, d1b = b
  80.             possible_points.update(d1a.intersection(d1b))
  81.         test = 0
  82.         for p in possible_points:
  83.             for s, _, d, _ in sensor_sets:
  84.                 if man_dist(p, s) <= d:
  85.                     break
  86.             else:
  87.                 return int(4000000 * p.real + p.imag)
  88.  
  89.  
  90. def main():
  91.     assert day15('test15', 10) == 26
  92.     print(f"Part 1: {day15('input15', 2000000)}")
  93.  
  94.     assert day15('test15', 10, True) == 56000011
  95.     print(f"Part 2: {day15('input15', 2000000, True)}")
  96.  
  97.  
  98. if __name__ == '__main__':
  99.     main()
  100.  
Advertisement
Add Comment
Please, Sign In to add comment