# ndpar/algorithms

Solved firest 10 problems

Andrey Paramonov committed Feb 27, 2010
0 parents commit 6241c3ea6f60db044452e8e5ceabd3e236e904ba
Showing with 459 additions and 0 deletions.
1. +52 −0 mymath.erl
2. +22 −0 p001.erl
3. +60 −0 p002.erl
4. +47 −0 p003.erl
5. +37 −0 p004.erl
6. +59 −0 p005.erl
7. +43 −0 p006.erl
8. +41 −0 p007.erl
9. +51 −0 p008.erl
10. +31 −0 p009.erl
11. +16 −0 p010.erl
 @@ -0,0 +1,52 @@ +-module(mymath). +-export([primes_upto/1]). +-include_lib("eunit/include/eunit.hrl"). + +%% Find all prime numbers upto specified value. +%% +primes_upto(N) -> eratosthenes(math:sqrt(N), lists:seq(2, N)). + + +%% Functional implementation of Eratosthenes sieve algorithm +%% http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes +%% +%% Very clean but very slow. Works relatively fast for N < 100,000 +%% +eratosthenes_sieve([]) -> []; +eratosthenes_sieve([P|Xs]) -> [P | eratosthenes_sieve([X || X <- Xs, X rem P > 0])]. + + +%% Functional implementation of Euler sieve algorithm +%% +%% Very clean but very slow. Works relatively fast for N < 10,000 +%% +euler_sieve([]) -> []; +euler_sieve([P|Xs]) -> [P | euler_sieve(Xs -- lists:map(fun(X) -> X*P end, [P|Xs]))]. + + +%% Recursion implementation of Eratosthenes sieve algorithm +%% Author: Zac Brown +%% +%% Not so obvious but very efficient +%% +eratosthenes(Max, [H|T]) when H =< Max -> [H | eratosthenes(Max, sieve([H|T], H))]; +eratosthenes(_Max, L) -> L. + +sieve([H|T], N) when H rem N =/= 0 -> [H | sieve(T, N)]; +sieve([_H|T], N) -> sieve(T, N); +sieve([], _N) -> []. + +%% Tests + +primes_upto_30_test() -> + ?assertEqual([2, 3, 5, 7, 11, 13, 17, 19, 23, 29], primes_upto(30)). + +primes_upto_2m_test() -> + ?assertEqual(1999993, lists:last(primes_upto(2000000))). + + +euler_sieve_test() -> + ?assertEqual([2, 3, 5, 7, 11, 13, 17, 19, 23, 29], euler_sieve(lists:seq(2, 30))). + +eratosthenes_sieve_test() -> + ?assertEqual([2, 3, 5, 7, 11, 13, 17, 19, 23, 29], eratosthenes_sieve(lists:seq(2, 30))).
 @@ -0,0 +1,22 @@ +%% Problem +%% --------------------- +%% If we list all the natural numbers below 10 that are multiples of 3 or 5, +%% we get 3, 5, 6 and 9. The sum of these multiples is 23. +%% +%% Find the sum of all the multiples of 3 or 5 below 1000. +%% --------------------- + +-module(p001). +-include_lib("eunit/include/eunit.hrl"). + +multiples35(N) -> + [X || X <- lists:seq(1, N), (X rem 3 =:= 0) or (X rem 5 =:= 0)]. + +multiples35_test() -> + ?assertEqual(466, length(multiples35(999))). + +result() -> + lists:sum(multiples35(999)). + +result_test() -> + ?assertEqual(233168, result()).
 @@ -0,0 +1,60 @@ +%% Problem +%% --------------------- +%% Each new term in the Fibonacci sequence is generated by adding the previous two terms. +%% By starting with 1 and 2, the first 10 terms will be: +%% 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... +%% +%% Find the sum of all the even-valued terms in the sequence which do not exceed four million. +%% --------------------- + +-module(p002). +-include_lib("eunit/include/eunit.hrl"). + +%% Solution +%% --------------------- +%% Streight forward +%% --------------------- + +fib(Max) -> + fib(1, 1, Max). + +fib(Fst, Snd, Max) -> + fib(Fst, Snd, Max, 0). + +fib(_Fst, Snd, Max, Acc) when Snd > Max -> + Acc; +fib(Fst, Snd, Max, Acc) when Snd rem 2 =:= 0 -> + fib(Snd, Fst+Snd, Max, Acc+Snd); +fib(Fst, Snd, Max, Acc) -> + fib(Snd, Fst+Snd, Max, Acc). + +fib_test() -> + ?assertEqual(4613732, fib(4000000)). + +%% Solution +%% --------------------- +%% Found on Euler forum +%% --------------------- + +fse(Max) -> fse({1, 1}, Max, 0). + +fse({P1, P2}, Max, T) when (P1 + P2) < Max -> + fse({P1 + 2 * P2, 2 * P1 + 3 * P2}, Max, T + P1 + P2); +fse({P1, P2}, Max, T) when (P1 + P2) >= Max -> T. + +fse_test() -> + ?assertEqual(4613732, fse(4000000)). + +%% Solution +%% --------------------- +%% 2 8 34 144... +%% E(n) = 4*E(n-1) + E(n-2) +%% --------------------- + +f(M) -> f(2, 8, M, 10). + +f(A, B, Max, R) when A + 4*B > Max -> R; +f(A, B, Max, R) -> f(B, A + 4*B, Max, R + A + 4*B). + +f_test() -> + ?assertEqual(4613732, f(4000000)).
 @@ -0,0 +1,47 @@ +%% Problem +%% --------------------- +%% The prime factors of 13195 are 5, 7, 13 and 29. +%% What is the largest prime factor of the number 600851475143? +%% --------------------- + +-module(p003). +-include_lib("eunit/include/eunit.hrl"). + +%% Solution +%% --------------------- +%% Inspired by: +%% http://thetaoishere.blogspot.com/2008/05/largest-prime-factor-of-number.html +%% --------------------- + +lpf(1) -> 1; +lpf(2) -> 2; +lpf(N) when N rem 2 == 0 -> lpf(erlang:max(2, N div 2)); +lpf(N) -> lpf(3, trunc(math:sqrt(N)), N). + +lpf(I, Sn, N) when I > Sn -> N; +lpf(I, _S, N) when N rem I == 0 -> erlang:max(I, lpf(N div I)); +lpf(I, Sn, N) -> lpf(I + 2, Sn, N). + + +%% Tests + +lpf_1_test() -> + ?assertEqual(1, lpf(1)). + +lpf_2_test() -> + ?assertEqual(2, lpf(2)). + +lpf_3_test() -> + ?assertEqual(3, lpf(3)). + +lpf_16_test() -> + ?assertEqual(2, lpf(16)). + +lpf_20_test() -> + ?assertEqual(5, lpf(20)). + +lpf_17_test() -> + ?assertEqual(17, lpf(17)). + +problem_test() -> + ?assertEqual(6857, lpf(600851475143)).
 @@ -0,0 +1,37 @@ +%% Problem +%% --------------------- +%% 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. +%% --------------------- + +-module(p004). +-include_lib("eunit/include/eunit.hrl"). + +%% Solution +%% --------------------- +%% Brute force +%% --------------------- + +find_largest_palindrome() -> + lists:max(palindromes(lists:seq(100, 999))). + +palindromes(Factors) -> + [M * N || M <- Factors, N <- Factors, is_palindrome(M * N)]. + +is_palindrome(N) -> + Nl = integer_to_list(N), + Nl =:= lists:reverse(Nl). + + +%% Tests + +is_palindrome_true_test() -> + ?assertEqual(true, is_palindrome(9009)). + +is_palindrome_false_test() -> + ?assertEqual(false, is_palindrome(9001)). + +find_test() -> + ?assertEqual(906609, find_largest_palindrome()).
 @@ -0,0 +1,59 @@ +%% Problem +%% --------------------- +%% 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 +%% without any remainder. +%% +%% What is the smallest number that is evenly divisible by all of the numbers from 1 to 20? +%% --------------------- + +-module(p005). +-include_lib("eunit/include/eunit.hrl"). + +%% Solution +%% --------------------- +%% Inspired by: +%% http://basildoncoder.com/blog/2008/06/10/project-euler-problem-5/ +%% --------------------- + +find(Max) -> lists:foldl(fun lcm/2, 1, lists:seq(1, Max)). + +lcm(A, B) -> (A * B) div gcd(A, B). + +gcd(A, B) when A < B -> gcd(B, A); +gcd(A, 0) -> A; +gcd(A, B) -> gcd(B, A rem B). + + +%% Tests + +gcd_test() -> + ?assertEqual(6, gcd(84, 18)). + +lcm_test() -> + ?assertEqual(12, lcm(4, 6)). + +find_10_test() -> + ?assertEqual(2520, find(10)). + +find_20_test() -> + ?assertEqual(232792560, find(20)). + +%% Solution from bitRAKE +%% --------------------- +%% This does not require programming at all. Compute the prime factorization of each number from 1 +%% to 20, and multiply the greatest power of each prime together: +%% +%% 20 = 2^2 * 5 +%% 19 = 19 +%% 18 = 2 * 3^2 +%% 17 = 17 +%% 16 = 2^4 +%% 15 = 3 * 5 +%% 14 = 2 * 7 +%% 13 = 13 +%% 11 = 11 +%% +%% All others are included in the previous numbers. +%% +%% ANSWER: 2^4 * 3^2 * 5 * 7 * 11 * 13 * 17 * 19 = 232,792,560 +%% ---------------------
 @@ -0,0 +1,43 @@ +%% Problem +%% --------------------- +%% The sum of the squares of the first ten natural numbers is, +%% 1^2 + 2^2 + ... + 10^2 = 385 +%% The square of the sum of the first ten natural numbers is, +%% (1 + 2 + ... + 10)^2 = 55^2 = 3025 +%% Hence the difference between the sum of the squares of the +%% first ten natural numbers and the square of the sum is 3025 - 385 = 2640. +%% +%% Find the difference between the sum of the squares of the +%% first one hundred natural numbers and the square of the sum. +%% --------------------- + +-module(p006). +-include_lib("eunit/include/eunit.hrl"). + +%% Solution (long) +%% --------------------- + +diff(Max) -> 2 * lists:sum([M * N || M <- lists:seq(1, Max), N <- lists:seq(1, Max), M < N]). + +%% Solution (fast) +%% --------------------- + +diff2(N) -> N * (N + 1) * (3*N + 2) * (N - 1) div 12. + + +%% Tests + +diff_1_test() -> + ?assertEqual(0, diff(1)). + +diff_2_test() -> + ?assertEqual(4, diff(2)). + +diff_10_test() -> + ?assertEqual(2640, diff(10)). + +diff_100_test() -> + ?assertEqual(25164150, diff(100)). + +diff2_100_test() -> + ?assertEqual(25164150, diff2(100)).
 @@ -0,0 +1,41 @@ +%% Problem +%% --------------------- +%% By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, +%% we can see that the 6th prime is 13. +%% +%% What is the 10001st prime number? +%% --------------------- + +-module(p007). +-include_lib("eunit/include/eunit.hrl"). + +%% Solution +%% --------------------- +%% Inspired by: +%% http://basildoncoder.com/blog/2008/10/26/project-euler-problem-7/ +%% --------------------- + +find_prime(N) -> + lists:nth(N, sieve_with_atleast_n_primes(N)). + +sieve_with_atleast_n_primes(N) -> + mymath:primes_upto(upper_bound_estimate(N)). + +upper_bound_estimate(N) -> + trunc(N * math:log(N) + N * math:log(math:log(N))). + + +%% Tests + +find_prime_10_test() -> + ?assertEqual(29, find_prime(10)). + +upper_bound_estimate_test() -> + ?assertEqual(114319, upper_bound_estimate(10001)). + +find_prime_10001_test() -> + ?assertEqual(104743, find_prime(10001)). + + +%% See also: +%% http://primes.utm.edu/lists/small/