from math import dist def solve(input): points = [] for line in open(input): x,y = map(int, line.strip().split(",")) points.append((x,y)) # Part 1: # find the largest rectangle created by two points def areas(): for p in points: for q in points: if p != q: yield area(p,q) # answer 1 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]])) # 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]] # sort lines by y coord lines.sort(key=lambda l: (l[0][1],l[1][1],l[0][0],l[1][0])) #print(lines) # we want to know if the rectangle formed by a pair of points # is completely contained within an axis-aligned polygon. # # 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 = {} ys = sorted(set(p[1] for l in lines for p in l)) for y in ys: # select lines which intersect with the scanline at y mylines = [] for p,q in lines: if p[1] <= y <= q[1]: 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)) #print(ys) #print(bounds) def inbounds(p,q): y0 = min(p[1],q[1]) y1 = max(p[1],q[1]) x0 = min(p[0],q[0]) x1 = max(p[0],q[0]) #print(y0, y1, ys) start = ys.index(y0) for i in range(start,len(ys)): y = ys[i] if y > y1: break if not bounds[y][0] <= x0 <= x1 <= bounds[y][1]: return False return True def inbound_areas(): for p in points: for q in points: if p != q and inbounds(p,q): yield area(p,q) # answer 2 print(max(inbound_areas())) def area(p,q): dx = abs(p[0] - q[0]) + 1 dy = abs(p[1] - q[1]) + 1 return dx*dy solve("sample") solve("input")