52 lines
1.8 KiB
Python
Raw Permalink Normal View History

2022-12-15 17:06:33 +01:00
# SPDX-License-Identifier: MIT
# Copyright (c) 2022 Akumatic
#
# https://adventofcode.com/2022/day/15
from re import findall
def read_file(filename: str = "input.txt") -> list:
pattern = "Sensor at x=(.+), y=(.+): closest beacon is at x=(.+), y=(.*)"
with open(f"{__file__.rstrip('code.py')}{filename}", "r") as f:
return [[int(x) for x in findall(pattern, line)[0]] for line in f.readlines()]
def combine_ranges(ranges: list) -> list:
new_ranges = list()
start, stop = ranges[0]
for i in range(1, len(ranges)):
if ranges[i][0] > stop:
new_ranges.append(range(start, stop))
start, stop = ranges[i]
continue
if ranges[i][1] > stop:
stop = ranges[i][1]
new_ranges.append(range(start, stop))
return new_ranges
def get_blocked_ranges(coords: list, line: int, _min = float('-inf'), _max = float('inf')) -> list:
ranges = list()
for sx, sy, bx, by in coords:
sb_dist = abs(bx - sx) + abs(by - sy)
height_dist = abs(sy - line)
if height_dist > sb_dist:
continue
x_min = max(sx - (sb_dist - height_dist), _min)
x_max = min(sx + (sb_dist - height_dist), _max)
ranges.append((x_min, x_max))
return combine_ranges(sorted(ranges))
def part1(vals: list, test: bool = False) -> int:
return sum(len(r) for r in get_blocked_ranges(vals, 10 if test else 2000000))
def part2(vals: list, test: bool = False) -> int:
max_val = 20 if test else 4000000
for i in range(max_val + 1):
ranges = get_blocked_ranges(vals, i, 0, max_val)
if len(ranges) > 1:
return (ranges[0].stop + 1) * 4000000 + i
if __name__ == "__main__":
vals = read_file()
print(f"Part 1: {part1(vals)}")
print(f"Part 2: {part2(vals)}")