# MAS212 Class Test 1 (2018)¶

## Aim:¶

• To help you learn some Python essentials and programming skills to enjoy the remainder of this course.

How it works:

• Complete the notebook below, as follows. Click on a question, then from the menu select Insert -> Insert Cell Below. From the dropdown box (next to the "stop" symbol) choose whether you wish to insert 'Code' or 'Markdown'. Save regularly!
• Press Shift-Enter to execute the code in a cell.
• Submit the .ipynb file via http://somas-uploads.shef.ac.uk/mas212 by 23.59pm on Sun 7th Oct 2018. If you are off-campus, you will need to use a VPN to submit.
• Your lecturer will mark each question as either 2 (good), 1 (needs revision), 0 (not attempted/wrong).
• This is an open-book test, which means you may consult books, notes and internet resources. Do not discuss or share your test with anyone. Copy-and-pasting is not permitted. Please give answers in your own words.
• Some of these questions are relatively straightforward, and some are harder (e.g. Q10, 11, 13, 19, 20). Please don't spend any longer than a maximum of 3 hours on this test, as it is for a relatively small amount of credit.

Key Resources:

• Lecture materials and links on course web page: http://sam-dolan.staff.shef.ac.uk/mas212/

## A. The Python language

1. True or False? (i) Python is case-sensitive. (ii) Strings are mutable.

Statement (i) is True and statement (ii) is False.

2. In your own words, describe the list and set containers, highlighting at least one similarity and one difference between them.

Lists and sets are container types. They may contain any number of other objects, or may be empty. Sets and lists may contain objects of different types (e.g. int, float, str, etc). They are mutable, and are not of a fixed size. Both are iterable. Lists are ordered, and allow duplicates. By contrast, sets are unordered and do not allow duplicate elements. Lists can be indexed, sets cannot.

3. What is "vectorization"? What is a Universal Function, also known as a ufunc?

Vectorization is the practice of replacing for loops with array expressions, so that batch operations are implemented efficiently in a fast compiled language such as C. A Universal Function is a function that can act on a whole array, in an element-by-element fashion.

For example, suppose I wanted to apply "sin" to every element in an array A. I could do this by looping over the array, and applying math.sin to each element in turn. A better, vectorized way to do this is by applying a ufunc: np.sin(A).

4. Broadcasting. Let A, B and C be arrays with shapes (3,3,4), (1,4) and (4,4), respectively. Which of the following products exist, under the rules of broadcasting?
(i) A\*A ; (ii) A\*B ; (iii) A\*C.

Products (i) and (ii) exist (A\*A and A\*B). The product (iii) A\*C does not exist.

## B. Python code

5. Python as a calculator: Calculate $6 \times 2$, $(3^2 + 5^2)^{1/3}$, $(3 + 5i)^{3}$ and $\exp(-i\pi/4)$.

In [6]:
import math, cmath
[6*2, (3**2+5**2)**(1/3), (3+5*1j)**3, cmath.exp(-1j*math.pi/4)]

Out[6]:
[12, 3.239611801277483, (-198+10j), (0.7071067811865476-0.7071067811865475j)]

6. Find the following sum: $$\sum_{k=1}^{10} k^{-k} = 1^{-1} + 2^{-2} + 3^{-3} + \ldots + 10^{-10} .$$ Now print() your result to 12 decimal places.

In [9]:
mysum=sum([k**(-k) for k in range(1,11)])
print("%.12f" % mysum)

1.291285997059


7. Calculate and display $\ln(2)$ to 5 significant figures, by using a truncated version of the series $$\ln(2) = 1 - 1/2 + 1/3 - 1/4 + 1/5 - \ldots$$

In [12]:
tot = 0
for k in range(1,500000):
tot += 1/k*(-1)**(k+1)
print("%.5f" % tot)

0.69315


8. Write code to generate a list of the first 15 Triangular Numbers: [1,3,6,10,15, $\ldots$, 120]

