{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "

cs1001.py , Tel Aviv University, Winter 2020

\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Recitation 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We tested if a positive integer (or a range of integers) satisfies the Collatz conjecture (using \"while\" and \"for\" loops). \n", "We discussed the basics of lists, the efficiency of list operations and how to efficiently concatenate a list to another. We also demonstrated list comprehension. \n", "Finally, we discussed functions, short circuit evaluation and analyzed the efficiency of the functions we saw.\n", "\n", "#### Takeaways:\n", "\n", "
    \n", "
  1. Lists can be a highly modular and useful data structure. Make sure that you understand their functionality and also their limits (figuratively and literally).
  2. \n", "
  3. Avoid using the + operator for extending a given list. Use += or list.extend() instead.\n", "
  4. Functions can be used in one another (max2 in max3_v3) and can be composed together.
  5. \n", "
  6. When analyzing a function's performance, think about the input that will cause the largest amount of work and then measure how many operations the function does.
  7. \n", "
  8. Using short circuit evaluation, if e.g. you have a long \"and\" condition, place the part that is most easy to compute first since if it is false, all other parts of the condition will not be computed.
  9. \n", "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Code for printing several outputs in one cell (not part of the recitation):" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from IPython.core.interactiveshell import InteractiveShell\n", "InteractiveShell.ast_node_interactivity = \"all\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Collatz Conjecture\n", "\n", "The Collatz Conjecture, from Wikipedia:\n", "\n", "Start with any positive integer $n$. Each term in the Collatz sequence is obtained from the previous term as follows: \n", "* If the previous term is even, the next term is one half the previous term: $n \\to n // 2$ \n", "* If the previous term is odd, the next term is 3 times the previous term plus 1: $n \\to 3\\cdot n + 1$ \n", "* If we reach $1$, we stop\n", "\n", "The Collatz conjecture is the following statement: for any $n \\geq 1$, the sequence above reaches $1$ in a finite amount of steps." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Check conjecture for a single number:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Enter a positive integer to apply Collatz algorithm: 7\n", "7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1\n", "7 is OK!\n" ] } ], "source": [ "orig_num = int(input(\"Enter a positive integer to apply Collatz algorithm: \"))\n", "num = orig_num\n", "\n", "while num > 1:\n", " print(num, end=\" \")\n", " if num % 2 == 0:\n", " num = num // 2\n", " else:\n", " num = 3*num + 1\n", "\n", "print(num)\n", "print(orig_num, \"is OK!\")\n", "\n", "\n", " \n", " \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Check conjecture for a range of numbers:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Check Collatz algorithm for 1 ... 8\n", "1\n", "1 is OK!\n", "2 1\n", "2 is OK!\n", "3 10 5 16 8 4 2 1\n", "3 is OK!\n", "4 2 1\n", "4 is OK!\n", "5 16 8 4 2 1\n", "5 is OK!\n", "6 3 10 5 16 8 4 2 1\n", "6 is OK!\n", "7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1\n", "7 is OK!\n", "8 4 2 1\n", "8 is OK!\n" ] } ], "source": [ "limit = int(input(\"Check Collatz algorithm for 1 ... \"))\n", "\n", "orig_num = 1\n", "while orig_num <= limit:\n", " num = orig_num\n", "\n", " while num > 1:\n", " print(num, end=\" \")\n", " if num % 2 == 0:\n", " num = num // 2\n", " else:\n", " num = 3*num + 1\n", "\n", " print(num)\n", " print(orig_num, \"is OK!\")\n", " \n", " orig_num += 1\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The type $range$\n", "\n", "We've met the python type $range$ in the lecture. Given integers $a,b,c$, $range(a,b,c)$ represents the range of indices from $a$, up to (and excluding) $b$, in intervals of size $c$.\n", "\n", "We can also declare simpler range variables by the following logic:\n", "* $range(a) = range(0,a,1)$\n", "* $range(a,b) = range(a,b,1)$\n" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n" ] } ], "source": [ "for i in range(10):\n", " print(i)\n", " " ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "3\n", "5\n" ] } ], "source": [ "for i in range(1, 7, 2):\n", " print(i)\n" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "7\n", "5\n", "3\n" ] } ], "source": [ "for i in range(7, 1, -2):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Check conjecture for a range of numbers (using \"for\")" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Check Collatz algorithm for 1 ... 4\n", "1\n", "1 is OK!\n", "2 1\n", "2 is OK!\n", "3 10 5 16 8 4 2 1\n", "3 is OK!\n", "4 2 1\n", "4 is OK!\n" ] } ], "source": [ "limit = int(input(\"Check Collatz algorithm for 1 ... \"))\n", "\n", "\n", "for orig_num in range(1, limit + 1):\n", " num = orig_num\n", "\n", " while num > 1:\n", " print(num, end=\" \")\n", " if num % 2 == 0:\n", " num = num // 2\n", " else:\n", " num = 3*num + 1\n", "\n", " print(num)\n", " print(orig_num, \"is OK!\")\n", " \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Lists - Basics\n", "\n", "A Python list is a collection of **ordered** elements. The elements can be of different types, they can include repetitions and they can even include lists.\n", "\n", "Python allows us to check how many elements a list contains using the $len(lst)$ function, and access an element at index $i$ using the command $lst[i]$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hello\n" ] }, { "ename": "IndexError", "evalue": "list assignment index out of range", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mIndexError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[0mlst\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m1000\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[0mlst\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 12\u001b[1;33m \u001b[0mlst\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m8\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m40\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 13\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mIndexError\u001b[0m: list assignment index out of range" ] } ], "source": [ "x = 10\n", "lst = [x, 1, 2, 3, \"name\", print, True, [3.14, 2.5]]\n", "len(lst)\n", "lst[4]\n", "lst[5]\n", "lst[5](\"hello\")\n", "#lst[100]\n", "lst[-1]\n", "lst[-1][0]\n", "lst[1] = 1000\n", "lst\n", "lst[8] = 40\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The empty list\n", "\n", "Just like we've seen the important empty string (''), there is an important list in python - the empty list (that is - the list containing no items).\n", "\n", "What would we expect the length of the empty list to be? What can we expect will happen if we try to access to first element in that list?" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "scrolled": true }, "outputs": [ { "ename": "IndexError", "evalue": "list index out of range", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mIndexError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mempty_lst\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mempty_lst\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mempty_lst\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mIndexError\u001b[0m: list index out of range" ] } ], "source": [ "empty_lst = []\n", "len(empty_lst)\n", "empty_lst[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## List slicing\n", "\n", "List slicing is a method of extracting a sublist from an existing one. The syntax should be familiar, it is the same as the syntax for range. Specifically, $lst[a:b:c]$ will give us the sublist of $lst$, starting from index $a$, up to (and exclusive of) $b$, in intervals of size $c$." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "[3, , [3.14, 2.5]]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lst = [x, 1, 2, 3, \"name\", print, True, [3.14, 2.5]]\n", "lst[3: 8: 2]\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## List concatenation\n", "\n", "Again, similar to what we've seen last week with strings, a natural action to take given two lists $l1, l2$ is concatenation: a list containing $len(l1)+len(l2)$ items, where the first $len(l1)$ items are those of $l1$ and the rest are those of $l2$.\n", "\n", "There are various methods of concatenating lists in python, let's look at them and discuss their pros and cons." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bad coding:\n", "Good coding:\n" ] } ], "source": [ "lst1 = [1, 2, 3]\n", "lst2 = [10, 20, 30]\n", "\n", "# Creating a new concatenated list\n", "lst_new = lst1 + lst2\n", "lst_new\n", "lst1\n", "lst2\n", "\n", "# Adding the elements of lst2 to lst1\n", "print(\"Bad coding:\")\n", "lst1 = lst1 + lst2\n", "lst1\n", "\n", "print(\"Good coding:\")\n", "lst1 = [1, 2, 3]\n", "lst2 = [10, 20, 30]\n", "lst1.extend(lst2)\n", "lst1\n", "lst1.append(10)\n", "lst1\n", "lst1.append(lst2)\n", "lst1\n", "\n", "lst1 = [1,2,3]\n", "lst2 = [10,20,30]\n", "lst1 += lst2 #invokes extend!!\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Common List functions\n", "\n", "We've seen the $len(\\cdot)$ function, and in a sense, the indexing call $lst[i]$ is also a function. What other builtin functions does Python supply for lists?" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-24.5" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lst = [10, -40.5, 6]\n", "sum(lst)" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[-40.5, 6, 10]" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[10, -40.5, 6]" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[-40.5, 6, 10]" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lst = [10, -40.5, 6]\n", "slst = sorted(lst)\n", "slst\n", "lst\n", "\n", "lst.sort()\n", "lst" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Iterating over lists\n", "\n", "Let's combine two things we've seen today: loops and lists.\n", "\n", "Given a list, it is easy to iterate over the list elements. One way of doing that is to initialize an index $i=0$ and use a $while$ loop to iterate over $i < len(lst)$ where in each iteration we can access the $i$-th element in the list via the command $lst[i]$" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n", "hi\n", "bye\n", "100\n" ] } ], "source": [ "lst = [1, 2, 3, 4, \"hi\", \"bye\", 100]\n", "i = 0\n", "while i < len(lst):\n", " print(lst[i])\n", " i += 1" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "But wait, this is a very structured loop! Given $lst$, we know exactly how many iterations it will run and so it makes much more sense to do a similar iteration with a for loop iterating over the $range$ of the length of the list:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n", "hi\n", "bye\n", "100\n" ] } ], "source": [ "lst = [1, 2, 3, 4, \"hi\", \"bye\", 100]\n", "for i in range(len(lst)):\n", " print(lst[i])\n", " " ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Finally, we have another option. A list is what we call an \"iterable\" type in python, meaning there is a natural way for python to iterate over the elements of the list.\n", "We can use this natural iteration by iteration over the **elements** of the list using a for loop:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n", "hi\n", "bye\n", "100\n" ] } ], "source": [ "lst = [1, 2, 3, 4, \"hi\", \"bye\", 100]\n", "for item in lst:\n", " print(item)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Think? When would it make sense to loop over the list using the $range$ of the length of the list and when would it make sense to simply loop over the elements themselves?\n", "\n", "## Exercise: given grades, how many are there above average?" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "#### solution 1: using loops" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "How many grades? 4\n", "enter a grade: 10\n", "enter a grade: 78\n", "enter a grade: 60.5\n", "enter a grade: 92\n", "3 grades are above the average 60.125\n" ] } ], "source": [ "count = int(input(\"How many grades? \"))\n", "above = 0\n", "\n", "grades = []\n", "for i in range(count):\n", " grade = float(input(\"enter a grade: \"))\n", " #grades[i] = grade #wrong\n", " #grades.append(grade)\n", " #grades.extend([grade])\n", " grades += [grade] #invokes extend\n", " #grades = grades + [grade] #bad coding!\n", " \n", "s = sum(grades)\n", "avg = s/count\n", "\n", "for grade in grades:\n", " if grade > avg:\n", " above += 1\n", "\n", "print(above, \"grades are above the average\", avg)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### list comprehension example:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 3, 6, 9]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[0, 9, 36, 81]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "['!', '!', '!', '!']" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" }, { "data": { "text/plain": [ "[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n", "\n", "lst1 = [x for x in lst if x % 3 == 0]\n", "lst1\n", "lst2 = [x**2 for x in lst if x % 3 == 0]\n", "lst2\n", "lst3 = [\"!\" for x in lst if 2*x > 10]\n", "lst3\n", "lst4 = [1 for x in lst]\n", "lst4\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A list comprehension command has the following structure:\n", "\n", "lst = [x for y in object if cond]\n", "\n", "And is equivalent to the following piece of code:\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "'type' object is not iterable", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mlst\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32mfor\u001b[0m \u001b[0my\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mobject\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mcond\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[0mlst\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mTypeError\u001b[0m: 'type' object is not iterable" ] } ], "source": [ "lst = []\n", "for y in object:\n", " if cond:\n", " lst.append(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Solution 2: using list comprehension" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "How many grades? 3\n", "enter a grade: 100\n", "enter a grade: 50\n", "enter a grade: 20\n", "1 grades are above the average 56.666666666666664\n" ] } ], "source": [ "count = int(input(\"How many grades? \"))\n", "above = 0\n", "\n", "grades = []\n", "#try to replace this loop by list comprehension exp\n", "for i in range(count):\n", " grade = float(input(\"enter a grade: \"))\n", " #grades[i] = grade #wrong\n", " #grades.append(grade)\n", " #grades.extend([grade])\n", " grades += [grade] #invokes extend\n", " #grades = grades + [grade] #bad coding!\n", " \n", "s = sum(grades)\n", "avg = s/count\n", "\n", "\n", "above = len([grade for grade in grades if grade > avg])\n", "\n", "print(above, \"grades are above the average\", avg)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functions: max2, max3\n", "\n", "In the code we've seen so far we made use of various built-in python functions (print, len, etc). \n", "\n", "Each call to such a function is actually a call to a sequence of commands encapsulated within it \n", "\n", "For example, printing a string encapsulates an iteration over the characters of the string, printing each one in turn. Had we needed to call this sequence of command each time we wanted to print a string, our code would look a lot more messy.\n", "\n", "Similarly, we would like to have the option of defining a complex operation that is easily callable, and for that we use functions:" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "30" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" }, { "ename": "TypeError", "evalue": "max2() missing 1 required positional argument: 'b'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[0mx\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mmax2\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m10\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;36m30\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 13\u001b[1;33m \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mmax2\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m10\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mTypeError\u001b[0m: max2() missing 1 required positional argument: 'b'" ] } ], "source": [ "def max2(a,b):\n", " '''\n", " max2(float,float) ---> float\n", " return the maximum od a and b\n", " '''\n", " if a>=b:\n", " return a\n", " #else:\n", " # return b\n", " return b\n", "\n", "x = max2(10,30)\n", "x\n", "y = max2(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### max3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So we know how to find the maximum between two numbers. What do we do if we're given 3 numbers?\n", "\n", "Given $a,b,c$, we can check whether $a$ is the largest (i.e., $a \\geq b$ and $a \\geq c$). If this is not the case we can check if $b$ is the largest similarly ($b \\geq a$ and $b \\geq c$). If this is also False, we must have that $c$ is the largest.\n", "\n", "Let's see the code:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def max3_v1(a,b,c):\n", " if a >= b and a >= c:\n", " return a\n", " elif b >= a and b >= c:\n", " return b\n", " else:\n", " return c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But...\n", "\n", "Come to think of it, we already know how to find the maximum between two numbers. How can we use the function $max2$ in order to solve $max3$ without \"reinventing the wheel\"?" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def max3_v3(a,b,c):\n", "## max_ab = max2(a,b)\n", "## total_max = max2(max_ab,c)\n", "## return total_max\n", " return max2(max2(a,b), c)\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Collatz over range, with functions" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "1 is OK!\n", "2 1\n", "2 is OK!\n", "3 10 5 16 8 4 2 1\n", "3 is OK!\n", "4 2 1\n", "4 is OK!\n", "5 16 8 4 2 1\n", "5 is OK!\n", "6 3 10 5 16 8 4 2 1\n", "6 is OK!\n" ] } ], "source": [ "\n", "def collatz(orig_num):\n", " num = orig_num\n", " \n", " while num > 1:\n", " print(num, end=\" \")\n", " if num%2 == 0:\n", " num = num//2\n", " else:\n", " num = 3*num+1\n", " \n", " print(num)\n", " print(orig_num, \"is OK!\")\n", " \n", "def collatz_range(limit):\n", " for num in range(1, limit + 1):\n", " collatz(num)\n", "\n", "collatz_range(6)\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Short circuit evaluation\n", "\n", "When python evaluates logical expressions, there are certain cases where the evaluation can be \"cut short\" in the middle of the expression. Consider the following example: given the predicate $a \\textrm{ or } b$ and prior knowledge that $a = True$, do we really need to evaluate $b$?\n", "\n", "The answer is no, since $True \\textrm{ or } b = True$ for any $b$.\n", "\n", "And since python is smart and efficient, given such a predicate, after evaluating $a = True$ python will immediately interpret the whole predicate as $True$ without evaluating $b$:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" }, { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mx\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m3\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m \u001b[1;32mor\u001b[0m \u001b[1;32mTrue\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 5\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero" ] } ], "source": [ "x = True or 3/0\n", "x\n", "\n", "x = 3/0 or True\n", "x\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What do we expect will happen on the hand, given a predicate of the form $a \\textrm{ and } b$?" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" }, { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mx\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;32mTrue\u001b[0m \u001b[1;32mand\u001b[0m \u001b[1;36m3\u001b[0m\u001b[1;33m/\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 5\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero" ] } ], "source": [ "x = False and 3/0\n", "x\n", "\n", "x = True and 3/0\n", "x" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "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.7.1" } }, "nbformat": 4, "nbformat_minor": 1 }