recursion - gitlab · recursion properties (informally) as observed from the pictures each instance...
TRANSCRIPT
Recursion
To understand recursion you must first understand recursion
or
The Droste effect
Advertisement for Droste cocoa, c. 1900
Koch Snowflake Fractal
The Koch snowflake can be constructed by starting with an equilateral triangle, then recursively altering each line segment as follows:
1. divide the line segment into three segments of equal length.
2. draw an equilateral triangle that has the middle segment from step 1 as its base and points outward.
3. remove the line segment that is the base of the triangle from step 2.
Menger Sponge
Romanesco broccoli
Recursion properties (informally)as observed from the picturesEach instance size• may be the same • may change
Termination• the chain of instances of the problem may go forever (unbounded recursion)• the chain of instances of the problem may terminate
What are (often) the desirable properties from a programming point of view?
Unbounded (mutual) recursion ...
https://www.youtube.com/watch?v=N0HoqjxfvJ4
... kills
Fundamental rules for creating good recursive functions
• There must be a base case (or cases)• Each recursive call must lead towards a base case!
Base case – defining a value for which the function is evaluated without recursivelly calling itself
• We can always take an unbounded recursion with a starting point and transform it into a bounded recursion where the starting point is the base case.
!
• Recursive programs are often more succint and easier to understand• Some problems are more easily solved by recursion• Recursion is often used as a method of traversing (or navigating)
over complex data structures. Linked lists, binary trees, ...• Program verification is easier (induction)
• because it is recursion !
Why recursion is important?
Definitions of “Ancestors of x”
Non-recursive:
parents of x, parents of parents of x, parents of parents of parents of x,...
Recursive:
parents of x, ancestors of parents of x.
https://everything2.com/index.pl?node_id=477013
FactorialA factorial of a non-negative integer n, denoted by n!, is the product of all positive integers less than or equal to n.
0! = 1 (by convention)1! = 12! = 2 * 1 3! = 3 * 2 * 14! = 4 * 3 * 2 * 1 5! = 5 * 4 * 3 * 2 * 1 6! = 6 * 5 * 4 * 3 * 2 * 1 ...
2! = 2 * 1!3! = 3 * 2!4! = 4 * 3! 5! = 5 * 4!6! = 6 * 5!...
n! = n * (n-1)!
4! is 4 * 3!now you need to solve the subproblem of computing 3!, which is 3 * 2!
now you need to solve 2!, which is 2 * 1!now 1!, which is 1 * 0!
0! is equal to 1 by convention (the base case!)now you can compute 1! = 1 * 0! which is 1 * 1 = 1
now you can compute 2! = 2 * 1! which is 2 * 1 = 2now you can compute 3! = 3 * 2! which is 3 * 2 = 6
now you can compute 4! = 4 * 3! which is 4 * 6 = 24
Task: compute 4!
!
Basic idea behind good recursive algorithms
To solve a problem, solve a smaller instance of the same problem, and then use the solution to that smaller instance to solve the original problem.
!
fac :: Integer -> Integerfac n
| n == 0 = 1| n > 0 = n * fac (n-1)| otherwise = error "Negative argument"
Factorial
fac 4→ 4 * fac 3→ 4 * (3 * fac 2) → 4 * (3 * (2 * fac 1))→ 4 * (3 * (2 * (1 * fac 0)))→ 4 * (3 * (2 * (1 * 1)))→ 4 * (3 * (2 * 1))→ 4 * (3 * 2)→ 4 * 6→ 24
fac :: Integer -> Integerfac n
| n == 0 = 1| n > 0 = n * fac (n-1) | otherwise = error ”Negative argument"
Function evaluation on input value 4
Sum of Factorials
sumFacs n = fac 0 + fac 1 + … + fac (n-1) + fac n
sumFacs :: Integer -> IntegersumFacs n | n == 0 = 1 | n > 0 = sumFacs (n - 1) + fac n | otherwise = error "The argument should be non-negative."
Yth Power of x
power :: Integer -> Integer -> Floatpower x y | y == 0 = 1 | y > 0 = fromIntegral x * power x ( y - 1 ) | otherwise = 1 / power x ( abs y )
Mutual Recursion
isEven :: Integer -> BoolisEven n
| n == 0 = True | otherwise = isOdd (n - 1)
isOdd :: Integer -> BoolsOdd n | n == 0 = False | otherwise = isEven (n - 1)
Drawing Hands
M.C. Esher1948