Reviewing Mutation and Aliasing

The following code works as expected, and prints [[1,4], [2,5], [3,6]]

def trans(given):
  nrows = len(given)
  ncols = len(given[0])
  matrix = [[0,0],[0,0],[0,0]]
  for i in range(ncols):
    for j in range(nrows):
      matrix[i][j] = given[j][i]
  return matrix

a = [[1,2,3],[4,5,6]]
However, the following code prints [[3,6], [3,6], [3,6]]:
def trans(given):
  nrows = len(given)
  ncols = len(given[0])
  #matrix = [[0,0],[0,0],[0,0]] #commented this out and replaced it with the line below
  matrix = [[0]*nrows]*ncols
  for i in range(ncols):
    for j in range(nrows):
      matrix[i][j] = given[j][i]
  return matrix

a = [[1,2,3],[4,5,6]]
Why? Because the multiplication with ncols simply duplicates the references to the same list.

Here is the correct version:

def trans(given):
  nrows = len(given)
  ncols = len(given[0])
  matrix = [[0 for _ in range(nrows)] for _ in range(ncols)]  #initialize as separate lists for each row
  for i in range(ncols):
    for j in range(nrows):
      matrix[i][j] = given[j][i]
  return matrix

a = [[1,2,3],[4,5,6]]

It is worth emphasizing again that there is a subtle difference between:

In the first case, the original list (associated with L) is getting modified; while in the second case, a new list is getting created and L is then associated with the new list.

Recursion

What is recursion?

Iterative algorithms so far

Multiplication: Iterative Solution

def mult_iter(a, b):
  result = 0
  while b > 0:   #iteration
    result += a     #current value of computation: a running sum
    b -= 1          #current value of iteration variable
  return result

Multiplication: Recursive Solution

Factorial

n! = n*(n-1)*(n-2)*...*1

Recursive function scope example

def fact(n):
  if n == 1:
    return 1
  else:
    return n*fact(n-1)

print(fact(4))
Order of computation:

Some observations:

Iteration vs. Recursion.
Iteration:

def factorial_iter(n):
  prod = 1
  for i in range(1,n+1):
    prod *= i
  return prod

Recursion:
def factorial(n):
  if n == 1:
    return 1
  else:
    return n*factorial(n-1)