diff --git a/2022/python/day15.py b/2022/python/day15.py index 048b63b..978f20b 100644 --- a/2022/python/day15.py +++ b/2022/python/day15.py @@ -1,10 +1,16 @@ import matrix import math +import sys from pprint import pprint import shared from scanf import scanf +from typing import Optional from dataclasses import dataclass + + +LIMIT = 4000000 + #def fuckoff_ill_do_my_own_cityblock(y1,x1, y2,x2): def cityblock(y1,x1, y2,x2): return abs(y2-y1) + abs(x2-x1) @@ -15,6 +21,7 @@ class Sensor: sY: int bX: int bY: int + _d: int = None @property def s(self): @@ -26,7 +33,9 @@ class Sensor: @property def distance(self): - return cityblock(self.sY,self.sX, self.bY, self.bX) + if self._d is None: + self._d = cityblock(self.sY,self.sX, self.bY, self.bX) + return self._d def distance_to(self, bY, bX): return cityblock(self.sY,self.sX, bY, bX) @@ -44,11 +53,93 @@ class Sensor: return list(range(start[1],end[1]+1)) + def in_diamond(self): + sX,sY = self.sX, self.sY + up_lim = sY - self.distance + dn_lim = sY + self.distance + + le_lim = sX - self.distance + ri_lim = sX + self.distance + + u = (up_lim, sX) + d = (dn_lim, sX) + l = (sY, le_lim) + r = (sY, ri_lim) + + infliction = 1 + height = -1 + for idx, x in enumerate(range(l[1],r[1]+1)): + height += infliction + if (sY, x) == self.s: + infliction = -1 + for y in range(sY-height, sY+height+1): + yield (y,x) +def part1(rows, sample=False): + sensors = [] + sensor_points = [] + beacon_points = [] + ineligible_points = set() + xSet = set() + ySet = set() + for row in rows: + x,y,bx,by = scanf("Sensor at x=%d, y=%d: closest beacon is at x=%d, y=%d", row) + xSet.add(x) + xSet.add(bx) + ySet.add(y) + ySet.add(by) + sensors.append(Sensor(sX=x,sY=y,bX=bx,bY=by)) + minX, maxX = min(xSet),max(xSet) + minY, maxY = min(ySet),max(ySet) -#@shared.profile -def part1(rows): + for sensor in sensors: + sensor_points.append(sensor.s) + beacon_points.append(sensor.b) + if sample: + for yx in sensor.in_diamond(): + ineligible_points.add(yx) + + CHECK_ROW = 2000000 + if sample: + CHECK_ROW = 10 + + ineligible = set() + for s in sensors: + coll = s.on_line(CHECK_ROW) + ineligible.update(coll) + + count_ignoring_current_beacons = 0 + for i in ineligible: + if (CHECK_ROW, i) not in beacon_points: + count_ignoring_current_beacons += 1 + + print(count_ignoring_current_beacons, "with removing beacons, final answer") + if not sample: + return + + mx = matrix.matrix_of_size(maxX+1, maxY+1) + for yx in ineligible_points: + y,x = yx + if y >= 0 and x >= 0: + if y <= maxY and x <= maxX: + mx[y][x] = "#" + for yx in beacon_points: + y,x = yx + if y >= 0 and x >= 0: + if y <= maxY and x <= maxX: + mx[y][x] = "B" + for yx in sensor_points: + y,x = yx + if y >= 0 and x >= 0: + if y <= maxY and x <= maxX: + mx[y][x] = "S" + print(matrix.ppmx(mx, pad=False,space=True)) + + +tuning = lambda y,x: y + (LIMIT * x) + +def part2(rows): sensors = [] sensor_points = [] beacon_points = [] @@ -67,51 +158,34 @@ def part1(rows): for sensor in sensors: beacon_points.append(sensor.b) - CHECK_ROW = 10 - CHECK_ROW = 2000000 + #coord_range = (0, LIMIT) + coord_range = (0, 20) - print(beacon_points) - print("") ineligible = set() for s in sensors: coll = s.on_line(CHECK_ROW) ineligible.update(coll) - #print(coll) count_ignoring_current_beacons = 0 for i in ineligible: if (CHECK_ROW, i) not in beacon_points: count_ignoring_current_beacons += 1 - - - #print(ineligible) - print(len(ineligible), "without removing beacons") print(count_ignoring_current_beacons, "with removing beacons, final answer") - - # mx[sensor.sY][sensor.sX] = "S" - # mx[sensor.bY][sensor.bX] = "B" - - - - - - -#@shared.profile -def part2(rows): - pass - def main(): + sample = False + if sys.argv[-1] == "--sample": + sample = True rows = [row for row in shared.load_rows(15)] with shared.elapsed_timer() as elapsed: - part1(rows) + part1(rows, sample) print("🕒", elapsed()) - with shared.elapsed_timer() as elapsed: - part2(rows) - print("🕒", elapsed()) + #with shared.elapsed_timer() as elapsed: + # part2(rows) + # print("🕒", elapsed()) if __name__ == "__main__":