day 9 cleanup
This commit is contained in:
parent
92138cf8e5
commit
0dcd675042
60
day09/sol.py
60
day09/sol.py
@ -1,31 +1,54 @@
|
|||||||
from math import dist
|
from math import dist
|
||||||
|
|
||||||
def solve(input):
|
def solve(input):
|
||||||
points = []
|
points = []
|
||||||
for line in open(input):
|
for line in open(input):
|
||||||
x,y = map(int, line.strip().split(","))
|
x,y = map(int, line.strip().split(","))
|
||||||
points.append((x,y))
|
points.append((x,y))
|
||||||
|
|
||||||
|
# Part 1:
|
||||||
|
# find the largest rectangle created by two points
|
||||||
|
|
||||||
def areas():
|
def areas():
|
||||||
for p in points:
|
for p in points:
|
||||||
for q in points:
|
for q in points:
|
||||||
if p != q:
|
if p != q:
|
||||||
yield area(p,q)
|
yield area(p,q)
|
||||||
|
|
||||||
|
# answer 1
|
||||||
print(max(areas()))
|
print(max(areas()))
|
||||||
|
|
||||||
|
# Part 2:
|
||||||
|
# find the largest rectangle formed by a pair of points
|
||||||
|
# which is contained within the polygon defined by the list of points.
|
||||||
|
|
||||||
lines = list(zip(points, points[1:]+[points[0]]))
|
lines = list(zip(points, points[1:]+[points[0]]))
|
||||||
# keep only vertical lines, and sort so the uppermost point (lowest x coord) is the first of the pair
|
# keep only vertical lines, and sort so the uppermost point (lowest y coord) is the first of the pair
|
||||||
lines = [(min(p,q),max(p,q)) for p,q in lines if p[1] != q[1]]
|
lines = [(min(p,q),max(p,q)) for p,q in lines if p[1] != q[1]]
|
||||||
# sort by y coord
|
# sort lines by y coord
|
||||||
lines.sort(key=lambda l: (l[0][1],l[1][1],l[0][0],l[1][0]))
|
lines.sort(key=lambda l: (l[0][1],l[1][1],l[0][0],l[1][0]))
|
||||||
print(lines)
|
|
||||||
|
#print(lines)
|
||||||
|
|
||||||
# we want to know if the rectangle formed by a pair of points
|
# we want to know if the rectangle formed by a pair of points
|
||||||
# is completely contained within the axis-aligned polygon defined
|
# is completely contained within an axis-aligned polygon.
|
||||||
# by the list of points.
|
|
||||||
# we can do that with a scanline algorithm:
|
|
||||||
# for each x position in the list of points,
|
|
||||||
#
|
#
|
||||||
|
# we can do that with a pseudo-scanline algorithm.
|
||||||
|
#
|
||||||
|
# we make a couple simplifying assumptions:
|
||||||
|
# 1. first, that the polygon is not self-intersecting
|
||||||
|
# 2. second, that the polygon is not "U shaped" --
|
||||||
|
# that is, it has a definite, single width in every horizontal slice
|
||||||
|
# and it doesn't curve around at all -- so we don't have to worry
|
||||||
|
# about voids
|
||||||
|
#
|
||||||
|
# for each y position, we first calculate the horizontal bounds of the
|
||||||
|
# polygon at that line.
|
||||||
|
#
|
||||||
|
# then, to test if a rectangle is contained within the polygon,
|
||||||
|
# we just need to iterate through the y positions which fall inside the rectangle
|
||||||
|
# and check whether the rectangle would exceed the previously computed bounds
|
||||||
|
# of the polygon at any of those points.
|
||||||
|
|
||||||
bounds = {}
|
bounds = {}
|
||||||
ys = sorted(set(p[1] for l in lines for p in l))
|
ys = sorted(set(p[1] for l in lines for p in l))
|
||||||
@ -34,11 +57,14 @@ def solve(input):
|
|||||||
mylines = []
|
mylines = []
|
||||||
for p,q in lines:
|
for p,q in lines:
|
||||||
if p[1] <= y <= q[1]:
|
if p[1] <= y <= q[1]:
|
||||||
mylines.append(p[0])
|
mylines.append(p[0]) # only keep the x coord
|
||||||
|
# since we are assuming no self-intersection and no voids,
|
||||||
|
# the bounds on this line are just the leftmost and rightmost
|
||||||
|
# x coordinate of the intersecting lines
|
||||||
bounds[y] = (min(mylines),max(mylines))
|
bounds[y] = (min(mylines),max(mylines))
|
||||||
|
|
||||||
print(ys)
|
#print(ys)
|
||||||
print(bounds)
|
#print(bounds)
|
||||||
|
|
||||||
def inbounds(p,q):
|
def inbounds(p,q):
|
||||||
y0 = min(p[1],q[1])
|
y0 = min(p[1],q[1])
|
||||||
@ -46,21 +72,23 @@ def solve(input):
|
|||||||
x0 = min(p[0],q[0])
|
x0 = min(p[0],q[0])
|
||||||
x1 = max(p[0],q[0])
|
x1 = max(p[0],q[0])
|
||||||
#print(y0, y1, ys)
|
#print(y0, y1, ys)
|
||||||
i = ys.index(y0)
|
start = ys.index(y0)
|
||||||
j = ys.index(y1) + 1
|
for i in range(start,len(ys)):
|
||||||
for y in ys[i:j]:
|
y = ys[i]
|
||||||
|
if y > y1:
|
||||||
|
break
|
||||||
if not bounds[y][0] <= x0 <= x1 <= bounds[y][1]:
|
if not bounds[y][0] <= x0 <= x1 <= bounds[y][1]:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def areas2():
|
def inbound_areas():
|
||||||
for p in points:
|
for p in points:
|
||||||
for q in points:
|
for q in points:
|
||||||
if p != q and inbounds(p,q):
|
if p != q and inbounds(p,q):
|
||||||
yield area(p,q)
|
yield area(p,q)
|
||||||
|
|
||||||
print(max(areas2()))
|
# answer 2
|
||||||
|
print(max(inbound_areas()))
|
||||||
|
|
||||||
def area(p,q):
|
def area(p,q):
|
||||||
dx = abs(p[0] - q[0]) + 1
|
dx = abs(p[0] - q[0]) + 1
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user