0% found this document useful (0 votes)
44 views58 pages

CP 07 Recursion1

Uploaded by

AR7 Studio
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views58 pages

CP 07 Recursion1

Uploaded by

AR7 Studio
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 58

BITS Pilani

K K Birla Goa Campus

CSF111: Computer Programming

Recursion I – How to think about recursion

Swaroop Joshi

2023 These slides borrow a lot from CSE2221 at OSU


Recursion

✤ A remarkably important concept and programming technique

✤ One of the most confusion concepts too!

✤ Be patient!
The question
considered now

How to think about recursion so you


can use it to develop elegant
solutions
The question The questions
considered now considered only later

How to think about recursion so you


can use it to develop elegant
solutions
The question The questions
considered now considered only later
✤ Why do recursive functions work

How to think about recursion so you


can use it to develop elegant
solutions
The question The questions
considered now considered only later
✤ Why do recursive functions work

✤ How do recursive functions work

How to think about recursion so you


can use it to develop elegant
solutions
The question The questions
considered now considered only later
✤ Why do recursive functions work

✤ How do recursive functions work

How to think about recursion so you


can use it to develop elegant
solutions
If you start by insisting on knowing the
answer to this question, you may never be
fully capable of developing elegant recursive
solutions to problems!
Implement the following function
/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
...
}
Implement the following function
/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
...
}
We have a function with the following contract!
#include<freelunch.h>
/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int fl_factorial(int n) {...}
A Free-Lunch sounds good!

✤ The slightly nasty thing about the free-lunch library is that you cannot
directly use them to solve your problems.

✤ You must make your problems smaller first!


A Free-Lunch sounds good!

✤ The slightly nasty thing about the free-lunch library is that you cannot
directly use them to solve your problems.

✤ You must make your problems smaller first!

/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
return fl_factorial(n); This will not work!
}
Recognising the smaller problem

✤ A key to recursive thinking is the ability to recognise some smaller instance


of the same problem “hiding inside” the problem you need to solve

✤ Finding → 5!

✤ Smaller subproblem → 4!

✤ How? → subtract 1 from n


Finding a factorial

✤ Make the number smaller by


subtracting one from it

✤ Call the free-lunch factorial function


on the smaller number

✤ Use the value to solve it for the


original number
Finding a factorial

✤ Make the number smaller by


subtracting one from it 5→4

✤ Call the free-lunch factorial function


on the smaller number

✤ Use the value to solve it for the


original number
Finding a factorial

✤ Make the number smaller by


subtracting one from it 5→4

✤ Call the free-lunch factorial function


on the smaller number 4! is 24

✤ Use the value to solve it for the


original number
Finding a factorial

✤ Make the number smaller by


subtracting one from it 5→4

✤ Call the free-lunch factorial function


on the smaller number 4! is 24

✤ Use the value to solve it for the Multiply this value by 5 → 5! = 5 * 4!


original number
Finding a factorial
The smaller subproblem our free-
lunch library function can handle!

✤ Make the number smaller by


subtracting one from it 5→4

✤ Call the free-lunch factorial function


on the smaller number 4! is 24

✤ Use the value to solve it for the Multiply this value by 5 → 5! = 5 * 4!


original number
It’s free-lunch time!

int factorial(int n) {
int answer = 1;
int factorial_n_minus_1 = fl_factorial(n - 1);
answer = n * factorial_n_minus_1;
return answer;
}
It’s free-lunch time!

int factorial(int n) {
int answer = 1;
int factorial_n_minus_1 = fl_factorial(n - 1);
answer = n * factorial_n_minus_1;
return answer;
}

Does it work?
Trace it!
Program State
n = 5
int answer = 1;

n = 5
answer =
int factorial_n_minus_1 = fl_factorial(n - 1);

n =
answer =
factorial_n_minus_1 =
answer = n * factorial_n_minus_1;

n =
answer =
factorial_n_minus_1 =
return answer;
Program State
n = 5
int answer = 1;

n = 5
answer = 1
int factorial_n_minus_1 = fl_factorial(n - 1);

n =
answer =
factorial_n_minus_1 =
answer = n * factorial_n_minus_1;

n =
answer =
factorial_n_minus_1 =
return answer;
Program State

How do you trace over this call? n = 5


int answer = 1; Just like any other call – in one step, by
looking at its contract!
n = 5
answer = 1
int factorial_n_minus_1 = fl_factorial(n - 1);

n =
answer =
factorial_n_minus_1 =
answer = n * factorial_n_minus_1;

n =
answer =
factorial_n_minus_1 =
return answer;
Program State
n = 5
int answer = 1;

n = 5
answer = 1
int factorial_n_minus_1 = fl_factorial(n - 1);

n = 5
answer = 1
factorial_n_minus_1 = 24
answer = n * factorial_n_minus_1;

n =
answer =
factorial_n_minus_1 =
return answer;
Program State
n = 5
int answer = 1;

n = 5
answer = 1
int factorial_n_minus_1 = fl_factorial(n - 1);

n = 5
answer = 1
factorial_n_minus_1 = 24
answer = n * factorial_n_minus_1;

n =5
answer = 120
factorial_n_minus_1 = 24
return answer;
Program State
n = 5
int answer = 1;

n = 5
answer = 1
int factorial_n_minus_1 = fl_factorial(n - 1);

n = 5
answer = 1
factorial_n_minus_1 = 24
answer = n * factorial_n_minus_1;

n =5
answer = 120
factorial_n_minus_1 = 24
return answer;
Almost done with the free-lunch!

Is this code correct?


/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
int answer = 1;
int factorial_n_minus_1 = fl_factorial(n - 1);
answer = n * factorial_n_minus_1;
return answer;
}
Almost done with the free-lunch!

Is this code correct?


/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
int answer = 1;
int factorial_n_minus_1 = fl_factorial(n - 1); What if n is 0?
answer = n * factorial_n_minus_1;
return answer;
}
Almost done with the free-lunch!

/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
Accounting for n = 0
int factorial(int n) {
int answer = 1;
if (n > 0) {
int factorial_n_minus_1 = fl_factorial(n - 1);
answer = n * factorial_n_minus_1;
}
return answer;
}
Almost done with the free-lunch!

/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
int answer = 1;
if (n > 0) {
int factorial_n_minus_1 = fl_factorial(n - 1);
answer = n * factorial_n_minus_1;
}
return answer;
} Now this works for all allowed value of n
Oh! Did I mention…
Oh! Did I mention… There is no free-lunch!
Oh! Did I mention… There is no free-lunch!

/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/ What do we do now?
int factorial(int n) {
int answer = 1;
if (n > 0) {
int factorial_n_minus_1 = fl_factorial(n - 1);
answer = n * factorial_n_minus_1;
}
return answer;
}
Do we have a function that computes a factorial
Recursion that we can call here?

/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
int answer = 1;
if (n > 0) {
int factorial_n_minus_1 = fl_factorial(n - 1);
answer = n * factorial_n_minus_1;
}
return answer;
}
Do we have a function that computes a factorial
Recursion that we can call here?

/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) { How about this one?
int answer = 1;
if (n > 0) {
int factorial_n_minus_1 = fl_factorial(n - 1);
answer = n * factorial_n_minus_1;
}
return answer;
}
Recursion

/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
int answer = 1;
if (n > 0) {
int factorial_n_minus_1 = factorial(n - 1);
answer = n * factorial_n_minus_1;
}
return answer;
}
Recursion

/**
* @brief Computes n! for the given n.
* Requires n >= 0 This is a recursive implementation of
*/ factorial, where we call the same
int factorial(int n) { function on a smaller subproblem
int answer = 1;
if (n > 0) {
int factorial_n_minus_1 = factorial(n - 1);
answer = n * factorial_n_minus_1;
}
return answer;
}
Recursion

/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
int answer = 1;
if (n > 0) {
answer = n * factorial(n - 1);
}
return answer;
}
Recursion

/**
* @brief Computes n! for the given n.
* Requires n >= 0
*/
int factorial(int n) {
int answer = 1;
if (n > 0) {
answer = n * factorial(n - 1); A more elegant version
}
return answer;
}
Crucial theorem of recursion
Crucial theorem of recursion

✤ If your code for a function is correct when it calls the (hypothetical)


FreeLunch version of the function (remember, it must be on a smaller
instance of the problem)
Crucial theorem of recursion