In [13]:
[k*(k+1)//2 for k in range(1,16)]

Out[13]:
[1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120]

9. Write code to save your name and registration number, on separate lines, into a file "me.txt".

In [17]:
f = open("me.txt", "w")
f.write("Sam Dolan\n")
f.write("012345679")
f.close()


10. Write a function pascal(n) to calculate the n-th row of Pascal's triangle as a list. For example, pascal(3) should return the list [1,3,3,1].
print() the 20th row.

In [24]:
def pascal(n):
row = [1,1]
for i in range(1,n):
row = [1] + [row[i+1]+row[i] for i in range(len(row)-1)] + [1]
return row
print(pascal(20))

[1, 20, 190, 1140, 4845, 15504, 38760, 77520, 125970, 167960, 184756, 167960, 125970, 77520, 38760, 15504, 4845, 1140, 190, 20, 1]


11. Write code to implement the secant method to compute the largest root of $f(x) = x^3 - 5x - 1$ to 5 decimal places, starting with the initial values $x_0 = 2.1$ and $x_1 = 2.5$.

In [25]:
x0, x1 = 2.1, 2.5
def f(x):
return x**3 - 5*x - 1
maxits =10
tol = 1e-6
for k in range(maxits):
xnew = (x0*f(x1) - x1*f(x0))/(f(x1) - f(x0))
x0, x1 = x1, xnew
if abs(x1-x0) < tol:
break
print("%.5f" % ((x0+x1)/2))

2.33006


## C. String processing

In [27]:
s = "A man, a plan, a canal - Panama!"
print(s)

A man, a plan, a canal - Panama!


12. Write code to count how many times the first letter of the alphabet appears in the string above (case insensitive: count both 'a' and 'A').

In [28]:
s.count('a') + s.count('A')

Out[28]:
10

13. Write a function checkpalindrome(s) which returns True if the phrase in s is a palindrome, and False otherwise. Check your function works by using the string above. (Task: remove all punctuation and spaces from the string; change it to lowercase; then check whether the string is equal to its reverse).

In [32]:
def checkpalindrome(s):
punc = ",.!- "
for c in punc:
s = s.replace(c, "")
s = s.lower()
print(s)
palin = False
if s == s[::-1]:
palin = True
return palin

print(checkpalindrome(s))

amanaplanacanalpanama
True


## D. numpy and linear algebra

In [33]:
import numpy as np
xs = np.array([0.868, 0.836, 0.410, 0.657, 0.071, 0.602, 0.806, 0.325, 0.872, 0.475])


14. Write code to find the mean average of data set xs (above) by using the formula $$\langle x\rangle = \frac{1}{n} \sum_i x_i$$

In [35]:
xmean = xs.sum() / len(xs)
print(xmean)

0.5922


15. Write code to find the variance of the data set xs by using the formula $$\text{var} = \langle x^2 \rangle - \langle x \rangle^2$$ [N.B. Do not use the functions xs.mean() or xs.var() in Q14 and Q15].

In [38]:
x2mean = (xs**2).sum() / len(xs)
var = x2mean - xmean**2
print(var)

0.06537756


16. Let $A$ be the $2 \times 2$ matrix $$A = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}.$$ Use Python to calculate $A^{10}$ (i.e. $A$ multiplied by itself 10 times) using the rules of matrix multiplication.
Make a conjecture about the entries in $A^n$.

In [42]:
A = np.matrix([[1,1],[1,0]])
A10 = A**10
print(A10)
# Conjecture:  The entries of A^n are the Fibonacci numbers F_{n+1} (top left),
# F_n (top right & bottom left) and F_{n-1} (bottom right).

[[89 55]
[55 34]]


17. Find the eigenvalues of the real symmetric matrix $$A = \begin{bmatrix} -1 & 2 & 3 \\ 2 & 4 & 1 \\ 3 & 1 & -3 \end{bmatrix} .$$ and verify that the sum of the eigenvalues is zero.

In [43]:
A = np.matrix("-1,2,3 ; 2,4,1 ; 3,1,-3")
eigs = np.linalg.eig(A)[0]
print("The eigenvalues are %.6f, %.6f and %.6f" % tuple(eigs))
print("The sum of eigenvalues is %.4e, which is zero to within machine precision." % sum(eigs))

The eigenvalues are -5.177534, -0.037039 and 5.214573
The sum of eigenvalues is -3.5527e-15, which is zero to within machine precision.


## E. Polynomials

In [44]:
from numpy.polynomial import Polynomial
p = Polynomial([3,2,1])  # This is a quadratic polynomial: x^2 + 2x + 3.
p**2 # p^2 is a quartic polynomial: (x^2 + 2x + 3)^2 = x^4 + 4x^3 + 10x^2 + 12x + 9

Out[44]:
Polynomial([  9.,  12.,  10.,   4.,   1.], [-1.,  1.], [-1.,  1.])

18. Use the Polynomial class (imported above) to find the roots of the quartic polynomial $$p(x) = 2 x^4 + 5x^3 - 18x^2 - 27x + 54 .$$ Hint: p.roots()

In [54]:
p = Polynomial([54,-27,-18,5,2])
rts = p.roots()
print("The roots of the quartic polynomial are: [%.3f, %.3f, %.3f, %.3f]" % tuple(rts) )

The roots of the quartic polynomial are: [-3.000, -3.000, 1.500, 2.000]


19. Check that the polynomial $y(x) = 35 x^4 - 30 x^2 + 3$ is a solution of Legendre's differential equation for $n=4$, by substituting it into the left-hand side of the differential equation below, and showing that the LHS is zero. $$\frac{d}{dx} \left[ (1 - x^2) \frac{d y}{d x} \right] + n(n+1) y = 0 .$$ (Hint: Use p.deriv() to take the derivative of a polynomial p.)

In [56]:
y = Polynomial([3,0,-30,0,35])
tmp = Polynomial([1,0,-1])*y.deriv()
n = 4
tmp2 = tmp.deriv() + n*(n+1)*y
print(tmp2)

poly([ 0.])


## F. Cryptography

20. The name of a Fields Medallist has been scrambled using a One-Time Pad with a key made from the digits of $\pi$. Write code to unscramble the ciphertext to find a person's name.
The ciphertext is: PBVZFVOOWCFSQHWL.

(Hint: the first letter of the person's name is M: this is found by shifting the first letter of the ciphertext P back by 3 letters (3 is the first digit of $\pi$). The next letter should be shifted back by 1, the next by 4, and so on. You may find the functions chr() and ord() useful.)

In [67]:
ciphertext = "PBVZFVOOWCFSQHWL"
pidigits   = "3141592653589793"
plaintext  = ""
for i in range(len(ciphertext)):
c = ciphertext[i]
shift = int(pidigits[i])
plaintext += chr((ord(c) - shift - 65) % 26 + 65)
print(plaintext)

MARYAMMIRZAKHANI


The person is Maryam Mirzakhani, who won the Fields Medal in 2014 for her work on the dynamics and geometry of Riemann surfaces and their moduli spaces.

In [ ]: