Duncan's blog

October 29, 2008

Project Euler: problem 11

Filed under: Coldfusion,Project Euler — duncan @ 7:00 am
Tags: , , , , ,

This is one of those problems that at first glance looks really difficult, but when it comes down to it, wasn’t that hard.

Problem 11

In the 20 x 20 grid below, four numbers along a diagonal line have been marked in red.

08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48

The product of these numbers is 26 x 63 x 78 x 14 = 1788696.

What is the greatest product of four adjacent numbers in any direction (up, down, left, right, or diagonally) in the 20 x 20 grid?

One thing it doesn’t mention in that spec is if the numbers have to be in a straight line, or if it means it could be up, left, diagonal, right all in the same set of four.  However, in the list of all the problems, it summarises it as "What is the greatest product of four numbers on the same straight line in the 20 by 20 grid?"

So basically this can be done with four sets of nested loops, one each for horizontal, vertical, and the two diagonals.

Going diagonally, we have to exclude some values in opposing corners. Laying it out like this helped me visualise what I need to do in the code:

Diagonal 1:

08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48

Diagonal 2:

08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48

This one was a bit like problem 8, with a large block of numbers which is ideal for plugging into <cfsavecontent>. Use a nested loop when constructing the array, as our block of numbers is delimited on the line by CRLF, and delimited between the numbers by spaces.

<cfsavecontent variable="grid">
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
</cfsavecontent>

<cfset numbers = ArrayNew(2)>
<cfset m = 1>
<cfset max = 0>
<cfset product = 0>

<!--- store all this in a 2D array --->
<cfloop index="i" list="#grid#" delimiters="#Chr(13)##Chr(10)#">
	<cfset n = 1>
	<cfloop index="j" list="#i#" delimiters=" ">
		<cfset numbers[m][n] = j>
		<cfset n = n + 1>
	</cfloop>
	<cfset m = m + 1>	
</cfloop>


<!--- across --->
<cfloop index="i" from="1" to="#ArrayLen(numbers)#">
	<cfloop index="j" from="1" to="#(ArrayLen(numbers[i])-3)#">
		<cfset product =numbers[i][j] 	* 
				numbers[i][j+1]	* 
				numbers[i][j+2]	* 
				numbers[i][j+3]>
		<cfif product GT max>
			<cfset max = product>
		</cfif>
	</cfloop>
</cfloop>

<!--- down --->
<cfloop index="i" from="1" to="#(ArrayLen(numbers)-3)#">
	<cfloop index="j" from="1" to="#ArrayLen(numbers[i])#">
		<cfset product =numbers[i][j] 	* 
				numbers[i+1][j]	* 
				numbers[i+2][j]	* 
				numbers[i+3][j]>
		<cfif product GT max>
			<cfset max = product>
		</cfif>
	</cfloop>
</cfloop>

<!--- diagonally 1, \\\\ --->
<cfloop index="i" from="1" to="#(ArrayLen(numbers)-3)#">
	<cfloop index="j" from="1" to="#(ArrayLen(numbers[i])-3)#">
		<cfset product =numbers[i][j]		* 
				numbers[i+1][j+1]	* 
				numbers[i+2][j+2]	* 
				numbers[i+3][j+3]>
		<cfif product GT max>
			<cfset max = product>
		</cfif>
	</cfloop>
</cfloop>

<!--- diagonally 2, //// --->
<cfloop index="i" from="4" to="#ArrayLen(numbers)#">
	<cfloop index="j" from="1" to="#(ArrayLen(numbers[i])-3)#">
		<cfset product =numbers[i][j]		* 
				numbers[i-1][j+1]	* 
				numbers[i-2][j+2]	* 
				numbers[i-3][j+3]>
		<cfif product GT max>
			<cfset max = product>
		</cfif>
	</cfloop>
</cfloop>

<cfoutput><strong>#max#</strong></cfoutput>

For each of the loops, we don’t want to go all the way to the end of the line. For instance on the horizontal one, we loop as far as the 3rd last, because we’re going to grab those last 3 values anyway.
The vertical loop just switches round the values for i and j from the horizontal loop.
The diagonal loops require manipulating both i and j values.

3 Comments »

  1. so what will the last answer be?
    Can it be solved by other programs like python?

    Comment by Fari — January 2, 2010 @ 10:16 am | Reply

  2. The last answer, well you’ll have to work that out yourself! This problem can certainly be solved with Python or most other programming languages. Try re-thinking my code into pseudocode / ‘structured english’, then rewrite into the language of your choice.

    Comment by duncan — January 2, 2010 @ 10:30 am | Reply

  3. […] previously blogged about this Project Euler puzzle 6 years ago, using ColdFusion.  This is my approach using PHP as a simple practical exercise for myself, and […]

    Pingback by Project Euler: problem 11 (PHP) | Duncan's blog — September 29, 2014 @ 8:05 am | Reply


RSS feed for comments on this post. TrackBack URI

Leave a comment

Create a free website or blog at WordPress.com.