Selaa lähdekoodia

Improve day 15

Taddeus Kroes 3 vuotta sitten
vanhempi
sitoutus
821965b137
1 muutettua tiedostoa jossa 21 lisäystä ja 28 poistoa
  1. 21 28
      2022/15_beacon.py

+ 21 - 28
2022/15_beacon.py

@@ -2,39 +2,32 @@
 import sys
 import re
 
-def ranges(sensors, y):
-    intervals = set()
-
-    def pop_overlapping(a, b):
-        for other in intervals:
-            c, d = other
-            if a <= d and c <= b:
-                intervals.remove(other)
-                return min(a, c), max(b, d)
-
+def intervals(sensors, y):
     for sx, sy, bx, by in sensors:
-        dist = abs(sx - bx) + abs(sy - by) - abs(sy - y)
-        if dist >= 0:
-            interval = sx - dist, sx + dist
-            new = pop_overlapping(*interval)
-            while new:
-                interval = new
-                new = pop_overlapping(*interval)
-            intervals.add(interval)
-
-    return intervals
+        dx = abs(sx - bx) + abs(sy - by) - abs(sy - y)
+        if dx >= 0:
+            yield sx - dx, sx + dx
 
 def coverage(sensors, y):
-    covered = sum(r - l + 1 for l, r in ranges(sensors, y))
+    l, r = zip(*intervals(sensors, y))
     beacons = len(set(bx for _, _, bx, by in sensors if by == y))
-    return covered - beacons
+    return max(r) + 1 - min(l) - beacons
+
+def border(x, y, radius):
+    for dx in range(radius + 2):
+        dy = radius + 1 - dx
+        yield x + dx, y + dy
+        yield x + dx, y - dy
+        yield x - dx, y + dy
+        yield x - dx, y - dy
 
-def frequency(sensors, ymax):
-    for y in range(ymax + 1):
-        r = ranges(sensors, y)
-        if len(r) == 2:
-            (a, _), (b, _) = r
-            return (max(a, b) - 1) * 4000000 + y
+def frequency(sensors, limit):
+    rad = [(sx, sy, abs(sx - bx) + abs(sy - by)) for sx, sy, bx, by in sensors]
+    for sensor in rad:
+        for x, y in border(*sensor):
+            if 0 <= x <= limit and 0 <= y <= limit and \
+                    all(abs(x - sx) + abs(y - sy) > r for sx, sy, r in rad):
+                return x * 4000000 + y
 
 sensors = [tuple(map(int, re.findall(r'-?\d+', line))) for line in sys.stdin]
 print(coverage(sensors, 2000000))