aoc2022/day15.py
2022-12-15 07:36:26 +01:00

105 lines
3.1 KiB
Python

from collections import defaultdict
from tools.aoc import AOCDay
from typing import Any
def flatten(what: set) -> set:
found_something = True
while found_something:
found_something = False
liqlist = []
for c in what:
for c2 in liqlist:
if c[0] <= c2[0] and c[1] >= c2[1]:
found_something = True
c2[0] = c[0]
c2[1] = c[1]
elif c[0] >= c2[0] and c[1] <= c2[1]:
found_something = True
break
elif c2[0] <= c[1] < c2[1]:
found_something = True
c2[0] = c[0]
break
elif c2[0] <= c[0] < c2[1]:
found_something = True
c2[1] = c[1]
break
else:
liqlist.append([c[0], c[1]])
what = set((x[0], x[1]) for x in liqlist)
return what
class Day(AOCDay):
inputs = [
[
(26, "input15_test"),
(6275922, "input15"),
],
[
(56000011, "input15_test"),
(11747175442119, "input15"),
]
]
def get_sensor_beacon_dict(self):
sensors = {}
for line in self.getInput():
sp = line.split(" ")
sx, sy, bx, by = sp[2], sp[3], sp[8], sp[9]
sx = int(sx[2:-1])
sy = int(sy[2:-1])
bx = int(bx[2:-1])
by = int(by[2:])
sensors[(sx, sy)] = (bx, by)
return sensors
def part1(self) -> Any:
liq = 10 if self._current_test_file.endswith("_test") else 2000000
liqset = set()
for sensor, beacon in self.get_sensor_beacon_dict().items():
d = abs(sensor[0] - beacon[0]) + abs(sensor[1] - beacon[1])
if sensor[1] - d > liq > sensor[1] + d:
continue
r = 2 * (d - abs(sensor[1] - liq)) + 1
if r < 1:
continue
x_min, x_max = sensor[0] - r // 2, sensor[0] + r // 2
liqset.add((x_min, x_max))
liqset = flatten(liqset)
return sum(x[1] - x[0] for x in liqset)
def part2(self) -> Any:
max_c = 20 if self._current_test_file.endswith("_test") else 4000000
occ = defaultdict(set)
for sensor, beacon in self.get_sensor_beacon_dict().items():
d = abs(sensor[0] - beacon[0]) + abs(sensor[1] - beacon[1])
for y in range(-d, d + 1):
r = 2 * (d - abs(y)) + 1
if 0 <= sensor[1] + y <= max_c:
occ[sensor[1] + y].add((max(0, sensor[0] - r // 2), min(sensor[0] + r // 2, max_c)))
for y, occs in occ.items():
occs = flatten(occs)
assert len(occs) in [1, 2]
if len(occs) == 2:
f = list(occs)
min_y = min(x[1] for x in f)
max_x = max(x[0] for x in f)
if max_x - min_y == 2:
return (min_y + 1) * 4000000 + y
return ""
if __name__ == '__main__':
day = Day(2022, 15)
day.run(verbose=True)