import matrix import math from pprint import pprint import shared from scanf import scanf from dataclasses import dataclass from scipy.spatial.distance import cityblock @dataclass class Sensor: sX: int sY: int bX: int bY: int oX: int oY: int @property def s(self): return (self.oY+self.sY, self.oX+self.sX) @property def b(self): return (self.oY+self.bY, self.oX+self.bX) @property def distance(self): a,b = zip(self.s, self.b) return cityblock(a, b) def distance_to(self, y, x): a,b = zip(self.s, (y,x)) return cityblock(a, b) def on_line(self, y): print(self.s) midpoint = (y,self.s[1]) d = self.distance_to(*midpoint) if d > self.distance: print() return [] start = (y, midpoint[1] - abs(self.distance-d)) end = (y, midpoint[1] + abs(self.distance-d)) assert self.distance_to(*start) == self.distance print(self.distance_to(*start),'=',start[1],midpoint[1],end[1]) print(self.distance_to(*end)) print() for x in range(start[1]+1, 9999): d = self.distance_to(y, x) print(x, d) if d == self.distance: print("X should be:", x) break print() return list(range(start[1],end[1])) #@shared.profile def part1(rows): sensors = [] sensor_points = [] beacon_points = [] 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,oY=0, oX=0)) minX, maxX = min(xSet),max(xSet) minY, maxY = min(ySet),max(ySet) offsetX = 0 offsetY = 0 if minX < 0 or minY < 0: o = max(abs(minX), abs(minY)) offsetX = o offsetY = o for sensor in sensors: sensor.oY = offsetY sensor.oX = offsetX beacon_points.append(sensor.b) CHECK_ROW = 10 + offsetY #CHECK_ROW = 2000000 + offsetY print(beacon_points) print("") ineligible = set() for y,x in beacon_points: if y == CHECK_ROW: ineligible.add(x) mx = matrix.matrix_of_size(maxX+offsetX+1, maxY+offsetY+1) for s in sensors: coll = s.on_line(CHECK_ROW) ineligible.update(coll) #print(coll) for i in list(ineligible): if i < 0: continue if i > maxX+offsetX: continue mx[CHECK_ROW][i] = "#" for s in sensors: mx[s.s[0]][s.s[1]] = "S" mx[s.b[0]][s.b[1]] = "B" #print(matrix.ppmx(mx, pad=False, space=False)) print(" 1 1 2 2") print(" 0 5 0 5 0 5") matrix.view_matrix(mx, 11,0, 13, 30) print("") print("####B######################") print(ineligible) print(len(ineligible)) # mx[sensor.sY][sensor.sX] = "S" # mx[sensor.bY][sensor.bX] = "B" #@shared.profile def part2(rows): pass def main(): rows = [row for row in shared.load_rows(15)] with shared.elapsed_timer() as elapsed: part1(rows) print("🕒", elapsed()) with shared.elapsed_timer() as elapsed: part2(rows) print("🕒", elapsed()) if __name__ == "__main__": main()