Problem #86 concerns the surface area diagonal of rectangular prisms. The question reads:

My solution for this problem definitely falls into the category of brute force. Here is my solution:
Solution #1: Brute Force Approach
Let F(M) be the number of cuboids with this property ignoring rotations with dimensions less than or equal to M. We can observe that F(M) – F(M-1) is the number of cuboids with this property with at least one side length equal to M. Thus, it suffices to count for each possible value of M the number of triples (a,b,M) with a<=b<=M such that a cuboid with sides a, b, M has this property.
It is well known that by looking at the net of a rectangular prism, the surface area diagonal of the prism can have one of the lengths sqrt((a+b)^2+M^2), sqrt((a+M)^2+b^2), or sqrt((b+M)^2+a^2). To minimize the surface area diagonal, it is clear that the value sqrt((a+b)^2+M^2) will be the smallest, because the rate of change of x^2 increases as x increases. We can observe that sqrt((a+b)^2+M^2) <= sqrt(5*M^2). Thus, it suffices to list all square numbers up to 5*M^2 and then binary search the list for each value of (a+b)^2+M^2 to check whether the cuboid with sides a, b, M satisfies the condition. Here is an implementation of this approach in Python 2.7:
'''
Author: Walker Kroubalkian
Brute Force Approach to Project Euler Problem #86
'''
import time
from math import sqrt
def projectEulerProblemEightySix(n):
m = 0
squares = [0]
t = 1
upper = 2*int(sqrt(5*n))+1
while(t<upper):
squares.append(t*t)
t+=1
current = 0
while(current<n):
m+=1
cFactor = squares[m]
for abSum in range(2,2*m+1):
v = squares[abSum]+cFactor
value = binarySearch(squares, v)
if value>-1:
for a in range(max(abSum-m,1),abSum/2+1):
b = abSum - a
if(a<=b):
if b<=m:
current+=1
else:
break
return m
def binarySearch(myList, n):
lower = 0
upper = len(myList)-1
while(lower<upper-1):
middle = (lower+upper)/2
v = myList[middle]
if v>n:
upper = middle
elif v<n:
lower = middle
else:
return middle
if(myList[lower]==n):
return lower
if(myList[upper]==n):
return upper
return -1
start = time.time()
print projectEulerProblemEightySix(1000000)
print ("--- %s seconds ---" % (time.time()-start))
'''
Prints
1818
--- 4.28403687477 seconds ---
for input of n = 1000000.
'''
And with that, we’re done. That took nearly 5 seconds to run. I’d like to come back to this problem at some point to search for a more efficient solution. Binary Search continues to be very useful for improving the efficiency of my code.
Thanks for reading! See you tomorrow.