Advertisement
Guest User

Untitled

a guest
Dec 15th, 2022
255
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.98 KB | None | 0 0
  1. from collections import defaultdict
  2.  
  3. LIMIT_P2 = 4000000
  4. LIMIT_P1 = 2000000
  5.  
  6.  
  7. class Point:
  8.  
  9.     def __init__(self, x: int, y: int):
  10.         self.x = x
  11.         self.y = y
  12.  
  13.     def __add__(self, other):
  14.         return (self.x + other.x, self.y + other.y)
  15.  
  16.     def delta(self, x=0, y=0):
  17.         return Point(self.x + x, self.y + y)
  18.  
  19.     def __eq__(self, other):
  20.         return self.x == other.x and self.y == other.y
  21.  
  22.     def __hash__(self):
  23.         return hash(f"{self.x},{self.y}")
  24.  
  25.     def __repr__(self):
  26.         return f"Point({self.x},{self.y})"
  27.  
  28.  
  29. def part1(str_data: str, y: int):
  30.     sensors, beacons, pairs = get_map(str_data)
  31.     locations = set()
  32.  
  33.     for s, b in pairs:
  34.         locations.update(get_marks_at_y_axis(s, b, y))
  35.  
  36.     for s in sensors:
  37.         if s.y == y:
  38.             locations.remove(s.x)
  39.  
  40.     for b in beacons:
  41.         if b.y == y:
  42.             locations.remove(b.y)
  43.  
  44.     print(y, len(locations))
  45.  
  46.  
  47. def part2(str_data: str, limit_tl: Point, limit_dr: Point):
  48.     sensors, beacons, pairs = get_map(str_data)
  49.     store = defaultdict(lambda: 0)
  50.  
  51.     sensor_id = 0
  52.     sensor_total = len(sensors)
  53.     for sensor, beacon in pairs:
  54.         sensor_id += 1
  55.  
  56.         dist = manhattan_distance(sensor, beacon) + 1
  57.         print(f"{sensor_id} of {sensor_total}: sensor {sensor} with beacon {beacon} (distance={dist})")
  58.         vertical = -1
  59.  
  60.         xmin = max(limit_tl.x, sensor.x - dist)
  61.         xmax = min(limit_dr.x, sensor.x + dist)
  62.  
  63.         for x in range(xmin, xmax + 1):
  64.  
  65.             if x <= sensor.x:
  66.                 vertical += 1
  67.             else:
  68.                 vertical -= 1
  69.  
  70.             cu = (x, sensor.y - vertical)
  71.             cd = (x, sensor.y + vertical)
  72.  
  73.  
  74.             if cu == cd:
  75.                 store[cu] += 1
  76.             else:
  77.                 store[cu] += 1
  78.                 store[cd] += 1
  79.  
  80.             if store[cu] == 4:
  81.                 print(cu)
  82.  
  83.             if store[cd] == 4:
  84.                 print(cd)
  85.  
  86.  
  87.  
  88. def get_marks_at_y_axis(sensor: Point, beacon: Point, y):
  89.     distance = manhattan_distance(sensor, beacon)
  90.     distance_from_axis = abs(y - sensor.y)
  91.     limit = max(distance - distance_from_axis, 0)
  92.     return set(range(sensor.x - limit, sensor.x + limit + 1))
  93.  
  94.  
  95. def manhattan_distance(s: Point, b: Point):
  96.     return abs(b.x - s.x) + abs(b.y - s.y)
  97.  
  98.  
  99. def get_map(str_data: str):
  100.     sensors = set()
  101.     beacons = set()
  102.     pairs = []
  103.  
  104.     for l in str_data.strip().split('\n'):
  105.         pieces = (l + ';').split(' ')
  106.         pieces_chosen = [pieces[x][:-1].split('=')[-1] for x in (2, 3, 8, 9)]
  107.         x1, y1, x2, y2 = map(int, pieces_chosen)
  108.         sensors.add(Point(x1, y1))
  109.         beacons.add(Point(x2, y2))
  110.         pairs.append((Point(x1, y1), Point(x2, y2)))
  111.  
  112.     return sensors, beacons, pairs
  113.  
  114.  
  115. def main():
  116.     real = open('day15-real.txt').read().strip()
  117.     part1(real, LIMIT_P1)
  118.     part2(real, Point(0, 0), Point(LIMIT_P2, LIMIT_P2))
  119.  
  120.  
  121. if __name__ == '__main__':
  122.     main()
  123.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement