CS 101: “If” and Recursion
Abhiram Ranade
This week’ lab assignment: Write a program that takes as input
an integer n and a sequence of numbers w1,w2,...,wn which as shown in the figure
give the offsets of unit length blocks placed one on the other. After reading each wi
you should print (a) the x coordinates of the support for the first i blocks (in the picture
the dark line shows the support for the first 3 blocks – in this case you should print
w1+w2+w3 and w1+w2+1) and (b) the x coordinate of the joint center of mass of the
blocks. All coordinates are measured with respect to the left edge of the first block.
(The arrangement is stable only if the center of mass is inside the support). Draw the
arrangement using the turtle. Note that the xcoordinate of the joint center of mass of a
set of blocks is simply the mean of the xcoordinate of the centers. The key question
you need to answer is how to update the center of mass as you read more and more
blocks. State whether this arrangement is stable. This last part needs the use of the
“if” statement, this will be covered on Monday.
w1
w2w3
w4
Topics
“If” statement• Finding the absolute value of a number
– Using this in the sqrt procedure
• Determining whether a number is prime
Recursion: • What happens if a function calls itself.• Drawing Trees
Absolute value
Absolute value of x = x if x >= 0, -x if x < 0.
float myabs(float x){ // abs already in cmath
if (x >= 0) return x;
else return -x;
}
Procedure for sqrt
float sqrt(float k){
float xi=1;
while(xi*xi – k > 0.001 || k - xi*xi > 0.001){
xi = (xi + k/xi)/2 ;
}
return xi;
}
Procedure for sqrt
float sqrt(float k){
float xi=1;
while(myabs(xi*xi – k) > 0.001){
xi = (xi + k/xi)/2 ;
}
return xi;
}
If statement General Form
if (condition) {xxx} else {yyy}
• Condition is checked.
• If it is true, then xxx is executed.
• Otherwise yyy is executed.
• After xxx or yyy the statement following the if statement is executed.
If without else
if (condition) {xxx}• Condition is checked. • If it is true, then xxx is executed and after
this the statement following the if statement is executed.
• Otherwise xxx is ignored. After this the statement following the if statement is executed.
Conditions and bool data type
• Conditions: Relational expressions: x rel y• Bool data type stores condition values • true, false : reserved words (like int, float, for )
bool p, q, r, s, u, v; // take value true/false.p = x >= 0; //true if x (defined earlier) is >= 0.if (p) return x; else return -x; // acceptableq = x <= 9;u = true; v = false; r = p && q;
Primality testing
bool isPrime(int n){
bool answer=true; // default assumption
for (int i=2; i < n; i++){
if (n % i == 0) answer = false;
}
return answer;
}
Better Primality testing
bool isPrime(int n){
bool answer=true; // default assumption
for (int i=2; i < n && answer; i++){
if (n % i == 0) answer = false;
}
return answer;
} // much, much faster algorithms exist ...
Homework
• Write a program which takes as input integers n and y and prints the month and date for the nth day of year y. First write a function isLeap that returns true if and only if the given year is a leap year.
Example: for n=81, y = 2008 you should print “March 21”.
• Write a program which determines whether a number is perfect, i.e. is the sum of all its proper divisors.
Recursive Functions
• Can a function call itself?• What are the rules by which such functions
execute?
• A function may call itself, and the rule of execution is exactly same!
• Such functions are called recursive and are often useful.
Example
int funny(int x){
return x * funny(x-1);
}
void turtleMain(){
int z = funny(3); cout << z;
}
Execution
• Area present for turtleMain. call funny(3)• Area created for funny. Value of x = 3.
Call to funny(2).• Area created for funny. Value of x = 2.
Call to funny(1).• Area created for funny. Value of x = 1.
Call to funny(0).• .... call to funny(-1) ... funny(-2) ...
Subcontracting must be made to terminate eventually
int funny(int x){
if (x == 0) return 1;
else return x * funny(x-1);
}
void turtleMain(){
int z = funny(3); cout << z;}
void turtlemain(){int z = funny(3); cout << z;}
z :
void turtlemain(){int z = funny(3); cout << z;}
z :
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 3
void turtlemain(){int z = funny(3); cout << z;}
z :
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 3 x : 2
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
void turtlemain(){int z = funny(3); cout << z;}
z :
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 3 x : 2
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 1
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
void turtlemain(){int z = funny(3); cout << z;}
z :
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 3 x : 2
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 1
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
0
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 0
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 0
1
void turtlemain(){int z = funny(3); cout << z;}
z :
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 3 x : 2
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 1
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
1
void turtlemain(){int z = funny(3); cout << z;}
z :
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 3 x : 2
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
1
void turtlemain(){int z = funny(3); cout << z;}
z :
int funny(x){if (x==0) return 1;else return x * funny(x-1);}
x : 3
2
void turtlemain(){int z = funny(3); cout << z;}
z :
6
Remarks
• turtleMain then prints “6”.
• Can you guess what will be the result of a call to funny with argument n in general?
• Key ideas:– For some value a recursive function must return
directly, without calling itself. (Base case)– From any call, eventually the base case must be
reached.
Recursion in drawing
• Repetitive patterns in picture => repeat or for loops in programs
• What if parts of a picture are similar to the whole picture?
e.g. A tree = two small trees on top of a
two branches.
Use recursion while drawing.
A bush from the Savannah’s
A bush from the Savannah’s
Drawing trees will be fun, but..
• Trees arise in other applications
• Tree drawing ideas will actually be useful when we deal with these applications.
Management heirarchy of an organization
President
Vice President Vice President
Manager Manager ... ...
Animal Kingdom
Vertebrates Invertebrates
Warm blooded cold bloodedMammals
Designing a recursive program
• Identify what are the base cases.– Tree: branch height becomes too small. In this
case procedure must return directly.
• The general case:– draw left branch, draw small tree on top– come back to root– draw right branch, draw small tree on top– come back to root
Procedure tree(float size){
/* Draws tree from current position, growing in current direction in which turtle points. Parameter size says how long the branch will be.
If size < 0.1 nothing is drawn. Post condition: At the end the turtle is back
at the root, and pointing in the same direction as at the start. */
Post condition
• If more drawing is to happen after any call to tree, then programmer needs to know where the turtle is pointing. Hence drawing program must bring back the turtle to the starting position and starting orientation.
• Post conditions are useful in numerical computing as well. Will see later.
void tree(float size){ if (size < 0.1) return; // without drawing left(45); forward(size); right(45); // otherwise tree will not grow vertically tree(size/2.0);// turtle points “north” due to post condition. left(45);back(size); // move back on left branch right(90);forward(size);left(45); tree(size/2.0); // drawing is done, but turtle is not back right(45);back(size);left(45); // ensures post condition}
Homework
• Branches should become more vertical further from the root. Implement this. Hint: add an extra parameter to tree.
• rand(): returns a random number in the range 0..1. Use this to make the lengths a bit random.
• Overall idea: your tree should look more realistic. • Draw a nice forest on the screen.
Recursion in Numerical Computing
• Euclid’s algorith for greatest common divisor.
• “First algorithm ever invented”?
• Key idea:
Theorem: GCD of m,n is n if n divides m,
else it is the same as the GCD of n and
m mod n.
GCD Program
int gcd(int m, int n){
if (m % n == 0) then return n;
else return gcd(n,m%n);
}
gcd(72,120) -- gcd(120,72) -- gcd(72,48) --
gcd(48,24) -- 24.
Key questions in programming
• Will the program always halt?– Will the condition in for loops eventually
become false?– Will the base case be ever reached in recursion?
• GCD: Second argument n, always reduces. But n is always positive, and can only reduce to 1. When n=1, then m%n=0 and hence base case true.
How many iterations are needed?
Let p,q be the values of variables m,n. Let m>n, and suppose there was a recursive call. Then the values r,s to the recursive call are q, p%q and further:
r+s < (2/3) (p+q)
Thus at most log 3/2 (p+q) calls will be made.
Proof
r+s = q + p%q <= p ...Provided p > q.
r = q
s < q
3(r+s) < 2(p+q)
Homework
• Given integers r and n I wish to find t such that rt % n = 1. .....
• Could the recursive call be written as gcd(m%n,n)?