241-303 Discrete Maths: Recursion/3 1
Discrete Maths
• Objective– to show the close connection between rec
ursive definitions, recursive functions, and recursive (inductive) proofs
241-303, Semester 1 2014-2015
3. Recursion
241-303 Discrete Maths: Recursion/3 2
Overview
1. Recursive Definitions2. Recursive Functions3. Lists Recursively4. Trees Recursively5. Hilbert Curves6. Proving Recursive Programs Work7. Further Information
241-303 Discrete Maths: Recursion/3 3
1. Recursive Definitions
• A recursive definition involves:– 1. One or more basis rules, in which simple thin
gs are defined, and
– 2. One or more recursive (inductive) rules, where larger things are defined in terms of ‘smaller’ versions of those things.
241-303 Discrete Maths: Recursion/3 4
Examples
23
57 19
5 4left
subtreeright
subtree
• A tree is made from left and right subtrees.
the leaves are the basis
241-303 Discrete Maths: Recursion/3 5
Sierpinski Gasket
• Start with a triangle and cut out the middle piece as shown. This results in three smaller triangles to which the process is continued.
Use recursion to createstrange shapes
241-303 Discrete Maths: Recursion/3 6
3D Sierpinski Gasket
241-303 Discrete Maths: Recursion/3 7
Menger Sponge
removecenter square
repeat for the 8small squares
241-303 Discrete Maths: Recursion/3 8
• For many problems, recursive definitions are the natural way of specifying the problems– e.g. search over trees/graphs, parsing,
• Recursive definitions are very close to inductive statements, and so are usually easier to prove than loop invariants.
Why Bother with Recursive Definitions?
241-303 Discrete Maths: Recursion/3 9
1.1. Factorial, Recursively
• Remember that n! is 1*2*3*...*n.
• A recursive definition of n!:– Basis. 1! = 1
– Induction. n! = n * (n-1)!
it's inductive because the meaning of n! is defined using the smaller (n-1)!
241-303 Discrete Maths: Recursion/3 10
Prove the Specification Correct
• Prove the inductive statement S(n): – the recursive definition of n!, as defined
on the last slide, equals 1*2*3*...*n
• Basis. S(1) is clearly true.
continued
Show recursive n! is the same as a series of multiplications.
241-303 Discrete Maths: Recursion/3 11
• Induction. Assume that S(n) is true, which means that n! = 1*2*3...*n
• The recursive definition states that:– (n+1)! = (n+1) * n!– so, (n+1)! = n! * (n+1)– substitute in n! value from S(n), so
(n+1)! = 1*2*3*...n*(n+1)• This is S(n+1), so S(n) --> S(n+1) is true.
continued
241-303 Discrete Maths: Recursion/3 12
• In summary:– we have shown S(1) to be true– we have shown S(n) --> S(n+1) to be true
• This means that S(n) is true for all n >= 1:– the recursive definition of n! equals 1*2*3*...*n
• Why is this useful?– the correct recursive definition can be easily converted into a
correct recursive function
241-303 Discrete Maths: Recursion/3 13
1.2. Recursive Definition of Expressions
• We will look at expressions involving binary operators (e.g. +, *, /)– e.g X*2, (Y/3)*(W+2), X
• The variables/numbers in an expressions are called operands.
• Basis. An operand on its own is an expression (e.g. X).
continued
241-303 Discrete Maths: Recursion/3 14
Inductive Rules
• 1. If E1 and E2 are expression, and @ is a binary operator (e.g., +, *), then E1@E2 is an expression.
• 2. If E is an expression, then (E) is an expression.
• Examples: 5, X, 2+s, (X*Y) - 1
241-303 Discrete Maths: Recursion/3 15
An Induction Proof Using Length
• S(n): A binary operator expression E of length n has one more operand than operators.
• For example: len operands ops– X 1 1 0– (2*y)+3 7 3 2
continued
241-303 Discrete Maths: Recursion/3 16
• Examples:– S(1) 1 y X a 2– S(3) 2+a X*Y 3-s (x)– S(5) (1+d) 5*6-2
• Note: the examples suggest that S(2), S(4), S(6), etc. may not exist.
the length of the expression
continued
241-303 Discrete Maths: Recursion/3 17
• The proof of S(n) is by complete induction on the length of the expression:– length is counted as the number of operators, oper
ands and parentheses
• Basis. n=1. E must be a single operand (e.g. X). Since there are no operators, the basis holds.– e.g. the first examples on the last slide
continued
241-303 Discrete Maths: Recursion/3 18
• Induction: Assume S(1), S(2),..., S(n), and show that:– (S(1) or S(2) or … or S(n)) --> S(n+1)– this is complete induction.
• Let the expression for S(n+1) be called E.
• How can E be constructed?– there are two cases, corresponding to the two inductive ru
les
continued
241-303 Discrete Maths: Recursion/3 19
• a) If by rule (2), E = (E1)• Assume true: no of operands no of ops|
E1 x+1 x
• Prove E E = (E1) x+1 x
• So S(n+1) holds when E has the form (E1)
continued
241-303 Discrete Maths: Recursion/3 20
• b) If by rule (1), then E = E1@E2
• Assume true: no of operands no of ops|E1 a+1 aE2 b+1 b
• Prove E E = E1@E2 a+b+2 a+b+1
• So S(n+1) holds when E has the form E1@E2
continued
241-303 Discrete Maths: Recursion/3 21
• S(n+1) is true for both forms of E– this was proved by assuming that smaller expre
ssions (E1, E2) were true
– any smaller expression can be used since we are using complete induction
continued
241-303 Discrete Maths: Recursion/3 22
• In summary:– shown S(1) to be true– shown (S(1) or S(2) .. or S(n)) --> S(n+1) true
• This means that S(n) is true for all n >= 1:– a binary operator expression E of length n has one more operand tha
n operators
• Why is this useful?– the correct recursive definition can be easily converted into a correct
recursive function, which can be used in compilers
complete induction
241-303 Discrete Maths: Recursion/3 23
Notes
• We used all of S(1), ...S(n) in the inductive step, since we considered the subexpressions that made up E.
• Using subexpressions was only possible because expression was defined recursively in terms of subexpressions.
241-303 Discrete Maths: Recursion/3 24
2. Recursive Functions
• A recursive function is one that is called from within its own body– direct call: a function F() has a call to F() within it
self– indirect call: a function F1() calls F2() which calls
F3(), ... and eventually F1() is called
• Recursive definitions map easily to recursive functions.
241-303 Discrete Maths: Recursion/3 25
2.1. Factorial Code• The recursive definition of n! was:
– Basis. 1! = 1– Induction. n! = n * (n-1)!
• As a function:int fact(int n){ if (n <= 1) return 1; /* basis */ else return n * fact(n-1); /*induction*/}
a simpletranslation
241-303 Discrete Maths: Recursion/3 26
Understanding Recursive Execution
• Draw function calls as boxes, each containing the variables (and values) in that function call.
• Example:void main(){ int res = fact(4); printf(“%d”, res);}
241-303 Discrete Maths: Recursion/3 27
Diagram
main
n
res=fact(4)
fact
4return...
nfact
3return...
nfact
2return...
nfact
1return...
• The trick is to remember that there are multiple calls to fact().
241-303 Discrete Maths: Recursion/3 28
2.2. Convert int to binary
• The simplest algorithm for converting an integer to binary is recursive.
• It will translate:610 to 1102
1310 to 11012
continued
241-303 Discrete Maths: Recursion/3 29
• For an integer i > 0, convert it to binary as:– last bit is i%2
• '%' gives the remainder, so 9%4 == 1– leading bits are obtained by converting i/2 u
ntil i == 0• '/' is integer division, so 9/2 == 4
241-303 Discrete Maths: Recursion/3 30
Typical Looping Solution
void main(){ int i;
scanf(“%d”, &i); while (i > 0) { putchar(‘0’ + i%2); i = i/2; } putchar(‘\n’);}
i at start i/2 i%2 6 3 0 3 1 1 1 0 1 0
Input: 6Output: 011
241-303 Discrete Maths: Recursion/3 31
• Major problem: the answer comes out backwards:
610 is converted to 0112
• Fixing the looping version is much harder than writing a recursive definition of the algorithm.
241-303 Discrete Maths: Recursion/3 32
Recurive Definition
• Convert i to binary.– Basis. If i == 0, do nothing
– Induction. If i > 0, thenconvert i/2 , thenprint the bit i%2
it's inductive because the convert definitionfor i is defined using convert of i/2
241-303 Discrete Maths: Recursion/3 33
Recursive Code
void convert(int i){ if (i > 0) { convert(i/2); putchar(‘0’ + i%2); }}
void main(){ int i; scanf(“%d”, &i); convert(i); putchar(‘\n’);}
241-303 Discrete Maths: Recursion/3 34
Diagram
main
i
convert(6)
convert
6
iconvert
3
iconvert
1
iconvert
0
i 6
do nothing;return
convert(i/2);putchar(i%2)
convert(i/2);putchar(i%2)
convert(i/2);putchar(i%2)Input: 6
Output: 110
241-303 Discrete Maths: Recursion/3 35
2.3. Walking Robot
• A robot can take steps of 1 meter or 2 meters.
• Develop an algorithm to calculate the number of ways the robot can walk n meters.
More complex versions of this problemoccur in real robot controllers.
241-303 Discrete Maths: Recursion/3 36
Examples
• Distance n Seq. of Steps No. of Ways
to walk n meters 1 1 1
2 1,1 or 2 2
3 1,1,1 or 1,2 or 2,1 3
4 1,1,1,1 or 1,1,2 or1,2,1 or 2,1,1 or 2,2 5
241-303 Discrete Maths: Recursion/3 37
Recursive Definition
• Basis. No. of ways to walk 1 meter = 1. No. of ways to walk 2 meters = 2.
• Induction. No. of ways to walk n meters (n > 2) is the sum of:– no. of ways to walk n-1 (after a 1-step), plus– no. of ways to walk n-2 (after a 2-step)
241-303 Discrete Maths: Recursion/3 38
Recursive Code
int numWays(int n){ if ((n == 1) || (n == 2)) return n; else return numWays(n-1) +
numWays(n-2));}
241-303 Discrete Maths: Recursion/3 39
Table of Results• Distance to Walk No. of Ways
1 12 23 34 55 86 13
• This sequence of number of ways is a Fibonacci sequence. It appears in many places in maths (and computing).
241-303 Discrete Maths: Recursion/3 40
3. Lists Recursively
• The list data structure has a natural recursive definition (and implementation).
• When a data structure is recursive, functions for manipulating it are naturally recursive as well.– e.g. length of a list– e.g. is an element in a list?
241-303 Discrete Maths: Recursion/3 41
3.1. Recursive Definition• A list can be:
– Basis. Empty– Induction. A non-empty list consists of one nod
e (the head), followed by a list (the tail).
• Example:
23 5 7 19 5 4
tailhead
241-303 Discrete Maths: Recursion/3 42
3.2. Recursive Implementation
• Unfortunately, recursive data structures in C have to be implemented with pointers. – this is not true in many other languages, such as
Java, Haskell, Prolog, etc.
• Also, empty pointer data structures are usually coded using NULL.
continued
241-303 Discrete Maths: Recursion/3 43
The LIST Type
• struct CELL { int element; struct CELL *next;}
typedef struct CELL *LIST;
• Note. LIST can only hold integer elements.
241-303 Discrete Maths: Recursion/3 44
Diagrams of C Lists
w19 5 4
NULL
NULL
wan empty list
a 3-element list
241-303 Discrete Maths: Recursion/3 45
Example
void main(){ LIST w = NULL; /* an empty list */
w = makeList(); /* build a list */ : if (w != NULL) printList(w);
: :
241-303 Discrete Maths: Recursion/3 46
3.3. The length of a list
• The recursive definition of length follows the recursive definition of the list d.s:– Basis. The length of an empty list is 0.
– Induction. The length of a non-empty list is 1 + the length of the list tail.
241-303 Discrete Maths: Recursion/3 47
length()
int length(LIST w){ if (w == NULL) /* is w empty? */ return 0; else return 1 + length(w->next); }
241-303 Discrete Maths: Recursion/3 48
3.4. Is element x in the list?
• A recusive definition:– Basis. If the list is empty, then x is not in the list. R
eturn False (0).
– Induction. If the list is non-empty then:• 1. If x is the same as the list head, return True (1).• 2. If x is not the same as the head, then return the result
of examining the list tail.
241-303 Discrete Maths: Recursion/3 49
hasElement()
int hasElement(LIST w, int x){ if (w == NULL) /* empty? */ return 0; /* false */ else if (x == w->element) return 1; /* true */ else return hasElement(w->next, x);}
241-303 Discrete Maths: Recursion/3 50
3.5. A General Recursive Format• Most list functions have the “shape”:
ResultType fun(LIST w, ...){ if (w == NULL) return somethingSimple; else {
use w->element; ... fun(w->next, ...);
return result; }
}
Learn (and understand) this.
241-303 Discrete Maths: Recursion/3 51
4. Trees Recursively• The tree data structure has a natural recursiv
e definition (and implementation).
• Tree functions are naturally recursive:– e.g. the number of elements in a tree– e.g. is an element in a tree?
• Using loops in tree functions usually means BIG CODING MISTAKES.
241-303 Discrete Maths: Recursion/3 52
4.1. Recursive Definition• A binary tree can be:
– Basis. Empty– Induction. A non-empty tree consists of a node, a
nd left and right sub-trees (which may be empty).
23
57 19
5 4left
subtree
rightsubtree
241-303 Discrete Maths: Recursion/3 53
4.2. The TREE Type
• struct CELL { int element; struct CELL *left; struct cell *right;}
typedef struct CELL *TREE;
• Note. TREE can only hold integer element.
241-303 Discrete Maths: Recursion/3 54
Diagrams of C Trees
p 2
1 4
5
N N
NNN
a 4-element tree(N means NULL)
NULL
pan empty tree
241-303 Discrete Maths: Recursion/3 55
Example
void main(){ TREE p = NULL; /* an empty tree */
p = makeTree(); /* build a tree */ : if (p != NULL) printTree(p);
: :
241-303 Discrete Maths: Recursion/3 56
4.3. The number of elements in a tree
• The recursive definition of numElem follows the recursive definition of the tree d.s:– Basis. The numElem of an empty tree is 0.
– Induction. The numElem of a non-empty tree is: 1 + numElem of left subtree + numElem of right subtree
241-303 Discrete Maths: Recursion/3 57
numElem()
int numElem(TREE w){ if (w == NULL) /* is w empty? */ return 0; else return 1 + numElem(w->left) +
numElem(w->right); }
241-303 Discrete Maths: Recursion/3 58
4.4. Is element x in the tree?
• A recusive definition:– Basis. If the tree is empty, then x is not in the tree. R
eturn False (0).
– Induction. If the tree is non-empty then:• 1. If x is the same as the element, return True (1), or• 2. If x is in the left subtree, return True (1), or• 3. If x is in the right subtree, return True (1), or• 4. Return False.
241-303 Discrete Maths: Recursion/3 59
hasElement()int hasElement(TREE w, int x){ if (w == NULL) /* empty? */ return 0; /* false */ else if (x == w->element) return 1; else if (hasElement(w->left, x)) return 1; /* true */ else return hasElement(w->right, x);}
• Note: the last else combines cases 3 and 4.
241-303 Discrete Maths: Recursion/3 60
4.5. A General Recursive Format
• Most tree functions will have the “shape”:ResultType fun(TREE w, ...){ if (w == NULL) return somethingSimple; else {
use w->element; ... fun(w->left, ...); ... fun(w->right, ...);
return result; }
}
Learn (and understand) this.
241-303 Discrete Maths: Recursion/3 61
5. Hilbert Curves• Hilbert Curves are one kind of curve based on fract
als.
• Fractals are complex-looking shapes that are constructed by combining smaller basic shapes– fractals appear in nature (e.g. mountain/river shapes), an
d in computer games!
• They are easy to program recursively.
241-303 Discrete Maths: Recursion/3 62
Hilbert Curves of order 1, 2, and 3
H1
H2
H3
drawing starts at the top right corner
241-303 Discrete Maths: Recursion/3 63
Hilbert Curve, order 6
• This shows why curves of this type are often called “space-filling”.
H6
drawingstarts here
241-303 Discrete Maths: Recursion/3 64
5.1. Recursively Defining Hi
• H1 is• Hi is obtained by the composition of four instanc
es of Hi-1 of half size and appropriate rotation, and by tieing together the four Hi-1’s by three connecting lines.
• Four possible rotations:– any of these can be used to build H2, H3, etc.
241-303 Discrete Maths: Recursion/3 65
Hilbert Curves Again
H1
H2
H3
• For each curve, drawing starts at top right hand corner.
X
Y
241-303 Discrete Maths: Recursion/3 66
From Specification to Code
• Instead of recursively defining Hi using Hi-1, we will use a different approach.
• Four recursive drawing functions will be defined: Ai, Bi, Ci, Di
• Hi will be drawn by calling Ai
241-303 Discrete Maths: Recursion/3 67
Drawing Function
• Ai, Bi, Ci, Di have recursive definitions using Ai-1, Bi-1, Ci-1, Di-1.
• There are also basis drawings A1, B1, C1, D1
241-303 Discrete Maths: Recursion/3 68
Basis Drawings
A1
the arrow is thedrawing direction
on the screen
B1
C1
D1
241-303 Discrete Maths: Recursion/3 69
Recursive Drawings
Ai:Ai-1 Di-1
Ai-1 Bi-1
Bi:Bi-1 Bi-1
Ci-1 Ai-1
Ci:Di-1 Ci-1
Bi-1 Ci-1
Di:Ci-1 Ai-1
Di-1 Di-1
these are the connecting lines between the drawing operations
241-303 Discrete Maths: Recursion/3 70
5.2. Hilbert Curve Drawing Pseudo-code
#define WIDTH 512
/* global variables */int incr, x, y;
void main(){ int level; x = WIDTH; y = WIDTH; scanf(“%d”, &level); incr = WIDTH/pow(2,level); setplot(x,y); /* top right of plotter */ a(level); /* start with A */}
:
Draw Hlevel
x
y
241-303 Discrete Maths: Recursion/3 71
void a(int i) { if (i > 0) { d(i-1); x -= incr; plot(x,y); a(i-1); y -= incr; plot(x,y); a(i-1); x += incr; plot(x,y); b(i-1); } }
Ai:Ai-1 Di-1
Ai-1 Bi-1
241-303 Discrete Maths: Recursion/3 72
void b(int i) { if (i > 0) { c(i-1); y += incr; plot(x,y); b(i-1); x += incr; plot(x,y); b(i-1); y -= incr; plot(x,y); a(i-1); } }
Bi:Bi-1 Bi-1
Ci-1 Ai-1
241-303 Discrete Maths: Recursion/3 73
void c(int i) { if (i > 0) { b(i-1); x += incr; plot(x,y); c(i-1); y += incr; plot(x,y); c(i-1); x -= incr; plot(x,y); d(i-1); } }
Ci:Di-1 Ci-1
Bi-1 Ci-1
241-303 Discrete Maths: Recursion/3 74
void d(int i) { if (i > 0) { a(i-1); y -= incr; plot(x,y); d(i-1); x -= incr; plot(x,y); d(i-1); y += incr; plot(x,y); c(i-1); } }
Di:Ci-1 Ai-1
Di-1 Di-1
241-303 Discrete Maths: Recursion/3 75
Notes• The basis drawings A1, B1, C1, D1 are coded by calling a
(1), b(1), c(1), d(1)– the calls a(0), b(0), c(0), d(0) do nothing
• setplot(x,y)– sets the plotter coordinates to (x,y)
• plot(x,y)– draws a line from the current plotter coordinates to (x,y), and
updates the plotter coordinates
241-303 Discrete Maths: Recursion/3 76
5.3. Hilbert Curve URLs
• Java applets for generating fractals http://www.iit.edu/~krawczyk/java.html
– the Hilbert curve applet has a nice GUI
• The Shodor Education Foundationhttp://www.shodor.org/interactivate/activities/
– lots of maths-related applets
continued
241-303 Discrete Maths: Recursion/3 77
• Includes a Java applet in Peano.javahttp://monet.mercersburg.edu/henle/Peano/Peano.html
• Some discussion, and a Hilbert screen saverhttp://www.dcs.napier.ac.uk/~andrew/hilbert.html
241-303 Discrete Maths: Recursion/3 78
5.4. Some Fun Stuff
• Look at other fractal-based curves– e.g. Sierpinski curves, Koch curves
snowflakes, Levy dragons
241-303 Discrete Maths: Recursion/3 79
6. Proving Recursive Programs Work
• Proofs involving (recursive) functions usually say how input arguments affect the return value– e.g fact(i) --> i!
• Induction proofs usually involve the “size” of the argument, and how it changes as the function is recursively called.
241-303 Discrete Maths: Recursion/3 80
Different Kinds of Size
• Argument “size” can be things like:– the argument value. e.g. i in fact(i)– the length of a list passed as an argument– the number of nodes in a tree argument– etc.
241-303 Discrete Maths: Recursion/3 81
6.1. Proving fact()• A reminder of the code:
int fact(int n){ if (n <= 1) return 1; else return n * fact(n-1);}
• Inductive statement S(i):– when fact() is called with the value i for the argument n, f
act() returns i! when i >= 1
continued
241-303 Discrete Maths: Recursion/3 82
• Basis. For i=1, the first if-test results in a return value 1, which is 1!
• Induction. – Assume S(i) : fact(i) == i!– s(i+1): fact(i+1)
• returns (i+1) * fact(i) , which is:• (i+1) * i! , which is• (i+1)! , so the inductive step is true
241-303 Discrete Maths: Recursion/3 83
6.2. Proving convert()• A reminder of the code:
void convert(int i){ if (i > 0) { convert(i/2); putchar(‘0’ + i%2); }}
• Inductive statement S(k):– convert(k) produces the binary representation of integer
k >= 1– e.g. convert(6) == binary of 6 == 1102
e.g. 610 --> 1102
1310 --> 11012
continued
241-303 Discrete Maths: Recursion/3 84
• Basis. k == 1. The program executes:convert(0); // does nothingputchar('0'+ 1); // prints '1'
– this is the correct output– S(1) is true
• Induction. Assume S(k/2) and prove S(k) for k >= 2, when k is even, and when k is odd– show S(k/2) --> S(k) is true
241-303 Discrete Maths: Recursion/3 85
Graphically
iconvert
iconvert
iconvert
kconvert(i/2);putchar(i%2)
convert(i/2);putchar(i%2)
convert(i/2);putchar(i%2)
. . . .
Assume correct
k/2
241-303 Discrete Maths: Recursion/3 86
Inductive Cases• If k is even (e.g. 30), then output is:
– convert(k/2) then putchar(k%2) which is– “binary of k/2” 0 which is– 2 * “binary of k/2” which is– “binary of k” which is true
• If k == 30 then the output is:– convert(15) putchar(0) which is– “binary of 15” 0 which is– 2 * “binary of 15” which is
2 * 11112 == 111102
continued
241-303 Discrete Maths: Recursion/3 87
• If k is odd (e.g. 31), then output is:– convert(k/2) then putchar(k%2) which is– “binary of (k-1)/2” 1 which is– 2 * “binary of (k-1)/2” + 1 which is– “binary of k”
• If k == 31 then the output is:– convert(15) putchar(1) which is– “binary of 15” 1 which is– 2 * “binary of 15” + 1 which is– ( 2 * 11112 ) + 1 == 111112
241-303 Discrete Maths: Recursion/3 88
7. Further Information
• DM: section 3.4
• Algorithms + Data Structures = ProgramsNiklaus WirthPrentice-Hall, 1976, Chapter 3
241-303 Discrete Maths: Recursion/3 89
“Drawing Hands” M.C. Escher, 1948