Solutions to Sheet 1 by Nikolai Nøjgaard

In [1]:
import itertools as it
In [2]:
# Problem 1
def sphere_volume(r):
    return 4/3 * 3.14159 * r**3

sphere_volume(4)
Out[2]:
268.08234666666664
In [3]:
# Problem 2
def isolate(a, b, c, d, e):
    print(a, b, sep="     ", end="     ")
    print(c, d, e)

isolate(1, 2, 3, 4, 5)
1     2     3 4 5
In [4]:
# Problem 3.1
def first_half(string):
    return string[:int(len(string)/2)]

first_half("12345")
Out[4]:
'12'
In [5]:
# Problem 3.2
def backward(string):
    print(string[::-1]) # [start:end:step]

backward("abcd")
dcba
In [6]:
# Problem 4
def list_ops():
    lst = ["bear", "ant", "cat", "dog"];    print("1: {}".format(lst))
    lst.append("eagle");                    print("2: {}".format(lst))
    lst[2] = "fox";                         print("3: {}".format(lst))
    lst.pop(1);                             print("4: {}".format(lst))
    lst.sort(reverse=True);                 print("5: {}".format(lst))
    lst[lst.index("eagle")] = "hawk";       print("6: {}".format(lst))
    lst[-1] += " hunter";                   print("7: {}".format(lst))
    return lst

list_ops()
1: ['bear', 'ant', 'cat', 'dog']
2: ['bear', 'ant', 'cat', 'dog', 'eagle']
3: ['bear', 'ant', 'fox', 'dog', 'eagle']
4: ['bear', 'fox', 'dog', 'eagle']
5: ['fox', 'eagle', 'dog', 'bear']
6: ['fox', 'hawk', 'dog', 'bear']
7: ['fox', 'hawk', 'dog', 'bear hunter']
Out[6]:
['fox', 'hawk', 'dog', 'bear hunter']
In [7]:
# Problem 5
def pig_latin(word):
    vowels = ("a", "e", "i", "o", "u")
    return word + "hay" if word[0] in vowels else word[1:] + word[0] + "ay"

print(pig_latin("apple"), pig_latin("rock"))
applehay ockray
In [8]:
# Problem 6
def palindrome():
    return max(i*j for i, j in it.product(range(100, 1000), repeat=2) if str(i*j) == str(i*j)[::-1])

palindrome()
Out[8]:
906609
In [9]:
# Problem 7 - w/ list comprehension
def alt_harmonic(n):
    return sum([(-1)**(i+1)/i for i in range(1, n+1)])

print(alt_harmonic(5))
0.7833333333333332
In [10]:
# Problem 8
def list_info(lst):
    return min(lst), max(lst), sum(lst)/len(lst)

print(list_info((2, 3, 4, 5)))
(2, 5, 3.5)
In [11]:
# Problem 9
objects = [1, "a", [0], (0,), {0}]
for o1 in objects:
    o2 = o1
    if type(o1) is set: 
        o2.add(1) 
    else: 
        o2 += o1
    print(f"{type(o1)} o1 ({id(o1)}): {o1}, o2 ({id(o2)}): {o2}, equals?: {o1 == o2}")
    
<class 'int'> o1 (94345518095680): 1, o2 (94345518095712): 2, equals?: False
<class 'str'> o1 (140315967851248): a, o2 (140315844505200): aa, equals?: False
<class 'list'> o1 (140315853208640): [0, 0], o2 (140315853208640): [0, 0], equals?: True
<class 'tuple'> o1 (140315853193424): (0,), o2 (140315912353792): (0, 0), equals?: False
<class 'set'> o1 (140315853101088): {0, 1}, o2 (140315853101088): {0, 1}, equals?: True
In [12]:
# Problem 10
# calculator.py
from math import sqrt
def my_sum(addend1, addend2):
    return addend1 + addend2

def product(factor1, factor2):
    return factor1 * factor2

# other_file.py

# from calculator.py import *
def hypotenuse(side1, side2):
    return my_sum(product(side1, side1), product(side2, side2))
    
hypotenuse(2, 3)
Out[12]:
13
In [13]:
# problem 11
# example of how to generate random numbers
import random
print(random.randrange(1, 100)) # 100 is not included
51
In [14]:
# problem 12
def powerset(i):
    lst = list(i)
    return list(it.chain.from_iterable(it.combinations(lst, r) for r in range(len(lst)+1)))

powerset((1, 2, 3))

# why not set of sets? because sets are not hashable.
Out[14]:
[(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
In [15]:
# problem 13
class Backpack:
    """A Backpack object class. Has a name, color, max size, and
       a list of contents.

    Attributes:
        name (str): the name of the backpack's owner.
        color (str): the color of the backpack
        max_size (int): the max size
        contents (list): the contents of the backpack.
    """

    # Problem 13: Modify __init__() and put(), and write dump().
    def __init__(self, name, color, max_size=5):
        """Set the name, color, max size, and initialize
           an empty list of contents.

        Parameters:
            name (str): the name of the backpack's owner.
            color (str): the color of the backpack
            max_size(int, optional): max size of backpack

        """
        self.name = name
        self.color = color
        self.max_size = max_size
        self.contents = []

    def put(self, item):
        """Add an item to the backpack's list of contents unless it is full."""
        if len(self.contents) == self.max_size:
            print("No room!")
        else:
            self.contents.append(item)

    def take(self, item):
        """Remove an item from the backpack's list of contents."""
        self.contents.remove(item)

    def dump(self):
        """Remove all items from backpack."""
        self.contents.clear()

    # Magic Methods -----------------------------------------------------------

    # Problem 15: Write __eq__() and __str__().
    def __add__(self, other):
        """Add the number of contents of each Backpack."""
        return len(self.contents) + len(other.contents)

    def __lt__(self, other):
        """Compare two backpacks. If 'self' has fewer contents
        than 'other', return True. Otherwise, return False.
        """
        return len(self.contents) < len(other.contents)

    def __eq__(self, o):
        return (self.name, self.color, self.contents) == (o.name, o.color, o.contents)

    def __str__(self):
        return "<<Owner:\t{}\nColor:\t\t{}\nSize:\t\t{}\nMax Size:\t{}\nContents:\t{}>>".format(
            self.name, self.color, len(self.contents), self.max_size, self.contents)
In [16]:
# problem 13 - test function
def test_backpack():
    test = Backpack("foo", "green", max_size=4)
    if test.name != "foo":
        print("Name is incorrect.")
    for item in ["book", "pencil case"]:
        test.put(item)
    print("Contents: ", test.contents)

    # problem 15 - test magic methods
    print(str(test))
    test2 = Backpack("foo", "green", max_size=4)
    for item in ["book", "pencil case"]:
        test2.put(item)
    print(test == test2)


test_backpack()
Contents:  ['book', 'pencil case']
<<Owner:	foo
Color:		green
Size:		2
Max Size:	4
Contents:	['book', 'pencil case']>>
True
In [17]:
# Problem 14: Write a 'Jetpack' class that inherits from the 'Backpack' class.
class Jetpack(Backpack):
    """A jetpack that inherints from backpack.

    Attributes:
    - name (str): name of owner
    - color (str): color of backpack
    - max_size (int): max size of backpack
    - fuel: current fuel of the backpack"""

    def __init__(self, name, color, max_size=2, fuel=10):
        """Call the super class' constructor and initialize fuel

        Parameters:
        - name (str): name of owner
        - color (str): color of backpack
        - max_size (int): max size of backpack
        - fuel: current fuel of the backpack"""
        Backpack.__init__(self, name, max_size)
        self.fuel = fuel

    def fly(self, fuel_val):
        """Reduce the fuel amount for flying."""
        if self.fuel - fuel_val <= 0:
            print("Not enough fuel!")
        else:
            self.fuel -= fuel_val

    def dump(self):
        """Dump the contents of the backpack and fuel"""
        self.contents.clear()
        self.fuel = 0
In [18]:
# problem 16
# warning: don't execute in here, use ipython
def random_walk(max_iters=1e12):
    walk = 0
    directions = [1, -1]
    try:
        for i in range(int(max_iters)):
            walk += random.choice(directions)
    except KeyboardInterrupt:
        print("Process interupted at iteration " + str(i))
    else:
        print("Process completed")
    return walk

random_walk(10)
Process completed
Out[18]:
2
In [19]:
# problem 17
# warning: don't execute here, use ipython if the file does not exist
class ContentFilter:
    def __init__(self, given_file_name):
        self.file_name = ""
        self.contents = ""
        try:
            with open(given_file_name, "r") as f:
                self.file_name = given_file_name
                self.contents = f.read()
        except IOError:
            print("File not found. Try another name.")
            while (True):
                input_file_name = input()
                try:
                    with open(input_file_name, "r") as f:
                        self.file_name = input_file_name
                        self.contents = f.read()
                        break
                except IOError:
                    print("File not found. Try another name.")

#content_filter = ContentFilter("foo.txt")
In [20]:
# Problem 18
import numpy as np
def multiply_matrices():
    A = np.array([[3, -1, 4], [1, 5, -9]])
    B = np.array([[2, 6, -5, 3], [5, -8, 9, 7], [9, -3, -2, -3]])
    return A @ B

multiply_matrices()
Out[20]:
array([[ 37,  14, -32, -10],
       [-54,  -7,  58,  65]])
In [21]:
# problem 19
def mult_matrix_with_self():
    A = np.array([[3, 1, 4], [1, 5, 9], [-5, 3, 1]])
    return -np.linalg.matrix_power(A, 3) + 9*np.linalg.matrix_power(A, 2) - 15*A

mult_matrix_with_self()
Out[21]:
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])
In [22]:
# problem 20
def array_creation():
    A = np.triu(np.ones((7, 7)))
    B = np.tril(-np.ones((7, 7))) + np.triu(np.full((7,7), 5), 1)
    return A @ B @ A

