You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
1.9 KiB
Python
80 lines
1.9 KiB
Python
import re
|
|
from pprint import pprint
|
|
from PIL import Image
|
|
|
|
class Point:
|
|
def __init__(self, pos, vel):
|
|
self.pos = pos
|
|
self.vel = vel
|
|
|
|
def pos_at(self, sec):
|
|
x = self.pos[0] + self.vel[0] * sec
|
|
y = self.pos[1] + self.vel[1] * sec
|
|
return (x, y)
|
|
|
|
def __repr__(self):
|
|
return f'<Point pos={self.pos} vel={self.vel}>'
|
|
|
|
class Picture:
|
|
def __init__(self, width, height):
|
|
self.data = []
|
|
for _ in range(height):
|
|
self.data.append(['.'] * width)
|
|
|
|
def draw(self, x, y):
|
|
self.data[y][x] = '#'
|
|
|
|
def paint(self):
|
|
for row in self.data:
|
|
print(''.join(row))
|
|
|
|
|
|
def parse(point_str):
|
|
pos = (int(point_str[10:16]), int(point_str[17:24]))
|
|
vel = (int(point_str[36:38]), int(point_str[39:42]))
|
|
return(Point(pos, vel))
|
|
|
|
with open('input.txt', 'r') as f:
|
|
points = [parse(x) for x in f.readlines()]
|
|
|
|
def calc_bbox(points, sec):
|
|
coords = [p.pos_at(sec) for p in points]
|
|
|
|
min_x = min([x[0] for x in coords])
|
|
min_y = min([x[1] for x in coords])
|
|
max_x = max([x[0] for x in coords])
|
|
max_y = max([x[1] for x in coords])
|
|
return [(min_x, min_y), (max_x, max_y)]
|
|
|
|
def delta_from_bbox(bbox):
|
|
return (bbox[1][0] - bbox[0][0], bbox[1][1] - bbox[0][1])
|
|
|
|
|
|
def calc_min_res():
|
|
cur_res = 10000000000000000000
|
|
i = 0
|
|
while 1:
|
|
bbox = calc_bbox(points, i)
|
|
delta = delta_from_bbox(bbox)
|
|
res = delta[0] * delta[1]
|
|
if res > cur_res:
|
|
return i - 1
|
|
cur_res = res
|
|
i += 1
|
|
|
|
print('Calculating min res')
|
|
i = calc_min_res()
|
|
print('Finished. Points closest at second:', i)
|
|
|
|
def paint(points, sec):
|
|
coords = [p.pos_at(i) for p in points]
|
|
bbox = calc_bbox(points, sec)
|
|
delta = delta_from_bbox(bbox)
|
|
|
|
pic = Picture(delta[0] + 1, delta[1] + 1)
|
|
for pos in coords:
|
|
pic.draw(pos[0] - bbox[0][0], pos[1] - bbox[0][1])
|
|
pic.paint()
|
|
|
|
paint(points, i)
|