Functions and Recursion in Python
Data and File Structures Laboratory
http://www.isical.ac.in/~dfslab/2020/index.html
DFS Lab (ISI) Functions and Recursion in Python 1 / 20
Parameter passing
def function1 (x) : def function3 (l) :
x = 10 l = [ 10 ]
return return
def function2 (x) : def function4 (l) :
x = x + 1 l[0] = 10
return return
def function5 (l) :
l = l + l
print(l)
return
def function6 (l) :
l.extend(l)
return
DFS Lab (ISI) Functions and Recursion in Python 2 / 20
Standard parameter passing mechanisms
Call by value
argument expressions evaluated
values copied into local storage area of called function
changes made to parameters in called function not reflected in caller
Call by reference
reference to argument (its address) copied into local storage area of
called function
changes made to argument variables in callee are reflected in caller
Call by name
DFS Lab (ISI) Functions and Recursion in Python 3 / 20
Parameter passing in Python
Call by reference
Immutable arguments (integers, strings, tuples): passed by value or
reference (doesn’t matter)
Mutable arguments: passed by reference
in place changes reflected in caller
if the name is reassigned, it points to a different object
DFS Lab (ISI) Functions and Recursion in Python 4 / 20
Parameter passing in Python
Call by reference
Immutable arguments (integers, strings, tuples): passed by value or
reference (doesn’t matter)
Mutable arguments: passed by reference
in place changes reflected in caller
if the name is reassigned, it points to a different object
>>> x = 10
>>> id(x)
10914784
x x now points to a
x = x + 1 different object
>>> y = 10 x = a
>>> id(y) vs.
10914784 x
>>> y = y+1 x.inplace_operation()
>>> id(y) x = b
10914816
DFS Lab (ISI) Functions and Recursion in Python 4 / 20
Recursion
A recursive function is a function that calls itself.
The task should be decomposable into sub-tasks that are smaller, but
otherwise identical in structure to the original problem.
The simplest sub-tasks (called the base case) should be (easily)
solvable directly, i.e., without decomposing it into similar
sub-problems.
DFS Lab (ISI) Functions and Recursion in Python 5 / 20
Recursive vs. iterative implementations
def factorial(n) :
# Not recommended!
if n < 0 : return -1 def factorial(n) : # Recursive implementation
prod = 1 if n < 0 : return -1 # Error condition
while n > 0 : if n == 0 : return 1 # Base case
prod *= n return n * factorial(n-1) # Recursive call
n = n - 1
return prod
DFS Lab (ISI) Functions and Recursion in Python 6 / 20
Z curve
Problem statement
Consider a 2-D matrix of size 2m × 2m . The entries of the matrix are, in
row-major order, 1, 2, 3, . . . , 22m . Print the entries of the matrix in Z-curve
order (as shown in the picture below).
DFS Lab (ISI) Functions and Recursion in Python 7 / 20
Z curve: structure
(0, 0) Problem structure:
Base case: single
element
Recursive structure:
break given square
into 4 sub-squares
process squares in
Z-curve order
(N − 1, N − 1)
DFS Lab (ISI) Functions and Recursion in Python 8 / 20
Z curve: code
def z_curve(matrix, top_left_row, top_left_column, bottom_right_row,
bottom_right_column) :
# Base case
if top_left_row == bottom_right_row and \
top_left_column == bottom_right_column :
print("%d" % matrix[top_left_row][top_left_column], end=" ")
return
TLC
TLR
BRR
BRC
DFS Lab (ISI) Functions and Recursion in Python 9 / 20
Z curve: code
def z_curve(matrix, top_left_row, top_left_column, bottom_right_row,
bottom_right_column) :
# Base case
if top_left_row == bottom_right_row and \
top_left_column == bottom_right_column :
print("%d" % matrix[top_left_row][top_left_column], end=" ")
return
TLC BRC
TLR TLR
BRR BRR
TLC BRC
DFS Lab (ISI) Functions and Recursion in Python 9 / 20
Z curve: code
def z_curve(matrix, top_left_row, top_left_column, bottom_right_row,
bottom_right_column) :
# Base case
if top_left_row == bottom_right_row and \
top_left_column == bottom_right_column :
print("%d" % matrix[top_left_row][top_left_column], end=" ")
return
TLC (TLC + BRC)//2 (TLC + BRC)//2 + 1 BRC
TLR TLR
BRR BRR
TLC BRC
DFS Lab (ISI) Functions and Recursion in Python 9 / 20
Z curve: code
def z_curve(matrix, top_left_row, top_left_column, bottom_right_row,
bottom_right_column) :
# Base case
if top_left_row == bottom_right_row and \
top_left_column == bottom_right_column :
print("%d" % matrix[top_left_row][top_left_column], end=" ")
return
TLC (TLC + BRC)//2 (TLC + BRC)//2 + 1 BRC
TLR TLR
(TLC + BRC)//2 (TLC + BRC)//2 + 1
BRR BRR
TLC (TLC + BRC)//2 (TLC + BRC)//2 + 1 BRC
DFS Lab (ISI) Functions and Recursion in Python 9 / 20
Z curve: code
def z_curve(matrix, top_left_row, top_left_column, bottom_right_row,
bottom_right_column) :
# Base case
if top_left_row == bottom_right_row and \
top_left_column == bottom_right_column :
print("%d" % matrix[top_left_row][top_left_column], end=" ")
return
TLC (TLC + BRC)//2 (TLC + BRC)//2 + 1 BRC
TLR TLR
(TLR + BRR)//2 (TLC + BRC)//2 (TLC + BRC)//2 + 1
(TLR + BRR)//2 + 1
BRR BRR
TLC (TLC + BRC)//2 (TLC + BRC)//2 + 1 BRC
DFS Lab (ISI) Functions and Recursion in Python 9 / 20
Z curve: code
# Recurse
# upper-left sub-square
z_curve(matrix,
top_left_row,
top_left_column,
(top_left_row + bottom_right_row)//2,
(top_left_column + bottom_right_column)//2)
# upper-right sub-square
z_curve(matrix,
top_left_row,
(top_left_column + bottom_right_column)//2 + 1,
(top_left_row + bottom_right_row)//2,
bottom_right_column)
# lower-left sub-square
z_curve(matrix,
(top_left_row + bottom_right_row)//2 + 1,
top_left_column,
bottom_right_row,
(top_left_column + bottom_right_column)//2)
DFS Lab (ISI) Functions and Recursion in Python 10 / 20
Z curve: code
# lower-right sub-square
z_curve(matrix,
(top_left_row + bottom_right_row)//2 + 1,
(top_left_column + bottom_right_column)//2 + 1,
bottom_right_row,
bottom_right_column)
return
DFS Lab (ISI) Functions and Recursion in Python 11 / 20
Z curve: code
# lower-right sub-square
z_curve(matrix,
(top_left_row + bottom_right_row)//2 + 1,
(top_left_column + bottom_right_column)//2 + 1,
bottom_right_row,
bottom_right_column)
return
N = 2**2
i = 1; j = 0
A = [ [ x for x in range(j*N+i, j*N+i+N) ] for j in range(N) ]
z_curve(A,0,0,N-1,N-1); print()
DFS Lab (ISI) Functions and Recursion in Python 11 / 20
Permutations
Algorithm
To generate all permutations of 1, 2, 3, . . . , n, do the following:
1. Generate all permutations of 2, 3, . . . , n.
2. For each of the permutations generated above
(1) add 1 in the beginning;
(2) add 1 in the 2nd position;
...
(n) add 1 at the end.
DFS Lab (ISI) Functions and Recursion in Python 12 / 20
Permutations: code
def permute(A) :
n = len(A)
if n < 2: return [ A ]
# Need recursion for n >=2
permlist = [ ]
for p in permute(A[1:]) :
for position in range(n) :
p.insert(position, A[0])
permlist.append(p.copy())
p.pop(position)
return permlist
DFS Lab (ISI) Functions and Recursion in Python 13 / 20
Problems – I
1. Towers of Hanoi: see
https://en.wikipedia.org/wiki/Tower_of_Hanoi
CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=228623
2. Write a recursive function with prototype int C(int n, int r); to
compute the binomial coefficient using the following definition:
( ) ( ) ( )
n n−1 n−1
= +
r r r−1
Supply appropriate boundary conditions.
DFS Lab (ISI) Functions and Recursion in Python 14 / 20
Problems – II
3. Define a function G(n) as:
0 if n = 0
1 if n = 1
G(n) =
2 if n = 2
G(n − 1) + G(n − 2) + G(n − 3) if n ≥ 3
Write recursive and iterative (i.e., non-recursive) functions to compute
G(n).
DFS Lab (ISI) Functions and Recursion in Python 15 / 20
Problems – III
4. What does the following function compute?
int f ( int n )
{
int s = 0;
while (n--) s += 1 + f(n);
return s;
}
5. http://cse.iitkgp.ac.in/~abhij/course/lab/PDS/Spring15/
A4.pdf
DFS Lab (ISI) Functions and Recursion in Python 16 / 20
Problems – IV
6. In chess, a knight can move to a cell that is horizontally 2 cells and vertically 1 cell away, or
vertically 2 cells and horizontally 1 cell away (see Fig. 6). Thus, eight moves are possible for a
knight in general.
DFS Lab (ISI) Functions and Recursion in Python 17 / 20
Problems – V
Given an m × n chess-like board, and a knight at position (i, j) (where 0 ≤ i < m and
0 ≤ j < n), compute the probability that the knight remains on the board after a given number
(say k) of steps, assuming that, at each step, all eight moves are equally likely. Note that, once
the knight moves off the board, it can never return to the board.
Input Format
mnijk
Output Format
The probability value rounded up to 6 decimal places.
Sample Input 0
12011
Sample Output 0
0.000000
Sample Input 1
88331
Sample Output 1
1.000000
Sample Input 2
66001
Sample Output 2
0.250000
Sample Input 3
44002
DFS Lab (ISI) Functions and Recursion in Python 18 / 20
Problems – VI
Sample Output 3
0.125000
Explanation for the above
0 1 2 3
The knight starts at the top-left corner
(0,0). After 1 move, it may either move
0 0/2/2 2
off the board (permanently), or go to the
squares marked 1 (in red / blue). After
another move from the square marked
1 1 2 with a red (respectively, blue) 1, it lands
on one of the squares marked with a red
(respectively, blue) 2, or moves off the
2 2 1 board. The knight stays on the board for
8 distinct sequences of moves (of 2
steps each). The total number of such
3 2 2/2 moves of 2 steps each is 8 × 8 = 64.
DFS Lab (ISI) Functions and Recursion in Python 19 / 20
Problems – VII
7. Write a program that takes a positive integer n ≤ 5, and a non-negative integer k ≤ 100 as
command-line arguments, and computes the total number of cells reachable from any starting
cell within an infinite, n-dimensional grid in k steps or less. See the examples below. You are
only permitted to travel in a direction that is parallel to one of the grid lines; diagonal movement
is not permitted.
NOTE: If you are interested, you may compute a closed-form expression for the required
number, but DO NOT use the closed-form expression to compute the answer to this problem.
Starting Cell
n = 1, k = 2; number of cells reachable = 5
2 1 2
2 1 0 1 2
2 1 2
n = 2, k = 2; number of cells reachable = 13
For n = 3, your output for k = 0, 1 and 2 should be 1, 7, and 25, respectively.
DFS Lab (ISI) Functions and Recursion in Python 20 / 20