array_creation()
Out[22]:
array([[ -7.,  -8.,  -3.,   8.,  25.,  48.,  77.],
       [ -6., -12., -12.,  -6.,   6.,  24.,  48.],
       [ -5., -10., -15., -14.,  -7.,   6.,  25.],
       [ -4.,  -8., -12., -16., -14.,  -6.,   8.],
       [ -3.,  -6.,  -9., -12., -15., -12.,  -3.],
       [ -2.,  -4.,  -6.,  -8., -10., -12.,  -8.],
       [ -1.,  -2.,  -3.,  -4.,  -5.,  -6.,  -7.]])
In [23]:
# problem 21
def fancy_zeros(A):
    B = A.copy()
    B[B < 0] = 0
    return B

fancy_zeros(np.array([[-10, 5], [-30, 20]]))
Out[23]:
array([[ 0,  5],
       [ 0, 20]])
In [24]:
# problem 22
def stacking():
    A = np.array([[0, 2, 4], [1, 3, 5]])
    B = np.array([[3, 0, 0], [3, 3, 0], [3, 3, 3]])
    C = np.array([[-2, 0, 0], [0, -2, 0], [0, 0, -2]])
    col1 = np.vstack((np.zeros((2, 3)), A, B))
    col2 = np.vstack((A.T, np.zeros((2, 2)), np.zeros((2, 2))))
    col3 = np.vstack((np.eye(3), np.zeros((1, 3)), C))
    return np.hstack((col1, col2, col3))

stacking()
Out[24]:
array([[ 0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  2.,  3.,  0.,  1.,  0.],
       [ 0.,  2.,  4.,  4.,  5.,  0.,  0.,  1.],
       [ 1.,  3.,  5.,  0.,  0.,  0.,  0.,  0.],
       [ 3.,  0.,  0.,  0.,  0., -2.,  0.,  0.],
       [ 3.,  3.,  0.,  0.,  0.,  0., -2.,  0.],
       [ 3.,  3.,  3.,  0.,  0.,  0.,  0., -2.]])
In [25]:
# problem 23
def stoch_mat(A):
    # it is a row vector when it should be column
    # Equivalent: return A/A.sum(axis=1).reshape(3,1)
    return A/A.sum(axis=1)

stoch_mat(np.array([[2, 3],[3, 2]]))
Out[25]:
array([[0.4, 0.6],
       [0.6, 0.4]])
In [26]:
# problem 24
def approximate_pi(non_zero_terms):
    f = np.math.factorial
    coefs = np.zeros(non_zero_terms*2+1)
    for n in range(non_zero_terms):
        coefs[n*2+1] = f(2*n)/((2*n+1)*(f(n)**2)*4**n)
    # arcsin(.5) = 6 * pi
    return 6*np.polynomial.polynomial.polyval(.5, coefs)
pi_vals = np.arange(1, 15)
np.vectorize(approximate_pi)(pi_vals)
Out[26]:
array([3.        , 3.125     , 3.1390625 , 3.14115513, 3.14151117,
       3.14157672, 3.14158943, 3.14159198, 3.14159251, 3.14159262,
       3.14159265, 3.14159265, 3.14159265, 3.14159265])