Saturday, January 10, 2009

Erlang solution for Euler problem 4

In Euler problem number 4 we have to find the largest palindrome number which is the product of two 3-digit numbers.

Once again, since I am only doing this to learn Erlang, I simply went for the brute force approach: try all combinations of 3-digit numbers, multiply them, check whether the product is a palindrome, and remember the biggest one.

While working on this problem, I did learn a couple of interesting things about the if statement in Erlang which seem weird coming from a more traditional language like C++. In Erlang every if statement must have an else clause, even if you don't really need one. Also, you cannot call a function in the condition. Damien Katz's excellent blog on "What sucks about Erlang" discusses these restrictions as well as some other restrictions.

Project Euler has a one-minute rule which says that the run time of a solution must be less than one minute on a modestly powered computer. Although the run time of this solution was obviously less than one minute, I wondered how I would measure it in Erlang. It turns out that this is trivial: just call timer:tc(module, function, arguments). This is described in detail in this article on the trapexit website.

(erlide@cayle-spandons-computer.local)2> timer:tc(euler4, solve, []).
{444625,906609}

Here is my Erlang solution for Euler problem number 4:

%% Author: cayle.spandon
%% Created: Jan 9, 2009
%% Description: Project Euler, problem 4
%%
%% A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers
%% is 9009 = 91 × 99.
%%
%% Find the largest palindrome made from the product of two 3-digit numbers.
%%
%% Use the dumb as a brick brute force approach: try all combinations of two 3-digit numbers, multiply them, check if
%% the product is a palindrome, and remember the biggest one.
%%
%% I'm sure that the project Euler will have something much more clever, but -hey- I am trying to learn Erlang, not
%% trying to become a math genius.

-module(euler4).

-export([solve/0, reverse/1]).

reverse(N) ->
reverse(N, 0).

reverse(N, Reversed) ->
if
N == 0 -> Reversed;
true ->
NLastDigit = N rem 10,
reverse(N div 10, Reversed * 10 + NLastDigit)
end.

isPalindrome(N) ->
N == reverse(N).

solve() ->
solve(100, 100, 0).

solve(N1, N2, BestSoFar) ->
Product = N1 * N2,
case (Product > BestSoFar) and isPalindrome(Product) of
true -> NewBestSoFar = Product;
false -> NewBestSoFar = BestSoFar
end,
if
N1 < 999 -> solve(N1+1, N2, NewBestSoFar);
N1 == 999 ->
if
N2 < 999 -> solve(100, N2+1, NewBestSoFar);
N2 == 999 -> NewBestSoFar
end
end.

2 comments:

Anonymous said...

seems to be less than one minute:
C:\Asm>euler4

Euler 4

i 993 * j 913 = k 906609
70 ms

assembler sucks ;-)

Kalys Osmonov said...

reverse(N) -> reverse(N, 0).
reverse(0, Reversed) -> Reversed;
reverse(N, Reversed) -> reverse(N div 10, Reversed*10 + N rem 10).