# public ndpar /algorithms

### Subversion checkout URL

You can clone with HTTPS or Subversion.

Solved firest 10 problems

commit 6241c3ea6f60db044452e8e5ceabd3e236e904ba 0 parents
authored
52  mymath.erl
 ... ... @@ -0,0 +1,52 @@ 1 +-module(mymath). 2 +-export([primes_upto/1]). 3 +-include_lib("eunit/include/eunit.hrl"). 4 + 5 +%% Find all prime numbers upto specified value. 6 +%% 7 +primes_upto(N) -> eratosthenes(math:sqrt(N), lists:seq(2, N)). 8 + 9 + 10 +%% Functional implementation of Eratosthenes sieve algorithm 11 +%% http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes 12 +%% 13 +%% Very clean but very slow. Works relatively fast for N < 100,000 14 +%% 15 +eratosthenes_sieve([]) -> []; 16 +eratosthenes_sieve([P|Xs]) -> [P | eratosthenes_sieve([X || X <- Xs, X rem P > 0])]. 17 + 18 + 19 +%% Functional implementation of Euler sieve algorithm 20 +%% 21 +%% Very clean but very slow. Works relatively fast for N < 10,000 22 +%% 23 +euler_sieve([]) -> []; 24 +euler_sieve([P|Xs]) -> [P | euler_sieve(Xs -- lists:map(fun(X) -> X*P end, [P|Xs]))]. 25 + 26 + 27 +%% Recursion implementation of Eratosthenes sieve algorithm 28 +%% Author: Zac Brown 29 +%% 30 +%% Not so obvious but very efficient 31 +%% 32 +eratosthenes(Max, [H|T]) when H =< Max -> [H | eratosthenes(Max, sieve([H|T], H))]; 33 +eratosthenes(_Max, L) -> L. 34 + 35 +sieve([H|T], N) when H rem N =/= 0 -> [H | sieve(T, N)]; 36 +sieve([_H|T], N) -> sieve(T, N); 37 +sieve([], _N) -> []. 38 + 39 +%% Tests 40 + 41 +primes_upto_30_test() -> 42 + ?assertEqual([2, 3, 5, 7, 11, 13, 17, 19, 23, 29], primes_upto(30)). 43 + 44 +primes_upto_2m_test() -> 45 + ?assertEqual(1999993, lists:last(primes_upto(2000000))). 46 + 47 + 48 +euler_sieve_test() -> 49 + ?assertEqual([2, 3, 5, 7, 11, 13, 17, 19, 23, 29], euler_sieve(lists:seq(2, 30))). 50 + 51 +eratosthenes_sieve_test() -> 52 + ?assertEqual([2, 3, 5, 7, 11, 13, 17, 19, 23, 29], eratosthenes_sieve(lists:seq(2, 30))).
22  p001.erl
 ... ... @@ -0,0 +1,22 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% If we list all the natural numbers below 10 that are multiples of 3 or 5, 4 +%% we get 3, 5, 6 and 9. The sum of these multiples is 23. 5 +%% 6 +%% Find the sum of all the multiples of 3 or 5 below 1000. 7 +%% --------------------- 8 + 9 +-module(p001). 10 +-include_lib("eunit/include/eunit.hrl"). 11 + 12 +multiples35(N) -> 13 + [X || X <- lists:seq(1, N), (X rem 3 =:= 0) or (X rem 5 =:= 0)]. 14 + 15 +multiples35_test() -> 16 + ?assertEqual(466, length(multiples35(999))). 17 + 18 +result() -> 19 + lists:sum(multiples35(999)). 20 + 21 +result_test() -> 22 + ?assertEqual(233168, result()).
60  p002.erl
 ... ... @@ -0,0 +1,60 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% Each new term in the Fibonacci sequence is generated by adding the previous two terms. 4 +%% By starting with 1 and 2, the first 10 terms will be: 5 +%% 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 6 +%% 7 +%% Find the sum of all the even-valued terms in the sequence which do not exceed four million. 8 +%% --------------------- 9 + 10 +-module(p002). 11 +-include_lib("eunit/include/eunit.hrl"). 12 + 13 +%% Solution 14 +%% --------------------- 15 +%% Streight forward 16 +%% --------------------- 17 + 18 +fib(Max) -> 19 + fib(1, 1, Max). 20 + 21 +fib(Fst, Snd, Max) -> 22 + fib(Fst, Snd, Max, 0). 23 + 24 +fib(_Fst, Snd, Max, Acc) when Snd > Max -> 25 + Acc; 26 +fib(Fst, Snd, Max, Acc) when Snd rem 2 =:= 0 -> 27 + fib(Snd, Fst+Snd, Max, Acc+Snd); 28 +fib(Fst, Snd, Max, Acc) -> 29 + fib(Snd, Fst+Snd, Max, Acc). 30 + 31 +fib_test() -> 32 + ?assertEqual(4613732, fib(4000000)). 33 + 34 +%% Solution 35 +%% --------------------- 36 +%% Found on Euler forum 37 +%% --------------------- 38 + 39 +fse(Max) -> fse({1, 1}, Max, 0). 40 + 41 +fse({P1, P2}, Max, T) when (P1 + P2) < Max -> 42 + fse({P1 + 2 * P2, 2 * P1 + 3 * P2}, Max, T + P1 + P2); 43 +fse({P1, P2}, Max, T) when (P1 + P2) >= Max -> T. 44 + 45 +fse_test() -> 46 + ?assertEqual(4613732, fse(4000000)). 47 + 48 +%% Solution 49 +%% --------------------- 50 +%% 2 8 34 144... 51 +%% E(n) = 4*E(n-1) + E(n-2) 52 +%% --------------------- 53 + 54 +f(M) -> f(2, 8, M, 10). 55 + 56 +f(A, B, Max, R) when A + 4*B > Max -> R; 57 +f(A, B, Max, R) -> f(B, A + 4*B, Max, R + A + 4*B). 58 + 59 +f_test() -> 60 + ?assertEqual(4613732, f(4000000)).
47  p003.erl
 ... ... @@ -0,0 +1,47 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% The prime factors of 13195 are 5, 7, 13 and 29. 4 +%% What is the largest prime factor of the number 600851475143? 5 +%% --------------------- 6 + 7 +-module(p003). 8 +-include_lib("eunit/include/eunit.hrl"). 9 + 10 +%% Solution 11 +%% --------------------- 12 +%% Inspired by: 13 +%% http://thetaoishere.blogspot.com/2008/05/largest-prime-factor-of-number.html 14 +%% --------------------- 15 + 16 +lpf(1) -> 1; 17 +lpf(2) -> 2; 18 +lpf(N) when N rem 2 == 0 -> lpf(erlang:max(2, N div 2)); 19 +lpf(N) -> lpf(3, trunc(math:sqrt(N)), N). 20 + 21 +lpf(I, Sn, N) when I > Sn -> N; 22 +lpf(I, _S, N) when N rem I == 0 -> erlang:max(I, lpf(N div I)); 23 +lpf(I, Sn, N) -> lpf(I + 2, Sn, N). 24 + 25 + 26 +%% Tests 27 + 28 +lpf_1_test() -> 29 + ?assertEqual(1, lpf(1)). 30 + 31 +lpf_2_test() -> 32 + ?assertEqual(2, lpf(2)). 33 + 34 +lpf_3_test() -> 35 + ?assertEqual(3, lpf(3)). 36 + 37 +lpf_16_test() -> 38 + ?assertEqual(2, lpf(16)). 39 + 40 +lpf_20_test() -> 41 + ?assertEqual(5, lpf(20)). 42 + 43 +lpf_17_test() -> 44 + ?assertEqual(17, lpf(17)). 45 + 46 +problem_test() -> 47 + ?assertEqual(6857, lpf(600851475143)).
37  p004.erl
 ... ... @@ -0,0 +1,37 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% A palindromic number reads the same both ways. The largest palindrome made from the 4 +%% product of two 2-digit numbers is 9009 = 91 * 99. 5 +%% 6 +%% Find the largest palindrome made from the product of two 3-digit numbers. 7 +%% --------------------- 8 + 9 +-module(p004). 10 +-include_lib("eunit/include/eunit.hrl"). 11 + 12 +%% Solution 13 +%% --------------------- 14 +%% Brute force 15 +%% --------------------- 16 + 17 +find_largest_palindrome() -> 18 + lists:max(palindromes(lists:seq(100, 999))). 19 + 20 +palindromes(Factors) -> 21 + [M * N || M <- Factors, N <- Factors, is_palindrome(M * N)]. 22 + 23 +is_palindrome(N) -> 24 + Nl = integer_to_list(N), 25 + Nl =:= lists:reverse(Nl). 26 + 27 + 28 +%% Tests 29 + 30 +is_palindrome_true_test() -> 31 + ?assertEqual(true, is_palindrome(9009)). 32 + 33 +is_palindrome_false_test() -> 34 + ?assertEqual(false, is_palindrome(9001)). 35 + 36 +find_test() -> 37 + ?assertEqual(906609, find_largest_palindrome()).
59  p005.erl
 ... ... @@ -0,0 +1,59 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 4 +%% without any remainder. 5 +%% 6 +%% What is the smallest number that is evenly divisible by all of the numbers from 1 to 20? 7 +%% --------------------- 8 + 9 +-module(p005). 10 +-include_lib("eunit/include/eunit.hrl"). 11 + 12 +%% Solution 13 +%% --------------------- 14 +%% Inspired by: 15 +%% http://basildoncoder.com/blog/2008/06/10/project-euler-problem-5/ 16 +%% --------------------- 17 + 18 +find(Max) -> lists:foldl(fun lcm/2, 1, lists:seq(1, Max)). 19 + 20 +lcm(A, B) -> (A * B) div gcd(A, B). 21 + 22 +gcd(A, B) when A < B -> gcd(B, A); 23 +gcd(A, 0) -> A; 24 +gcd(A, B) -> gcd(B, A rem B). 25 + 26 + 27 +%% Tests 28 + 29 +gcd_test() -> 30 + ?assertEqual(6, gcd(84, 18)). 31 + 32 +lcm_test() -> 33 + ?assertEqual(12, lcm(4, 6)). 34 + 35 +find_10_test() -> 36 + ?assertEqual(2520, find(10)). 37 + 38 +find_20_test() -> 39 + ?assertEqual(232792560, find(20)). 40 + 41 +%% Solution from bitRAKE 42 +%% --------------------- 43 +%% This does not require programming at all. Compute the prime factorization of each number from 1 44 +%% to 20, and multiply the greatest power of each prime together: 45 +%% 46 +%% 20 = 2^2 * 5 47 +%% 19 = 19 48 +%% 18 = 2 * 3^2 49 +%% 17 = 17 50 +%% 16 = 2^4 51 +%% 15 = 3 * 5 52 +%% 14 = 2 * 7 53 +%% 13 = 13 54 +%% 11 = 11 55 +%% 56 +%% All others are included in the previous numbers. 57 +%% 58 +%% ANSWER: 2^4 * 3^2 * 5 * 7 * 11 * 13 * 17 * 19 = 232,792,560 59 +%% ---------------------
43  p006.erl
 ... ... @@ -0,0 +1,43 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% The sum of the squares of the first ten natural numbers is, 4 +%% 1^2 + 2^2 + ... + 10^2 = 385 5 +%% The square of the sum of the first ten natural numbers is, 6 +%% (1 + 2 + ... + 10)^2 = 55^2 = 3025 7 +%% Hence the difference between the sum of the squares of the 8 +%% first ten natural numbers and the square of the sum is 3025 - 385 = 2640. 9 +%% 10 +%% Find the difference between the sum of the squares of the 11 +%% first one hundred natural numbers and the square of the sum. 12 +%% --------------------- 13 + 14 +-module(p006). 15 +-include_lib("eunit/include/eunit.hrl"). 16 + 17 +%% Solution (long) 18 +%% --------------------- 19 + 20 +diff(Max) -> 2 * lists:sum([M * N || M <- lists:seq(1, Max), N <- lists:seq(1, Max), M < N]). 21 + 22 +%% Solution (fast) 23 +%% --------------------- 24 + 25 +diff2(N) -> N * (N + 1) * (3*N + 2) * (N - 1) div 12. 26 + 27 + 28 +%% Tests 29 + 30 +diff_1_test() -> 31 + ?assertEqual(0, diff(1)). 32 + 33 +diff_2_test() -> 34 + ?assertEqual(4, diff(2)). 35 + 36 +diff_10_test() -> 37 + ?assertEqual(2640, diff(10)). 38 + 39 +diff_100_test() -> 40 + ?assertEqual(25164150, diff(100)). 41 + 42 +diff2_100_test() -> 43 + ?assertEqual(25164150, diff2(100)).
41  p007.erl
 ... ... @@ -0,0 +1,41 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, 4 +%% we can see that the 6th prime is 13. 5 +%% 6 +%% What is the 10001st prime number? 7 +%% --------------------- 8 + 9 +-module(p007). 10 +-include_lib("eunit/include/eunit.hrl"). 11 + 12 +%% Solution 13 +%% --------------------- 14 +%% Inspired by: 15 +%% http://basildoncoder.com/blog/2008/10/26/project-euler-problem-7/ 16 +%% --------------------- 17 + 18 +find_prime(N) -> 19 + lists:nth(N, sieve_with_atleast_n_primes(N)). 20 + 21 +sieve_with_atleast_n_primes(N) -> 22 + mymath:primes_upto(upper_bound_estimate(N)). 23 + 24 +upper_bound_estimate(N) -> 25 + trunc(N * math:log(N) + N * math:log(math:log(N))). 26 + 27 + 28 +%% Tests 29 + 30 +find_prime_10_test() -> 31 + ?assertEqual(29, find_prime(10)). 32 + 33 +upper_bound_estimate_test() -> 34 + ?assertEqual(114319, upper_bound_estimate(10001)). 35 + 36 +find_prime_10001_test() -> 37 + ?assertEqual(104743, find_prime(10001)). 38 + 39 + 40 +%% See also: 41 +%% http://primes.utm.edu/lists/small/
51  p008.erl
 ... ... @@ -0,0 +1,51 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% Find the greatest product of five consecutive digits in the 1000-digit number. 4 +%% --------------------- 5 + 6 +-module(p008). 7 +-include_lib("eunit/include/eunit.hrl"). 8 + 9 +%% Solution 10 +%% --------------------- 11 + 12 +number() -> 13 + "73167176531330624919225119674426574742355349194934" ++ 14 + "96983520312774506326239578318016984801869478851843" ++ 15 + "85861560789112949495459501737958331952853208805511" ++ 16 + "12540698747158523863050715693290963295227443043557" ++ 17 + "66896648950445244523161731856403098711121722383113" ++ 18 + "62229893423380308135336276614282806444486645238749" ++ 19 + "30358907296290491560440772390713810515859307960866" ++ 20 + "70172427121883998797908792274921901699720888093776" ++ 21 + "65727333001053367881220235421809751254540594752243" ++ 22 + "52584907711670556013604839586446706324415722155397" ++ 23 + "53697817977846174064955149290862569321978468622482" ++ 24 + "83972241375657056057490261407972968652414535100474" ++ 25 + "82166370484403199890008895243450658541227588666881" ++ 26 + "16427171479924442928230863465674813919123162824586" ++ 27 + "17866458359124566529476545682848912883142607690042" ++ 28 + "24219022671055626321111109370544217506941658960408" ++ 29 + "07198403850962455444362981230987879927244284909188" ++ 30 + "84580156166097919133875499200524063689912560717606" ++ 31 + "05886116467109405077541002256983155200055935729725" ++ 32 + "71636269561882670428252483600823257530420752963450". 33 + 34 +fivelets([A,B,C,D,E]) -> [[A,B,C,D,E]]; 35 +fivelets([A,B,C,D,E|Xs]) -> [[A,B,C,D,E]|fivelets([B,C,D,E|Xs])]. 36 + 37 +prod(List) -> lists:foldl(fun(X, Prod) -> (X-\$0) * Prod end, 1, List). 38 + 39 +find() -> lists:max(lists:map(fun prod/1, fivelets(number()))). 40 + 41 + 42 +%% Tests 43 + 44 +fivelets_test() -> 45 + ?assertEqual(["12345", "23456"], fivelets("123456")). 46 + 47 +prod_test() -> 48 + ?assertEqual(120, prod("12345")). 49 + 50 +find_test() -> 51 + ?assertEqual(40824, find()).
31  p009.erl
 ... ... @@ -0,0 +1,31 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% A Pythagorean triplet is a set of three natural numbers, a < b < c, for which, a^2 + b^2 = c^2 4 +%% For example, 3^2 + 4^2 = 9 + 16 = 25 = 5^2. 5 +%% 6 +%% There exists exactly one Pythagorean triplet for which a + b + c = 1000. 7 +%% Find the product abc. 8 +%% --------------------- 9 + 10 +-module(p009). 11 +-include_lib("eunit/include/eunit.hrl"). 12 + 13 +%% Solution 14 +%% --------------------- 15 +%% Does not work for big P, i.e. 1,000,000 16 +%% --------------------- 17 + 18 +triplets(P) -> 19 + [ {A,B,round(math:sqrt(A*A + B*B))} || 20 + A <- lists:seq(1, P-2), 21 + B <- lists:seq(A+1, P-1), 22 + P*P =:= 2*(A*P + B*P - A*B) 23 + ]. 24 + 25 +%% Tests 26 + 27 +triplets_12_test() -> 28 + ?assertEqual([{3,4,5}], triplets(12)). 29 + 30 +triplets_k_test() -> 31 + ?assertEqual([{200,375,425}], triplets(1000)).
16  p010.erl
 ... ... @@ -0,0 +1,16 @@ 1 +%% Problem 2 +%% --------------------- 3 +%% The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. 4 +%% 5 +%% Find the sum of all the primes below two million. 6 +%% --------------------- 7 + 8 +-module(p010). 9 +-include_lib("eunit/include/eunit.hrl"). 10 + 11 +sum_primes(N) -> lists:sum(mymath:primes_upto(N)). 12 + 13 +% Tests 14 + 15 +sum_primes_test() -> 16 + ?assertEqual(142913828922, sum_primes(2000000)).