Problem #115 concerns separating rows of blocks into red sections and black sections. The question reads:
Project Euler Problem 115: Counting block combinations II NOTE: This is a more difficult version of Problem 114. A row measuring n units in length has red blocks with a minimum length of m units placed on it, such that any two red blocks (which are allowed to be different lengths) are separated by at least one black square. Let the fill-count function, F(m, n), represent the number of ways that a row can be filled. For example, F(3, 29) = 673135 and F(3, 30) = 1089155. That is, for m = 3, it can be seen that n = 30 is the smallest value for which the fill-count function first exceeds one million. In the same way, for m = 10, it can be verified that F(10, 56) = 880711 and F(10, 57) = 1148904, so n = 57 is the least value for which the fill-count function first exceeds one million. For m = 50, find the least value of n for which the fill-count function first exceeds one million.
My solution is almost identical to my solution for Problem #114. Therefore, I will not repeat the details for the recursions that I used. Here’s my solution:
Solution #1: Dynamic Programming Approach
As I did in Problem #114, we separate the recursion into tilings that end in a red square and tilings that end in a grey square. The recursions are nearly identical to the ones in Problem #114, and the initial conditions can easily be extended to account for the larger minimal red tilings. From this point, it is only a matter of applying the recursion repeatedly until a value with over 1000000 different tilings is obtained. Here is an implementation of this approach in Python 2.7:
''' Author: Walker Kroubalkian Dynamic Approach to Project Euler Problem #115 ''' import time def projectEulerProblemOneHundredFifteen(m,n): rTotals = [0]*m rTotals.append(1) gTotals = [1]*(m+1) sumG = sum(gTotals) l = len(gTotals) v = rTotals[l-1]+gTotals[l-1] while(v<=n): rValue = sumG for x in range(1,m): rValue-=gTotals[l-x] gValue = v rTotals.append(rValue) gTotals.append(gValue) sumG+=gValue l+=1 v = rTotals[l-1]+gTotals[l-1] return l-1 start = time.time() print projectEulerProblemOneHundredFifteen(50, 1000000) print ("--- %s seconds ---" % (time.time()-start)) ''' Prints 168 --- 0.000357866287231 seconds --- for input of m = 50, n = 1000000. '''
And with that, we’re done. Once again, dynamic programming proves to be invaluable at solving recursive problems.
Thanks for reading! See you tomorrow.