day15 part 2, wow slowww
This commit is contained in:
parent
75fe308ae0
commit
a8ffeb0f4c
@ -4,14 +4,10 @@ import sys
|
|||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import shared
|
import shared
|
||||||
from scanf import scanf
|
from scanf import scanf
|
||||||
from typing import Optional
|
from typing import Optional, List, Tuple
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LIMIT = 4000000
|
|
||||||
|
|
||||||
#def fuckoff_ill_do_my_own_cityblock(y1,x1, y2,x2):
|
|
||||||
def cityblock(y1,x1, y2,x2):
|
def cityblock(y1,x1, y2,x2):
|
||||||
return abs(y2-y1) + abs(x2-x1)
|
return abs(y2-y1) + abs(x2-x1)
|
||||||
|
|
||||||
@ -21,7 +17,14 @@ class Sensor:
|
|||||||
sY: int
|
sY: int
|
||||||
bX: int
|
bX: int
|
||||||
bY: int
|
bY: int
|
||||||
|
limit: Tuple[int,int] = (0,0)
|
||||||
_d: int = None
|
_d: int = None
|
||||||
|
_edges: List[Tuple[int,int]]= None
|
||||||
|
_border: List[Tuple[int,int]]= None
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (f"Sensor(sX={self.sX}, sY={self.sY}, bX={self.bX},"
|
||||||
|
f"bY={self.bY}, d={self._d}, edges={len(self._edges)}, borders={len(self._borders)})")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def s(self):
|
def s(self):
|
||||||
@ -53,6 +56,13 @@ class Sensor:
|
|||||||
|
|
||||||
return list(range(start[1],end[1]+1))
|
return list(range(start[1],end[1]+1))
|
||||||
|
|
||||||
|
def in_range(self, bY,bX):
|
||||||
|
d = cityblock(self.sY,self.sX, bY, bX)
|
||||||
|
if self.d < d:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def in_diamond(self):
|
def in_diamond(self):
|
||||||
sX,sY = self.sX, self.sY
|
sX,sY = self.sX, self.sY
|
||||||
up_lim = sY - self.distance
|
up_lim = sY - self.distance
|
||||||
@ -75,6 +85,62 @@ class Sensor:
|
|||||||
for y in range(sY-height, sY+height+1):
|
for y in range(sY-height, sY+height+1):
|
||||||
yield (y,x)
|
yield (y,x)
|
||||||
|
|
||||||
|
def edges(self):
|
||||||
|
if self._edges:
|
||||||
|
return self._edges
|
||||||
|
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
|
||||||
|
edges = set()
|
||||||
|
# to left -1 and right + 1
|
||||||
|
for idx, x in enumerate(range(l[1],r[1]+1)):
|
||||||
|
height += infliction
|
||||||
|
if (sY, x) == self.s:
|
||||||
|
infliction = -1
|
||||||
|
edges.add((sY-height,x))
|
||||||
|
edges.add((sY+height,x))
|
||||||
|
self._edges = edges
|
||||||
|
return self._edges
|
||||||
|
|
||||||
|
def border(self):
|
||||||
|
if self._border:
|
||||||
|
return self._border
|
||||||
|
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
|
||||||
|
border = set()
|
||||||
|
# to left -1 and right + 1
|
||||||
|
for idx, x in enumerate(range(l[1]-1,r[1]+2)):
|
||||||
|
height += infliction
|
||||||
|
if (sY, x) == self.s:
|
||||||
|
infliction = -1
|
||||||
|
border.add((sY-height,x))
|
||||||
|
border.add((sY+height,x))
|
||||||
|
self._border = border
|
||||||
|
return self._border
|
||||||
|
|
||||||
|
|
||||||
def part1(rows, sample=False):
|
def part1(rows, sample=False):
|
||||||
sensors = []
|
sensors = []
|
||||||
@ -89,11 +155,14 @@ def part1(rows, sample=False):
|
|||||||
xSet.add(bx)
|
xSet.add(bx)
|
||||||
ySet.add(y)
|
ySet.add(y)
|
||||||
ySet.add(by)
|
ySet.add(by)
|
||||||
sensors.append(Sensor(sX=x,sY=y,bX=bx,bY=by))
|
sensors.append(Sensor(sX=x,sY=y,bX=bx,bY=by,limit=(0,0)))
|
||||||
minX, maxX = min(xSet),max(xSet)
|
minX, maxX = min(xSet),max(xSet)
|
||||||
minY, maxY = min(ySet),max(ySet)
|
minY, maxY = min(ySet),max(ySet)
|
||||||
|
limLo = min(minX,minY)
|
||||||
|
limHi = max(maxX,maxY)
|
||||||
|
|
||||||
for sensor in sensors:
|
for sensor in sensors:
|
||||||
|
sensor.limit = (limLo,limHi)
|
||||||
sensor_points.append(sensor.s)
|
sensor_points.append(sensor.s)
|
||||||
beacon_points.append(sensor.b)
|
beacon_points.append(sensor.b)
|
||||||
if sample:
|
if sample:
|
||||||
@ -136,13 +205,13 @@ def part1(rows, sample=False):
|
|||||||
mx[y][x] = "S"
|
mx[y][x] = "S"
|
||||||
print(matrix.ppmx(mx, pad=False,space=True))
|
print(matrix.ppmx(mx, pad=False,space=True))
|
||||||
|
|
||||||
|
tuning = lambda y,x: y + (4000000 * x)
|
||||||
|
|
||||||
tuning = lambda y,x: y + (LIMIT * x)
|
def part2(rows, sample=False):
|
||||||
|
|
||||||
def part2(rows):
|
|
||||||
sensors = []
|
sensors = []
|
||||||
sensor_points = []
|
sensor_points = []
|
||||||
beacon_points = []
|
beacon_points = []
|
||||||
|
ineligible_points = set()
|
||||||
xSet = set()
|
xSet = set()
|
||||||
ySet = set()
|
ySet = set()
|
||||||
for row in rows:
|
for row in rows:
|
||||||
@ -156,22 +225,66 @@ def part2(rows):
|
|||||||
minY, maxY = min(ySet),max(ySet)
|
minY, maxY = min(ySet),max(ySet)
|
||||||
|
|
||||||
for sensor in sensors:
|
for sensor in sensors:
|
||||||
|
_ = sensor.edges()
|
||||||
|
_ = sensor.border()
|
||||||
|
sensor_points.append(sensor.s)
|
||||||
beacon_points.append(sensor.b)
|
beacon_points.append(sensor.b)
|
||||||
|
if sample:
|
||||||
|
for yx in sensor.in_diamond():
|
||||||
|
ineligible_points.add(yx)
|
||||||
|
|
||||||
#coord_range = (0, LIMIT)
|
L = 4000000
|
||||||
coord_range = (0, 20)
|
if sample:
|
||||||
|
L = 20
|
||||||
|
|
||||||
|
borders = defaultdict(int)
|
||||||
ineligible = set()
|
|
||||||
for s in sensors:
|
for s in sensors:
|
||||||
coll = s.on_line(CHECK_ROW)
|
for yx in s.border():
|
||||||
ineligible.update(coll)
|
y,x = yx
|
||||||
|
if y > 0 and y <= L and x > 0 and x <= L:
|
||||||
count_ignoring_current_beacons = 0
|
borders[yx] += 1
|
||||||
for i in ineligible:
|
|
||||||
if (CHECK_ROW, i) not in beacon_points:
|
TARGET = None
|
||||||
count_ignoring_current_beacons += 1
|
for (eY,eX) in borders.keys():
|
||||||
print(count_ignoring_current_beacons, "with removing beacons, final answer")
|
#print("checking:",(eY,ex))
|
||||||
|
away_from = []
|
||||||
|
for idx, s in enumerate(sensors):
|
||||||
|
d = s.distance_to(eY,eX)
|
||||||
|
if d > s.distance:
|
||||||
|
away_from.append(s.s)
|
||||||
|
if len(away_from) == len(sensors):
|
||||||
|
TARGET = (eY,eX)
|
||||||
|
print(TARGET, tuning(eY,eX))
|
||||||
|
break
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
mx[TARGET[0]][TARGET[1]] = "!"
|
||||||
|
matrix.highlight(mx, blink_green=[TARGET,])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
sample = False
|
sample = False
|
||||||
@ -183,9 +296,9 @@ def main():
|
|||||||
part1(rows, sample)
|
part1(rows, sample)
|
||||||
print("🕒", elapsed())
|
print("🕒", elapsed())
|
||||||
|
|
||||||
#with shared.elapsed_timer() as elapsed:
|
with shared.elapsed_timer() as elapsed:
|
||||||
# part2(rows)
|
part2(rows, sample)
|
||||||
# print("🕒", elapsed())
|
print("🕒", elapsed())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -334,6 +334,6 @@ def highlight(matrix, red=[], green=[], blue=[], blink_green=[]):
|
|||||||
for (y, x) in blink_green:
|
for (y, x) in blink_green:
|
||||||
new = f"{colors.BLINK}{colors.GREEN}{mx[y][x]}{colors.ENDC}"
|
new = f"{colors.BLINK}{colors.GREEN}{mx[y][x]}{colors.ENDC}"
|
||||||
mx[y][x] = new
|
mx[y][x] = new
|
||||||
ppmx(mx, pad=False, space=True, zero="0")
|
print(ppmx(mx, pad=False, space=True, zero="0"))
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user