Find the maximum sum travelling from the top of the triangle to the base.
Here is a little example:
1
3 2
4 1 6
I have marked the maximum sum with red numbers. For a small triangle of numbers like this you could easily brute force the solution and just check all paths from the top to the bottom. For a large triangle, that would be too labour intensive. A better solution, I think, is to coalesce the rows of the triangle working from the bottom up. So, in this simple example, you would first replace the second row with the maximum value possible by adding a number in that row to the two numbers below it in the triangle. In this case, 3 + 4 > 3 + 1 so you would replace 3 by 7 and 2 + 6 > 2 + 1 so you'd replace 2 by 8. That would reduce the triangle to this:
1
7 8
Performing the same step on the reduced triangle would give you the final answer (since 1 + 8 > 1 + 7).
9
To solve this problem I put the data into an array of arrays:
let data =
[|
[|04; 62; 98; 27; 23; 09; 70; 98; 73; 93; 38; 53; 60; 04; 23|];
[|63; 66; 04; 68; 89; 53; 67; 30; 73; 16; 69; 87; 40; 31|];
[|91; 71; 52; 38; 17; 14; 91; 43; 58; 50; 27; 29; 48|];
[|70; 11; 33; 28; 77; 73; 17; 78; 39; 68; 17; 57|];
[|53; 71; 44; 65; 25; 43; 91; 52; 97; 51; 14|];
[|41; 48; 72; 33; 47; 32; 37; 16; 94; 29|];
[|41; 41; 26; 56; 83; 40; 80; 70; 33|];
[|99; 65; 04; 28; 06; 16; 70; 92|];
[|88; 02; 77; 73; 07; 63; 67|];
[|19; 01; 23; 75; 03; 34|];
[|20; 04; 82; 47; 65|];
[|18; 35; 87; 10|];
[|17; 47; 82|];
[|95; 64|];
[|75|]
|]
You will notice that I inverted the triangle so that the widest part is at the bottom. I wanted my algorithm to proceed from the start of the array to end and not vice versa.
Next I defined a helper function:
let max x y = if x < y then y else x
Now I want a function that will coalesce two arrays into one:
let coalesce (a:int[]) (b:int[]) =
[| for i in 0..b.Length-1 -> max (a.[i]+b.[i]) (a.[i+1]+b.[i]) |]
So, the idea here is that two one-dimensional arrays are passed in. The first one is assumed to be one longer than the second (in production code you'd probably want to enforce the precondition). This function creates a new one-dimensional array with the same length as the second input array. Each entry in the new array is the max of the entry in the second array with either of the numbers above it in the first array.
Finally, I want to apply the coalesce operation to the entire data array:
data |> Array.fold coalesce (Array.zeroCreate (data.[0].Length+1)) |> printfn "%A"
I have created an array with length one greater than the maximum line in the data array and I'm using that as the state accumulator passed to the fold function. At each step in the fold operation it will be replaced by an array one entry smaller until, when it's done, there will just be an array with a single element which will be the final answer.
I should note that one potential problem with this solution arises if you want to know the actual path that led to the answer.
No comments:
Post a Comment