Recursion COM1022 Functional Programming Techniques Professor Steve Schneider University of Surrey Autumn 2009 Week 10 Professor Steve Schneider Recursion Autumn 2009 Week 10 1 / 35
This session After this session, you should understand the principle of recursion be able to use recursion over integers to solve simple problems Reference Thompson, Chapter 4 [based on slides by Dr Hans Georg Schaathun] Professor Steve Schneider Recursion Autumn 2009 Week 10 2 / 35
Modular programming Outline Modular programming 1 Primitive recursion 2 General forms of recursion 3 Iteration 4 Error handling 5 Conclusion 6 Professor Steve Schneider Recursion Autumn 2009 Week 10 3 / 35
Modular programming Software development The key to problem solving Split the task into smaller and manageable problems Software development is the same Each subproblem gives a function Many subproblems apply to different tasks Write the functions such that they can be reused Professor Steve Schneider Recursion Autumn 2009 Week 10 4 / 35
Modular programming Planning the development If I had all the functions in the world, which would I use? This question points to subproblems 1 Then move to the key functions – one at a time 2 Apply the same question to them 3 This idea apply in a myriad of ways Todays main topic is a special case known as recursion Professor Steve Schneider Recursion Autumn 2009 Week 10 5 / 35
Primitive recursion Outline Modular programming 1 Primitive recursion 2 General forms of recursion 3 Iteration 4 Error handling 5 Conclusion 6 Professor Steve Schneider Recursion Autumn 2009 Week 10 6 / 35
Primitive recursion A recursive definition A recursive function is defined in terms of itself. Factorial: n ! = 1 · 2 · 3 · . . . · n Recursive definition: 0 ! = 1 (1) n ! = n · ( n − 1 )! for n > 0 (2) A recursive function is defined in terms of itself. Why is this not a circular definition? Professor Steve Schneider Recursion Autumn 2009 Week 10 7 / 35
Primitive recursion The basic components The recursive case ( n ! = ( n − 1 )! · n ) large cases (for n ) are reduced to a smaller case ( n − 1) The base case (0 ! = 1) some small case must be solved explicitely Without the base case, recursion would never end n , n − 1 , n − 2 , . . . , 1 , 0 , − 1 , . . . , −∞ Without the recursive case, everything would be explicit one line for every n (0 , 1 , 2 , . . . , ∞ ) Professor Steve Schneider Recursion Autumn 2009 Week 10 8 / 35
Primitive recursion Recursion in Haskell Haskell supports recursive definitions. Two different styles: Pattern matching: factorial :: Int -> Int factorial 0 = 1 factorial n = n * factorial (n-1) or by cases: factorial :: Int -> Int factorial n | n == 0 = 1 | otherwise = n * factorial (n-1) Professor Steve Schneider Recursion Autumn 2009 Week 10 9 / 35
Primitive recursion For example factorial 4 = 4 · ( factorial 3 ) = 4 · 3 · ( factorial 2 ) = 4 · 3 · 2 · ( factorial 1 ) = 4 · 3 · 2 · 1 · ( factorial 0 ) = 4 · 3 · 2 · 1 · 1 = 24 Professor Steve Schneider Recursion Autumn 2009 Week 10 10 / 35
Primitive recursion Why recursion? Fundamental principle in mathematics and in computer programming Used in all programming paradigms you will see it in Java Recursion tends to make it simple to prove correctness 1 define and understand algorithms 2 It often makes computationally efficient algorithms Professor Steve Schneider Recursion Autumn 2009 Week 10 11 / 35
Primitive recursion Primitive recursion What if we knew the value of f ( n − 1 ) . How would we define f ( n ) ? f 0 = ... 1 2 f n = ... f (n-1) ... The recursive case depends on f (n-1) expressions independent of f Professor Steve Schneider Recursion Autumn 2009 Week 10 12 / 35
Primitive recursion Integer square root The integer square root of a number n is the greatest integer whose square is less than or equal to n . Examples intsqrt 15 = 3 intsqrt 16 = 4 Exercise : Define intsqrt using primitive recursion. handset question intsqrt 0 = ??? intsqrt n = ...(intsqrt (n-1))... If you know intsqrt (n-1) then how can that help you work out intsqrt n ? Professor Steve Schneider Recursion Autumn 2009 Week 10 13 / 35
Primitive recursion Cuts and pieces Exercise : How many pieces can the 2-d plane be separated into with n lines? handset question pieces 0 = ??? pieces n = ??? If you know pieces (n-1) then how can that help you work out pieces n ? Professor Steve Schneider Recursion Autumn 2009 Week 10 14 / 35
Primitive recursion Summing a function Exercise : Given a function f :: Int -> Int , how do I calculate Σ n i = 1 f ( i ) ? handset question sigma f 0 = ??? sigma f n = ??? If you know sigma f (n-1) then how can that help you work out sigma f n ? Observe that sigma is a higher-order function . This means that it can take another function f as an argument. Question : What is the type of sigma ? handset question Professor Steve Schneider Recursion Autumn 2009 Week 10 15 / 35
General forms of recursion Outline Modular programming 1 Primitive recursion 2 General forms of recursion 3 Iteration 4 Error handling 5 Conclusion 6 Professor Steve Schneider Recursion Autumn 2009 Week 10 16 / 35
General forms of recursion Many forms of recursion Sometimes the recursive case does not call n − 1 More generally: For which values of k would f ( k ) help us define f ( n ) ? Sometimes we need f ( n − 1 ) and f ( n − 2 ) Sometimes we can work with f ( n / 2 ) In general we look for f on some ‘smaller’ arguments Professor Steve Schneider Recursion Autumn 2009 Week 10 17 / 35
General forms of recursion Divisors How many times can a factor p divide into a number m ? For given p and m , want the largest n such that p n divides m . Examples powerdiv 2 8 = 3 powerdiv 3 8 = 0 powerdiv 3 18 = 2 powerdiv 3 1 = 0 powerdiv 2 1000 = 3 Define powerdiv p m in terms of powerdiv on ‘smaller’ arguments. What’s the base case? What’s the recursive case? [note that powerdiv p (m-1) does not help towards powerdiv p m ] Professor Steve Schneider Recursion Autumn 2009 Week 10 18 / 35
General forms of recursion Split-and-Conquer q n = q · q · . . . · q (3) How do you compute this efficiently? Primitive recursion can be used here: but n − 1 multiplications is quite expensive q 0 = 1 , (4) q 1 = q , (5) � ( q ⌊ n / 2 ⌋ ) 2 , if n is even q n = (6) ( q ⌊ n / 2 ⌋ ) 2 · q , if n is odd Professor Steve Schneider Recursion Autumn 2009 Week 10 19 / 35
General forms of recursion A Haskell example myExp q 0 = 1 myExp q 1 = q myExp q n | n ‘mod‘ 2 == 0 = h*h | n ‘mod‘ 2 == 1 = h*h*q where h = myExp q (n ‘div‘ 2) where allows you to define a variable for internal use in the definition Professor Steve Schneider Recursion Autumn 2009 Week 10 20 / 35
General forms of recursion Split-and-Conquer This is a split-and-conquer algorithm each recursive step halves the problem reaches base case in 2 log 2 n steps. 2 log 2 n << n − 1 (except for small n ) Professor Steve Schneider Recursion Autumn 2009 Week 10 21 / 35
General forms of recursion Fibonacci numbers Fibonacci sequence 1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , 55 , 89 , 144 , 233 , . . . Each number is the sum of the two preceeding numbers How do we write this in recursive form? For example fib 1 = 1 fib 2 = 1 fib n = fib (n-1) + fib (n-2) Each step requires two preceeding numbers Professor Steve Schneider Recursion Autumn 2009 Week 10 22 / 35
General forms of recursion Efficiency fib n = fib (n-1) + fib (n-2) fib (n-2) is calculated twice once for fib (n-1) and once for fib n fib (n-3) is calculated three times once for fib (n-2) and twice (!) for fib (n-1) The compiler/interpreter may or may not optimise i.e. remember and reuse previous calculation Professor Steve Schneider Recursion Autumn 2009 Week 10 23 / 35
Iteration Outline Modular programming 1 Primitive recursion 2 General forms of recursion 3 Iteration 4 Error handling 5 Conclusion 6 Professor Steve Schneider Recursion Autumn 2009 Week 10 24 / 35
Iteration Space considerations Recursion can be expensive in terms of space. Each recursive call must keep track of the context it was called in, until the final computation once the base case is reached. Recall: factorial 4 = 4 · ( factorial 3 ) = 4 · 3 · ( factorial 2 ) = 4 · 3 · 2 · ( factorial 1 ) = 4 · 3 · 2 · 1 · ( factorial 0 ) = 4 · 3 · 2 · 1 · 1 = 24 Professor Steve Schneider Recursion Autumn 2009 Week 10 25 / 35
Iteration Iteration If a recursive call has no surrounding context, then the space requirements will not grow. A recursive definition of this form is called an iterative definition. ??? But f n = f (n-1) is not much use ??? Generally more arguments are required: f m n = f (...m...n...) (n-1) Professor Steve Schneider Recursion Autumn 2009 Week 10 26 / 35
Iteration Factorial revisited partfact tot 0 = tot partfact tot n = partfact (tot * n) (n-1) factorial n = partfact 1 n factorial 4 = partfact 1 4 = partfact 4 3 = partfact 12 2 = partfact 24 1 = partfact 24 0 = 24 Professor Steve Schneider Recursion Autumn 2009 Week 10 27 / 35
Recommend
More recommend