Day 5 - Overlapping vents

Oh boy, more cartesian coordinates.

We're going to read in the pairs of coordinates, we can filter at this point for only horizontal or vertical coordinates and then we're loooking for intersecting lines. There's probably a fancy mathmatical way to do this, but I suspect it's easier to just plot each line on a grid.

First, lets parse the input into lines

Right, we can turn the numbers into coordinates. We're going to use the filter command, but we need a function that can spot non-horizontal or vertical lines, so let's write that first

Now we can filter the list down to just the vertical and horizontal ones

Now we just have to apply those lines to a grid, and then walk the line adding 1 to each number in that coordinate. We're going to need to return a list of coordinates from a start/stop position, and then we're going to want to use some kind of grid object to keep track of the lines.

When we're calculating the lines, we need to remmeber that we wont know whether the start point is left or right of the end point. So we can use min(start.x, stop.x) to find the lowest x, and max(start.x, stop.x) to find the highest x.

Ok, that works. We initialise a grid, and then get all the values out, and filter for only the ones greater than 1 and then the length of the list is the number.

Let's try this all on some production data

Boom! That works. Now onto

Part 2 - Diagonals

This should be fairly easy, we now need to account for diagonal lines. We're told that we never have to worry about non-45 degree lines, so each line will increase by +/- 1 in each direction.

Luckily this just means redefining the line_from_coords, and not filtering the list.

Our line_from_coords now needs to handle not just determining if it's horizontal or vertical, but also diagonal.

That algorithm took a lot of tweaking to get right. In this case I had optimised myself into a corner that took a bit of thinking to get out of. Because in the earlier ones, I was using the min(start.x,stop.x) to ensure that the lines always went from left to right or from top to bottom, I had that same thing in here. But doing that made the algorithm far more complex when trying to work out how to calculate the ith item.

I had to stop and rethink from first principles. I remembered the old Bresenham's algorithm for drawing straight lines, which uses basic maths to work out the gradient of a line, the length of a line, and then uses a dx and dy to increment the pixel when needed. (You can find that here: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm)

In this case, we have a guaranteed easier case, we are only dealing with 45 degree lines, and that means that every movement in one axis will be mirrored in a movement in another. That means we can just walk the length of the line in any given direction, and work out all of the parts in another direction. If we were doing that to say 30 degree lines, we'd probably end up with missing bits.

Anyway, now we can generate the lines, we can simply take the prod data, not filter it, and run it through our new function and apply the grid again.