Generators

Exercise 1.1: Moving average

Write a generator that computes the moving average over a list of values.

For example, let $v = [1, 2 ,3, 4]$ be a list of $4$ integers. The moving average $ma$ over $v$ is $ma = [1, \frac{3}{2}, 2, \frac{5}{2}]$.


In [16]:
v = [1,2,3,4]

In [27]:
# Overwrite the function moving_avg
def moving_avg():
    avg = None
    _sum = 0
    _cnt = 0
    while True:
        term = yield avg
        _cnt += 1
        _sum += term
        avg = _sum / _cnt

In [28]:
# Testing your function
ma = moving_avg()
next(ma)

mavg = []
for value in v:
    mavg.append(ma.send(value))
    
mavg # Should print: [1.0, 1.5, 2.0, 2.5]


Out[28]:
[1.0, 1.5, 2.0, 2.5]

List comprehensions

Exercise 2.1: Unconditional comprehensions

Write the following code as a comprehension

v1 = [1, 2, 3, 4, 5]
v2 = []

for n in v1:
    v2.append(n * 2)

In [29]:
v1 = [1, 2, 3, 4, 5]

In [30]:
v2 = [x * 2 for x in v1]

In [31]:
v2 # Should print: [2, 4, 6, 8, 10]


Out[31]:
[2, 4, 6, 8, 10]

Exercise 2.2: Conditional comprehensions

Let $v1$ be a list of integers from 0 to 99


In [32]:
v1 = list(range(100))

Write a single line of code to create $v2$ as a list of squares of all even elements of $v1$


In [34]:
# Write your code here
v2 = [x ** 2 for x in v1 if x % 2 == 0]

In [35]:
v2 # Should print: [0, 4, 16, 36, 64, 100, ... ]


Out[35]:
[0,
 4,
 16,
 36,
 64,
 100,
 144,
 196,
 256,
 324,
 400,
 484,
 576,
 676,
 784,
 900,
 1024,
 1156,
 1296,
 1444,
 1600,
 1764,
 1936,
 2116,
 2304,
 2500,
 2704,
 2916,
 3136,
 3364,
 3600,
 3844,
 4096,
 4356,
 4624,
 4900,
 5184,
 5476,
 5776,
 6084,
 6400,
 6724,
 7056,
 7396,
 7744,
 8100,
 8464,
 8836,
 9216,
 9604]

Exercise 2.3: Approximate $\Pi$

Let $x$ and $y$ be random vectors of size $N$


In [40]:
import random

N = 100000

x = [random.random() for a in range(N)]
y = [random.random() for a in range(N)]

Write a single line of code to approximate $\Pi$ using the Monte Carlo method


In [42]:
# Write your code here
pi = 4 * len([1 for _x, _y in zip(x, y) if _x * _x + _y * _y <= 1]) / N
pi


Out[42]:
3.14544
Hint 1: $\frac{\Pi}{4} = \frac{\text{area of inscribed circle}}{\text{area of rectangle}}$
Hint 2: $\text{Check out the zip() function}$

Lambda Operator and the functions map() and reduce()

Exercise 3.1: Approximate the exponential function

Approximate the Maclaurin series for the exponential function at X with a polynomial of degree K

Please use the map() & reduce() functions


In [51]:
from functools import reduce
from math import factorial
import operator

K = 10
X = 4

def evaluate_polynomial(a, x):
    # Write your code here
        # xi: [x^0, x^1, x^2, ..., x^(K-1)]
        # axi: [a[0]*x^0, a[1]*x^1, ..., a[K-1]*x^(K-1)]
        # return sum of axi
    xi = [x ** k for k in range(K)]
    axi = [_a * _x for _a, _x in zip(a, xi)]
    return sum(axi)

In [52]:
evaluate_polynomial([1/factorial(x) for x in range(0, K)], X)
# For K=10 and X=4, should print: 54.15414462081129


Out[52]:
54.15414462081129

Lists of characters and the functions join() and append()

Exercise 4.1: Smart password generator

Write a function for generating a password of $N$ characters. Your password must have a fair number of lowercase letters, uppercase letters, and numbers. For example, if $N = 8$, you start filling out the list with 2 lowercase letters, 2 uppercase letters and 2 numbers. Then you complete the list with $N - 3*2$ lowercase letters.

Please use of the join(), append() and random.shuffle() functions.


In [69]:
import random

lowercase_letters = "abcdefghijklmnopqrstuvwxyz"
uppercase_letters = lowercase_letters.upper()

N = 8
password = []

for i in range(2):
    password.append(random.choice(lowercase_letters))

for i in range(2):
    password.append(random.choice(lowercase_letters))
    
for i in range(2):
    password.append(random.randint(0, 9))
    
for i in range(N - 3 * 2):
    password.append(random.choice(lowercase_letters))
    
password = "".join(map(lambda x: str(x), password))
    
# Add your code here
print(str(password))


cxsg34it