✤ If your code for a function is correct when it calls the (hypothetical)


FreeLunch version of the function (remember, it must be on a smaller
instance of the problem)

✤ then your code is still correct when you replace every call to the
FreeLunch version with a recursive call to your own version
Theorem applied

✤ If the code that makes a call to fl_factorial is correct,


Theorem applied

✤ If the code that makes a call to fl_factorial is correct,

✤ Then so is the code that makes a recursive call to (your own) factorial
Theorem applied

✤ If the code that makes a call to fl_factorial is correct,

✤ Then so is the code that makes a recursive call to (your own) factorial

✤ Remember: this is so only because the call to fl_factorial is for a


smaller subproblem, i.e., a smaller number.
Design recipe II* (for recursive solutions)

Data Understand the input data: int, double, char, bool, …

Smaller subproblem Finding the smaller instance of the data to pass to the recursion

Contract, Purpose, and


Describe (but don’t write) the function
Header

Examples Show what will happen when the function is done

Body The most creative step: implement the function body

Tests Run the examples


Design recipe II* (for recursive solutions)

Data Understand the input data: int, double, char, bool, …

Smaller subproblem Finding the smaller instance of the data to pass to the recursion

Contract, Purpose, and


Describe (but don’t write) the function
Header

Examples Show what will happen when the function is done

Body The most creative step: implement the function body

Tests Run the examples


Design a recursive function that…

✤ …counts the number of


digits in the given non-
negative integer
Design a recursive function that…

Data int num

✤ …counts the number of


digits in the given non-
negative integer
Design a recursive function that…

Data int num


Smaller an integer with one digit
subproblem removed

✤ …counts the number of


digits in the given non-
negative integer
Design a recursive function that…

Data int num


Smaller an integer with one digit
subproblem removed
Contract and Requires num >= 0
✤ …counts the number of Header int count_digits(int num)

digits in the given non-


negative integer
Design a recursive function that…

Data int num


Smaller an integer with one digit
subproblem removed
Contract and Requires num >= 0
✤ …counts the number of Header int count_digits(int num)

digits in the given non- 1 count_digits(0)


negative integer 1 count_digits(9)
Examples 2 count_digits(10)
2 count_digits(99)
...
Design a recursive function that…

Data int num


Smaller an integer with one digit
subproblem removed
Contract and Requires num >= 0
✤ …counts the number of Header int count_digits(int num)

digits in the given non- 1 count_digits(0)


negative integer 1 count_digits(9)
Examples 2 count_digits(10)
2 count_digits(99)
...

Body //??
Design a recursive function that…

Data int num


Smaller an integer with one digit
subproblem removed
Contract and Requires num >= 0
✤ …counts the number of Header int count_digits(int num)

digits in the given non- 1 count_digits(0)


negative integer 1 count_digits(9)
Examples 2 count_digits(10)
2 count_digits(99)
...

Body //??
Test //??
Design a recursive function that…

/**
* @brief Reports the number of digits in the given integer.
* Requires num >= 0
*/
int count_digits(int num) {
int answer = 1;

answer = 1 + fl_count_digits(num / 10);

return answer;
}
Design a recursive function that…

/**
* @brief Reports the number of digits in the given integer.
* Requires num >= 0
*/
int count_digits(int num) { Does it handle all possible
int answer = 1; values of num?

answer = 1 + fl_count_digits(num / 10);

return answer;
}
Design a recursive function that…

/**
* @brief Reports the number of digits in the given integer.
* Requires num >= 0
*/
int count_digits(int num) {
int answer = 1;
if (num > 9) {
answer = 1 + fl_count_digits(num / 10);
}
return answer;
}
Design a recursive function that…

/**
* @brief Reports the number of digits in the given integer.
* Requires num >= 0
*/
int count_digits(int num) {
int answer = 1;
if (num > 9) {
answer = 1 + fl_count_digits(num / 10);
}
return answer;
}
Now? Remove scaffolding!
Design a recursive function that…

/**
* @brief Reports the number of digits in the given integer.
* Requires num >= 0
*/
int count_digits(int num) {
int answer = 1;
if (num > 9) {
answer = 1 + fl_count_digits(num
fl_ / 10);
}
return answer;
}

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy