Functional Programming: Shaping the data to fit a function

As I mentioned in my last post I’ve been working on Project Euler problem 11 and one thing I noticed was that I was shaping the data around a windowed function since it seemed to fit the problem quite well.

In the 20x20 grid below, four numbers along a diagonal line have been marked in red.
The product of these numbers is 26 63 78 14 = 1788696.
What is the greatest product of four adjacent numbers in any direction (up, down, left, right, or diagonally) in the 20x20 grid?

I needed to get all the horizontals, verticals and diagonals into collections that I could then apply the function to and get the four adjacent numbers required by the problem.

In the first case we’re just running a map operation over each row and converting it into groups of 4 adjacent elements. By using concatMap we can ensure that the result is flattened back into a single collection.

To get the top to bottom values I had to first create a new array of arrays built up using values at the same column index in each row before applying the windowed function.

I found it much more difficult to get the diagonals into the right shape but luckily I bumped into Uday who helped me figure it out.

We started off by working out how to calculate all the numbers diagonally left to right from a specific point which resulted in this function:

diagonalPositions creates a sequence of pairs which contain all the different positions in the grid where we want to try and find a diagonal from. We then map over that in diagonals and find the diagonal from each of those places.

We then had to do the same to find diagonals running from right to left:

Obviously there’s a lot of duplication in this solution so another exercise for me is to try and make it a bit more concise!

I think I picked up this way of solving problems from playing around with clojure last year and it seems quite neat although I’m sure it might not seem that intuitive to someone who hadn’t seen it before.