RECURSION

In [4]:
def f(x):
    return x**2
In [5]:
f(4)
Out[5]:
16
In [6]:
f(5)
Out[6]:
25
In [7]:
f(-1)
Out[7]:
1
In [8]:
f(1.2)
Out[8]:
1.44
In [9]:
f("John")
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-4e27636d03a2> in <module>
----> 1 f("John")

<ipython-input-4-4261cf13ee74> in f(x)
      1 def f(x):
----> 2     return x**2

TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
In [16]:
# recursive solution to finding length
def length(xs):
    if xs == []:
        return 0
    else:
        return 1 + length(xs[1:])
In [23]:
length(['a','b',3])
Out[23]:
3
In [21]:
#non-recursive length function
def length1(xs):
    result = 0
    for x in xs:
        result = result + 1
    return result
In [22]:
length1([1,2,3])
Out[22]:
3
In [26]:
def factorial(n):
    if n < 0:
        return None
    elif n == 0:
        return 1
    else:
        return n*factorial(n-1)
In [36]:
print(factorial(20))
2432902008176640000
In [37]:
def sum_list_1(xs): # non-recursive
    result = 0
    for x in xs:
        result = result + x
    return result
In [38]:
sum_list_1([10,20,30])
Out[38]:
60
In [39]:
def sum_list_2(xs): # recursive
    if xs == []:
        return 0
    else:
        return xs[0] + sum_list_2(xs[1:])
In [40]:
sum_list_2([10,20,30])
Out[40]:
60
In [41]:
def max_list_1(xs):
    if xs == []:
        return None
    else:
        result = xs[0]
        for x in xs[1:]:
            if x > result:
                result = x
        return result
In [42]:
max_list_1([10,20,30])
Out[42]:
30
In [53]:
def max_list_2(xs):
    if xs == []:
        return None
    elif len(xs) == 1:
        return xs[0]
    else:
        tail_max = max_list_2(xs[1:])
        if xs[0] > tail_max:
            return xs[0]
        else:
            return tail_max
        #max(xs[0], max_list_2(xs[1:]))
In [54]:
max_list_2([10,20,30])
Out[54]:
30
In [45]:
max(10,20)
Out[45]:
20
In [55]:
def fibonacci(n):
    # return the nth fibonacci number
    if n <= 0:
        return None
    elif n == 1:
        return 1
    elif n == 2:
        return 1
    else:
        return fibonacci(n-1) + fibonacci(n-2)
    # this solution has repeated calculations which can be avoided by being clever (-:
In [56]:
fibonacci(6)
Out[56]:
8
In [60]:
for (x,y) in zip([1,2,3],['John','Alice','Bob','David']):
    print(x,y)
1 John
2 Alice
3 Bob
In [61]:
def zipp1(xs,ys):
    result = []
    if len(xs) < len(ys):
        for i in range(len(xs)):
            result.append((xs[i],ys[i]))
    else:
        for i in range(len(ys)):
            result.append((xs[i],ys[i]))
    return result  
In [64]:
zipp1([1,2,3,4,5],['John','Alice','Bob','David'])
Out[64]:
[(1, 'John'), (2, 'Alice'), (3, 'Bob'), (4, 'David')]
In [67]:
def zipp2(xs,ys):
    if xs == [] or ys == []:
        return []
    else:
        return [(xs[0],ys[0])] + zipp2(xs[1:],ys[1:])
In [68]:
zipp2([1,2,3,4,5],['John','Alice','Bob','David'])
Out[68]:
[(1, 'John'), (2, 'Alice'), (3, 'Bob'), (4, 'David')]
In [69]:
zipp2([2,3,4,5],['Alice','Bob','David'])
Out[69]:
[(2, 'Alice'), (3, 'Bob'), (4, 'David')]

Quicksort

In [70]:
def partition(pivot,xs):
    small = []
    large = []
    for x in xs:
        if x <= pivot:
            small.append(x)
        else:
            large.append(x)
    return (small,large)
In [74]:
partition(20,[5,9,20,2,3,8,9,16])
Out[74]:
([5, 9, 20, 2, 3, 8, 9, 16], [])
In [72]:
def quicksort(xs):
    if xs == []:
        return []
    else:
        pivot = xs[0]
        (small,large) = partition(pivot,xs[1:])
        return quicksort(small) + [pivot] + quicksort(large)
In [73]:
quicksort([5,9,20,2,3,8,9,16])
Out[73]:
[2, 3, 5, 8, 9, 9, 16, 20]
average time complexity = O(n logn)
In [ ]: