advent-of-code/2022/python/day15.py

156 lines
3.4 KiB
Python
Raw Normal View History

2022-12-15 06:17:19 +00:00
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
2022-12-15 15:08:01 +00:00
oX: int
oY: int
2022-12-15 06:17:19 +00:00
@property
def s(self):
2022-12-15 15:08:01 +00:00
return (self.oY+self.sY, self.oX+self.sX)
2022-12-15 06:17:19 +00:00
@property
def b(self):
2022-12-15 15:08:01 +00:00
return (self.oY+self.bY, self.oX+self.bX)
2022-12-15 06:17:19 +00:00
@property
def distance(self):
a,b = zip(self.s, self.b)
return cityblock(a, b)
2022-12-15 15:08:01 +00:00
def distance_to(self, y, x):
2022-12-15 06:17:19 +00:00
a,b = zip(self.s, (y,x))
return cityblock(a, b)
2022-12-15 15:08:01 +00:00
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]))
2022-12-15 06:17:19 +00:00
#@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)
2022-12-15 15:08:01 +00:00
sensors.append(Sensor(sX=x,sY=y,bX=bx,bY=by,oY=0, oX=0))
2022-12-15 06:17:19 +00:00
minX, maxX = min(xSet),max(xSet)
minY, maxY = min(ySet),max(ySet)
2022-12-15 15:08:01 +00:00
offsetX = 0
offsetY = 0
if minX < 0 or minY < 0:
o = max(abs(minX), abs(minY))
offsetX = o
offsetY = o
2022-12-15 06:17:19 +00:00
for sensor in sensors:
2022-12-15 15:08:01 +00:00
sensor.oY = offsetY
sensor.oX = offsetX
2022-12-15 06:17:19 +00:00
beacon_points.append(sensor.b)
2022-12-15 15:08:01 +00:00
CHECK_ROW = 10 + offsetY
#CHECK_ROW = 2000000 + offsetY
print(beacon_points)
print("")
2022-12-15 06:17:19 +00:00
ineligible = set()
2022-12-15 15:08:01 +00:00
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:
2022-12-15 06:17:19 +00:00
continue
2022-12-15 15:08:01 +00:00
if i > maxX+offsetX:
2022-12-15 06:17:19 +00:00
continue
2022-12-15 15:08:01 +00:00
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)
2022-12-15 06:17:19 +00:00
print(len(ineligible))
2022-12-15 15:08:01 +00:00
2022-12-15 06:17:19 +00:00
# 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()