Project Euler Problem #115

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(mn), 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.

Published by Walker Kroubalkian

My name is Walker Kroubalkian. I really enjoy math, computer science, and hiking.

Leave a comment

Design a site like this with WordPress.com
Get started