### Objective

Given a list of lines e.g. count how many points on the line overlap.

A line is specified as a pair of points

e.g. 645,570 -> 517,570

The easiest way to model the problem is as a Line class composed of a pair of Points

``````@dataclass(frozen=True, eq=True, order=True)
class Point:
x: int
y: int

@dataclass(frozen=True, eq=True)
class Line:
start: Point
stop: ``````

Then the Line class implements the function property points as follows

`````` 	@cached_property
def points(self):
if self.horizontal:
return [Point(x, self.start.y)
for x in range(min([self.start.x, self.stop.x]),
max([self.start.x, self.stop.x]) + 1)
]
elif self.vertical:
return [Point(self.start.x, y)
for y in range(min([self.start.y, self.stop.y]),
max([self.start.y, self.stop.y]) + 1)
]

else:
sorted_points = sorted([self.start, self.stop], key=lambda p: p.x)
y_step = 1 if sorted_points[0].y < sorted_points[1].y else -1
y = sorted_points[0].y
points = list()
for x in range(sorted_points[0].x, sorted_points[1].x + 1):
point = Point(x, y)
points.append(point)
y += y_step

return points``````

### Part 1

The solution is just counting how may points overlap. For this we use a Counter after filtering for horizontal and vertical lines, for part 1.

``````def day5_1(vents):
return quantify(Counter([point
for line in vents
for point in line.points
if (line.horizontal or line.vertical)
]).items(),
lambda item: item[1] > 1
)``````

### Part 2

``````def day5_2(vents):
return quantify(Counter([point
for line in vents
for point in line.points
]).items(),
lambda item: item[1] > 1
)``````