1. Write a function that returns the Pythagorean triplet (a, b, c) given any two of the arguments a, b or c.

For example, triplet(a=3, c=5) will return (3, 4, 5).


In [1]:
import numpy as np

In [16]:
def triplet(a=None, b=None, c=None):
    """Returns the Pythagoraen tripler (a, b, c) given any two arguments.
    
    Assumes but does not check that two named argumets are called.
    Retruns None if no triplet possible with given arguments.
    """
    
    if a is None:
        q, r = divmod(np.sqrt(c**2 - b**2), 1)
        if r == 0:
            return int(q), b, c
    elif b is None:
        q, r = divmod(np.sqrt(c**2 - a**2), 1)
        if r == 0:
            return a, int(q), c
    else:
        q, r= divmod(np.sqrt(a**2 + b**2), 1)
        if r == 0:
            return a, b, int(q)

In [15]:
triplet(a=3, c=5)


Out[15]:
(3, 4, 5)

In [17]:
triplet(a=3, b=5)

2. The $n^\text{th}$ Catalan number is given by $$ C_n = \prod_{k=2}^n \frac{n+k}{k} $$ for $n \ge 0$.

Write a function to calculate the $n^\text{th}$ Catalan number - it should take a single argument $n$ and return $C_n$. Use this function to generate a list of the first 10 odd Catalan numbers (i.e., n = 1, 3, 5, ...).


In [22]:
def catalan(n):
    """Returns the nth Catalan number."""
    
    ans = 1
    for k in range(2, n+1):
        ans *= (n+k)/k
    return ans

In [23]:
[catalan(n) for n in range(1, 10, 2)]


Out[23]:
[1, 5.0, 41.99999999999999, 428.99999999999994, 4862.0]

3. Rewrite the above function as a lambda function. This is tricky but introduces you to the functional style that is very useful in advanced programming. Some imports are done for you as a hint.


In [24]:
from functools import reduce
from operator import mul

In [29]:
catalan_L = lambda n: reduce(mul, ((n+k)/k for k in range(2, n+1)), 1)

In [30]:
[catalan_L(n) for n in range(1, 10, 2)]


Out[30]:
[1, 5.0, 41.99999999999999, 428.99999999999994, 4862.0]

4. Write a class called Matrix that can be initialized with an iterable of numbers, together with the number of rows r and the number of columns c. That is, you should be able to create a matrix M by calling M = Matrix([1,2,3,4], 2, 2) (assume the matrix is row ordered). The Matrix class will have a single additional method called at that takes a tuple (r, c) and returns the value at row r and column c. For example, M.at(0,1) will return 2. Internally, the data should be stored as a list and the at method will use indexing to find the right value to return.


In [1]:
class Matrix:
    """Simple class to represent a matrix."""
    
    def __init__(self, xs, rows, cols):
        self.xs = list(xs)
        self.rows = rows
        self.cols = cols  
            
    def at(self, i, j):
        idx = i*self.cols + j
        return self.xs[idx]

In [49]:
M =  Matrix([1,2,3,4], 2, 2)

In [50]:
M.at(0,1)


Out[50]:
2