Created
June 25, 2017 22:04
-
-
Save andreburgaud/48230f6298ba30f0179974c24c7b9784 to your computer and use it in GitHub Desktop.
FutureLearn - Functional Programming in Erlang 1.21 - Tail Recursion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(recursion). | |
-export([test/0,fib/1,loop/1,sum/1,max/1,perfect/1]). | |
% Typical loop in Erlang | |
loop(N) when N>0 -> | |
io:format("~p~n", [N]), | |
loop(N-1); | |
loop(_) -> % implies N = 0 | |
io:format("bye~n"). | |
% Sum of values F(0), F(1), ... F(N-1), F(N). | |
sum(N) -> | |
sum(N,0). | |
sum(N,A) when N>0 -> | |
sum(N-1, N+A); | |
sum(_,A) -> % N = 0 | |
A. | |
% Max value of F(0), F(1), ... F(N-1), F(N). | |
% Probably did not get a good sense of what was asked... | |
max(N) -> | |
max_loop(N,N). | |
max_loop(N,A) when N>0 -> | |
max_loop(N-1, max(N,A)); | |
max_loop(_,A) -> % N = 0 | |
A. | |
% Tail recursive Fibonacci with 2 accumulator (last 2 numbers). | |
% Starts with the first 2 fibonacci numbers than swap and add to get the | |
% two next ones | |
fib(N) -> | |
fib_loop(N, 0, 1). | |
fib_loop(0,A,_) -> | |
A; | |
fib_loop(N, A, B) when N>0 -> | |
fib_loop(N-1, B, A+B). | |
% Step by step fib(4): | |
% fib(4) = fib_loop(4,0,1) | |
% = fib_loop(3,1,1) | |
% = fib_loop(2,1,2) | |
% = fib_loop(1,2,3) | |
% = fib_loop(0,3,5) | |
% = 3 | |
% Perfect number | |
% A positive integer is perfect when it is the sum of its divisors, | |
% e.g. 6=1+2+3, 28=1+2+4+7+14. | |
perfect(0) -> | |
false; | |
perfect(N) -> | |
perfect(N,N-1,0). | |
perfect(N,0,A) -> | |
N == A; | |
perfect(N,D,A) when N rem D =:= 0 -> | |
perfect(N,D-1,A+D); | |
perfect(N,D,A) -> % D not a divisor | |
perfect(N,D-1,A). | |
% Test perfect number samples | |
test() -> | |
test_perfect() and test_non_perfect(). | |
% Perfect numbers | |
test_perfect() -> | |
lists:all(fun(X) -> X == true end, | |
[perfect(6),perfect(28),perfect(496),perfect(8128)]). | |
% Non perfect numbers | |
test_non_perfect() -> | |
lists:all(fun(X) -> X == false end, | |
[perfect(0),perfect(1),perfect(29),perfect(1000),perfect(5000)]). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment