I’ve been immersed in Rails for a few weeks now. It’s been great, but it has come at the expense of pushing ahead and learning more about Ruby. I decided to go back and do another Project Euler problem this week, but it was a bit too easy. Today I took on a more challenging problem, and spent all morning getting it to work.
Project Euler Problem 11
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
1. Take grid and turn it into an array
I obviously needed to be able to access each value, and was pretty sure they had to be integers as I had plans to perform mathematical operations on them later on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
2. Figure out mathematical plan
Rereading the instructions I determined there were four ways (horizontal, vertical, diagonal-right and diagonal-left) that combinations of numbers would be possible. Instead of trying to do this all at once and make one huge class with lots of sub methods, I decided that I would try each method one-by-one and if it produced the correct answer, I would stop.
3. Horizontal Combinations
This was the easiest, so I did it first.
First I tried to find the product of the first 4 numbers.
1 2 |
|
Once I was able to do this for the first 4 numbers, I tried to see if I could do this for any adjacent combiantion of 4 numbers in the first row
1 2 3 4 5 6 7 8 9 |
|
Then I figured out which product of all of these combinations was the greatest in value. As I went further down the rabbit hole I realized it would be helpful to encapsulate this logic into a method, which I did.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
At this point I decided to split my array into nested arrays, with each nested array containing a row of 20 numbers.
1 2 3 4 |
|
Once I had a nested array and a method to find the largest product, I then put the largest product of each row into a new array called answer, and then called the max method on that array to produce (what I hoped would be) the answer to the problem.
1 2 3 4 5 |
|
Unfortunately, this was not the answer, and I had to move on and see if the solution would be a vertical combination.
4. Vertical Combinations
I now needed to make arrays of the columns from my origonal grid. I realized that I could just ‘shift’ off the first element of each of the row arrays I had previously made, and combine them into a new nested array which contained all the columns of data.
1 2 3 4 5 6 7 8 9 |
|
Once I had this new array, I then see what the largest product of 4 adjacet vertical numbers were. I essentially reused the code I did when I did this for the rows of data, just replacing what array I was using. Looking back I could have put this into it’s own method too.
1 2 3 4 5 |
|
As with the horizontal combinations, this did not produce the correct answer. I knew that I was now venturing into more difficult territory with diagonals, but I was so invested in figuring out this problem that I was actually pretty excited.
5. Diagonal-Right Combinations
I tried to figure out what I needed to do in my head, but it wasn’t working. I went into excel and started visualizing it all, which was tremendously helpful.
I ended up determing that what I would do is make arrays of all the diagonals that went down and to the right. The green diagonals on the bottom-left and top-right represent the first and last array, since arrays beyond them would be less than 4 numbers in size. I figured if I started at the bottom-left most array and worked my way up to the top right most array, I would get all the diagonals in one fell swoop.
After some trial-and-error I was able to come up with a way to get all the numbers from a single diagonal line into an array, and then enapsulated it in a method called make_diagonal_array
1 2 3 4 5 6 7 8 9 |
|
Now that I could get a single diagonal array, I had to get all of them. I made a new array called diagonal, and shoveled each diagonal line onto it, again going from the bottom left most diagonal line to the top right most diagonal line. I used some of the same local varaible names that I used in the make_diagonal_array, which I call in the until loop. While this is a bit confusing, it was the least confusing way I could come up with at the time.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Hoping this would finally yield me the correct answer, I used the same code as I had done in the last two attempts.
1 2 3 4 5 |
|
I suppose this was just my lucky day, since this did not produce the right answer. I then went on to try to final set of combiations: diagonal-left.
6. Diagonal-Left
For this step all I had to do was modify the code I made for diagonal-right. This time I would start at the top-left most diagonal and go down to the bottom-right most diagonal. This was suprisingly hard to wrap my head around, but I eventually did with enough fiddling.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
FINALLY!! I got the answer (it’s 70,600,674). This was quite a lot of work, but well worth it. If I were to do some serious refactoring, I could put this all into a class, further encapsulate these methods, and make it all work nicely as one program instead of 4 separate attempts. Perhaps another time though - I need to enjoy the rest of my Saturday!