{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["([Home](https://mannymoo.github.io/IntroductionToPython/))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# SUPAPYT - Hands on Exercises"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Here're some suggested exercises to help familiarise you with python.\n", "- We'll work through them in the labs, but you can of course try them in your own time too."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## 1)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Make sure you can start the interactive interpreter from the commandline, as discussed in the [Getting started](https://mannymoo.github.io/IntroductionToPython/Getting-started.html) guide.\n", "- Start the interpeter, evaluate some simple maths expressions and then quit it."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## 2)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Try writing a simple script and passing it to the interpreter via the commandline ([see here](https://mannymoo.github.io/IntroductionToPython/Getting-started.html#Python-Scripts)).\n", "- This can be as simple as the \"Hello world!\" example in the lectures.\n", "- You can do the rest of the exercises at the commandline using a combination of the interactive interpreter and scripts, or using the Jupyter notebook format (if you have Jupyter installed). It's up to you which to use, so long as you know how to do both (or at least the use of the commandline).\n", "- The main point is: there are several different ways of interacting with the python interpreter, but it's the same interpreter working in the background. Different use cases benefit from different means of interaction. "]}, {"cell_type": "markdown", "metadata": {}, "source": ["## 3)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Convert `101010` from binary to base 10."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["- Convert `2a` from hexidecimal to base 10."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 4)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Write a function to calculate the length of the hypotenuse of a right angle triangle given the lengths of the other two sides.\n", "- What's the hypotenuse of a right angle triangle with other sides of length 6 and 8?"]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["- Here's an interesting aside on why even simple functions like calculating the hypotenuse can get complicated due to finite numerical precision: [Hypot \u2013 A story of a \u2018simple\u2019 function](https://walkingrandomly.com/?p=6633)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## 5)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- The above is an example of a [Pythagorean triple](https://en.wikipedia.org/wiki/Pythagorean_triple), as all three sides are integers.\n", "- Write a function which tests for Pythagorean triples:\n", " - Take the length of the other two sides as arguments.\n", " - Check if they're integers.\n", " - Calculate the hypotenuse.\n", " - Check if it's an integer.\n", " - Return `True` if all three are integers, else `False`.\n", "- Verify that (6, 8) is a Pythagorean triple.\n", "- Check (32, 46), (161, 240), and (372, 496).\n", "- Note that you want to check if the __value__ of the hypotenuse is an integer, not if it's of type `int` (since a `float` can have an integer value)."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 6)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Using two nested `for` loops, find all Pythagorean triples with hypotenuse < 100.\n", "- Put each triple into a `tuple` of length 3 and add it to a list containing all the triples.\n", "- Loop over the list of all triples and print them in columns of width three, eg, (6, 8, 10) $\\to$"]}, {"cell_type": "markdown", "metadata": {}, "source": ["` 6 8 10`"]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 7)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Try overriding one of the built-in types, like `list`, `int` or `str` by making a variable with that name (eg, `int = 3` - normally you should avoid doing this).\n", "- Verify that the built-in type is lost.\n", "- Can you recover it?"]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 8)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- We've discussed briefly the idea of \"mutable\" and \"immutable\" objects in python.\n", "- All basic types are immutable apart from lists and dictionaries.\n", "- See what happens when you assign two variables to the same object, then change one of the variable.\n", " - Eg, assign two variables to the same `int` value, then change the value of one of the variables and check if it changes the value of the other variable.\n", " - Try doing the same but assign a `list` instead of an `int`. Modify the the list (change/delete/add an element) and check the values of both variables."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["- In python the variable name and the object to which it refers are distinct.\n", "- In C++ terms, every variable in python is like a pointer.\n", "- For mutable objects you can access and modify the object via any variable assigned to it.\n", "- For immutable objects any attempt to change the object either raises an exception or creates a new object and assigns it to the variable. \n", "- The `id` built-in method returns a unique integer for every object (try `help(id)`) so you can use it to check if variables refer to the same object, or if an operation has modified an existing object or assigned a new object to the same variable."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 9)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Given the above, can you work out how you'd make a copy of a list, rather than creating a new variable that refers to the same list?\n", "- There are a few different ways."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 10)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- When slicing sequences (where supported) you can give a thrid int after a second colon"]}, {"cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["[2, 3, 4]\n"]}], "source": ["# Eg:\n", "l = [1,2,3,4,5]\n", "print(l[1:4:1])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Try to work out what this third int means. What happens if you give it a negative value?"]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 11)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Define a string with your name with your name and write a script to provide your name in reverse with all vowels capitalised and all consonants lower case.\n", "- Eg, `'Brave Sir Robin' => 'nIbOr rIs EvArb'`"]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 12)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- In addition to supporting function arguments of any type, python also has syntax for functions that can take a variable number of arguments.\n", "- For unnamed arguments this is done like so:"]}, {"cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [], "source": ["# Eg:\n", "def arguments(*args) :\n", " print('args =', args)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Try calling this function with different numbers of arguments (including none).\n", "- What is the type of `args` within the function?"]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["- You can also give arbitrary named arguments to a function like so:"]}, {"cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [], "source": ["# Eg:\n", "\n", "def named_args(**kwargs) :\n", " print('kwargs =', kwargs)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Then try calling it in various ways:"]}, {"cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [{"name": "stdout", "output_type": "stream", "text": ["kwargs = {}\n", "kwargs = {'a': 1, 'b': 2}\n", "kwargs = {'t': ('a', 'b', 'c'), 'l': [1, 2, 3], 'f': 3.5}\n"]}, {"ename": "TypeError", "evalue": "named_args() takes 0 positional arguments but 1 was given", "output_type": "error", "traceback": ["\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mnamed_args\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mnamed_args\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'a'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'b'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'c'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ml\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m3.5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mnamed_args\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: named_args() takes 0 positional arguments but 1 was given"]}], "source": ["# Eg:\n", "\n", "named_args()\n", "named_args(a = 1, b = 2)\n", "named_args(t = ('a', 'b', 'c'), l = [1, 2, 3], f = 3.5)\n", "named_args(1, n = 3)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- What type is `kwargs` within the method?\n", "- The last call fails as the method only expects named arguments."]}, {"cell_type": "markdown", "metadata": {}, "source": ["- The most flexible method, that takes an arbitrary number of unnamend and named arguments thus has this form:"]}, {"cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [], "source": ["# Eg:\n", "\n", "def args_and_keywords(*args, **kwargs) :\n", " print('args =', args)\n", " print('kwargs =', kwargs)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Give it a try and see what ways you can pass it arguments."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 13)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Write a class to represent a 3 component vector with x, y & z attributes.\n", "- Write the `__init__` member function to take values for x, y & z, with their default values being zero.\n", "- Write a member function to return the dot product of the vector with another 3-vector, which is passed as an argument.\n", "- Write a `__add__` member function that returns a new 3-vector that's the sum of the vector with another given as an argument, so you can use the `+` operator on instances of your class.\n", "- Write a member function to check if the vector is orthogonal to another 3-vector, ie, their dot product is zero.\n", "- Use instances of your class to verify that the vectors (4, -7, 9) and (54, -18, -38) are orthogonal.\n", "- Do the same for (890, 3254, 6404) + (542, -912, 834) and (1227, -484, -97) + (-8465, 7722, -813), making use of the `+` operator on instances of your class."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 14)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Use the `date` class from the `datetime` module to work out how old you are in days.\n", "- On what date will you be/were you 10000 days old?"]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 15)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Use `pickle` to save the date on which you're 10000 days old to a file, then load it again and verify that it's the same date you started with."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["## 16)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- Take [this file](https://raw.githubusercontent.com/MannyMoo/IntroductionToPython/master/vectors.txt), which has three integers per line, read each set of three into an instance of your 3-vector class defined in Q. 13, and add these to a list.\n", "- Check each 3-vector in the list against every other 3-vector in the list to see if they're orthogonal, and count how many (unique) pairs of vectors are orthogonal."]}, {"cell_type": "code", "execution_count": 0, "metadata": {}, "outputs": [], "source": []}, {"cell_type": "markdown", "metadata": {}, "source": ["([Home](https://mannymoo.github.io/IntroductionToPython/))"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.1"}}, "nbformat": 4, "nbformat_minor": 1}