Thursday, January 22, 2009

Erlang solution for Euler problem 18

In project Euler problem number 18 we are asked to determine the maximum sum traveling from the top of a triangle to the base.

This time, I did not solve the problem using the brute-force approach of trying all possible roots from the top to the bottom.

Instead, I rely on the observation that the cost from a to the bottom = cost from a to the bottom + max(cost from b to the bottom, cost from c to the bottom):

x
x x
x x x
a x x x
b c x x x
x x x x x x

This is used to "collapse" the bottom two rows of the triangle into one as follows:

x x
x x x x
x x x ==> x x x
x x x x x x x x
a x x x x d x x x x
b c x x x x

where d = a + max(b,c).

This process is repeated until there is one remaining row which contains the answer.

In Erlang this is implemented as follows:

%% Project Euler, problem 18
%%
%% Find the maximum sum travelling from the top of the triangle to the base.

-module(euler18).
-author('Cayle Spandon').

-export([solve/0]).

-define(TRIANGLE, [[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]].

% Reduce the triangle to a smaller triangle by collapsing the 1st and 2nd row into one.
% If we have collapsed the triangle to a single row with one number, we are done.
%
collapse_triangle([[N]]) ->
N;
collapse_triangle([FirstRow, SecondRow | RemainingRows]) ->
CollapsedRow = collapse_rows(FirstRow, SecondRow),
collapse_triangle([CollapsedRow | RemainingRows]).

% Collapse two rows into one as follows:
% A B
% C --> C' = C + max(A,B)
% When the first row is reduced to a single number, we are done.
%
collapse_rows([_A], []) ->
[];
collapse_rows([A, B | Tail1], [C | Tail2]) ->
[C + max(A, B)] ++ collapse_rows([B | Tail1], Tail2).

max(A, B) ->
if
A > B ->
A;
true ->
B
end.

solve() ->
collapse_triangle(?TRIANGLE).

1 comment:

Anonymous said...

Beautiful solution, thank you for sharing!