diff --git a/sum23/lecture_materials/06_Iteration1/lec_06_Iteration_notes.ipynb b/sum23/lecture_materials/06_Iteration1/lec_06_Iteration_notes.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..745cbc25b16b1735d7ebc4613be8af8a19cdd7fb --- /dev/null +++ b/sum23/lecture_materials/06_Iteration1/lec_06_Iteration_notes.ipynb @@ -0,0 +1,918 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "dd1c3a1b", + "metadata": {}, + "source": [ + "# Iteration\n", + "\n", + "## Readings:\n", + "\n", + "### For Friday\n", + "- Chapter 7 of Think Python\n", + "- Chapter 6.1 to 6.3 of Python for Everybody\n", + "\n", + "### For Monday\n", + "- Chapter 2 of Sweigart book\n", + "- Chapter 6.4 of Python for Everybody" + ] + }, + { + "cell_type": "markdown", + "id": "595d2e5b", + "metadata": {}, + "source": [ + "## Learning Objectives:\n", + "\n", + "- Implement an iterative algorithm using a `while` loop, for\n", + " - printing / counting\n", + " - validating user input\n", + " - performing an iterative calculation\n", + " - printing character art\n", + "\n", + "- Trace iterative algorithms and determine their output\n", + "\n", + "- Recognize common `while` loop errors\n", + " - Infinite loops (when unintentional)\n", + " - Off-by-one mistakes in the loop control variable\n", + "\n", + "- Read and trace through Python code containing nested loops.\n", + "\n", + "- Read and trace through Python code using `break` or `continue` in a `while` loop\n", + "\n", + "- Determine the effect of break and continue in nested loops" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "c30a8ea2", + "metadata": {}, + "outputs": [], + "source": [ + "# import statements\n", + "\n", + "import time\n", + "import math" + ] + }, + { + "cell_type": "markdown", + "id": "f113fc7b", + "metadata": {}, + "source": [ + "### Example 0: Simple countdowns" + ] + }, + { + "cell_type": "markdown", + "id": "73959e77", + "metadata": {}, + "source": [ + "**How to termination infinite loop in:**\n", + "- jupyter: Kernel > Interrupt (fix and then re-run)\n", + "- script mode / interactive mode: Ctrl + C (Kill signal)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb8de263", + "metadata": {}, + "outputs": [], + "source": [ + "#TODO: Copy/paste this example into PythonTutor\n", + "#Count from 0 to 3, printing each number\n", + "count = 0\n", + "\n", + "while count <= 3:\n", + " print(count)\n", + " count += 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "23dbc9da", + "metadata": {}, + "outputs": [], + "source": [ + "#TODO: Copy/paste this example into PythonTutor\n", + "#Count from 3 to -3, printing each number\n", + "count = 3\n", + "\n", + "while count >= -3:\n", + " print(count)\n", + " count -= 1" + ] + }, + { + "cell_type": "markdown", + "id": "115e8742", + "metadata": {}, + "source": [ + "### Example 1: Countdown timer alarm" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "42f4a48f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "How many seconds?5\n", + "5 seconds left\n", + "4 seconds left\n", + "3 seconds left\n", + "2 seconds left\n", + "1 seconds left\n", + "BEEP BEEP BEEP BEEP BEEP BEEP BEEP BEEP BEEP BEEP \n" + ] + } + ], + "source": [ + "# TODO: use input function to get user input for number of seconds\n", + "start = input(\"How many seconds?\")\n", + "\n", + "# TODO: copy start into another variable\n", + "remaining = int(start)\n", + "while remaining >= 1: # TODO: iterate from start to 1\n", + " print(remaining, \"seconds left\")\n", + " # TODO: update loop control variable's value to make progress towards terminating \n", + " # the loop, that is turning loop condition to False\n", + " remaining -= 1\n", + " # TODO: now run the cell to see the output. Didn't it go too fast?\n", + " # TODO: call time module sleep function, by passing 1 as argument\n", + " time.sleep(1)\n", + "\n", + "# TODO: print \"BEEP BEEP BEEP ...\" (10 BEEPS) without typing BEEP 10 times\n", + "# What string operator can you use here?\n", + "print(\"BEEP \" * 10)\n", + "\n", + "\n", + "# wake up call" + ] + }, + { + "cell_type": "markdown", + "id": "d54200ad", + "metadata": {}, + "source": [ + "## `for` loop\n", + "\n", + "- another kind of loop\n", + "- does not require initialization of loop control variable outside the loop\n", + "- loop statement itself creates the loop control variable\n", + "- keywords `for` and `in`\n", + "\n", + "### range built-in function\n", + "- accepts a single integer argument and produces a sequence of numbers from 0 to argument - 1, that is argument is exclusive\n", + "- accepts two integer arguments and produces a sequence of numbers from start (argument1) to end (argument2) - 1" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "43776615", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n", + "4\n" + ] + } + ], + "source": [ + "for i in range(5): # single arugment -> produces 0, 1, 2, 3, and 4\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "e3f01e6f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5\n", + "6\n", + "7\n", + "8\n", + "9\n" + ] + } + ], + "source": [ + "for i in range(5, 10): # two arguments -> produces 5, 6, 7, 8, and 9\n", + " print(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "b37a6842", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n", + "8\n" + ] + } + ], + "source": [ + "# TODO: write a for loop to iterate over the numbers 2 to 8\n", + "for var in range(2, 9):\n", + " print(var)" + ] + }, + { + "cell_type": "markdown", + "id": "558e4bed", + "metadata": {}, + "source": [ + "### Example 2: Print the square of all positive numbers <= 5\n", + "\n", + "First, we show the code for how to do this with a while loop. Then, we'll work together to do the same thing with a for loop." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "5ec1ba4f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 squared is:\n", + "1\n", + "2 squared is:\n", + "4\n", + "3 squared is:\n", + "9\n", + "4 squared is:\n", + "16\n", + "5 squared is:\n", + "25\n", + "all done!\n", + "x is 6\n" + ] + } + ], + "source": [ + "x = 1\n", + "while x <= 5:\n", + " print(str(x) + \" squared is:\")\n", + " print(str (x ** 2))\n", + " x += 1\n", + "print(\"all done!\")\n", + "print(\"x is \",str(x))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "1de3a188", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 squared is:\n", + "1\n", + "2 squared is:\n", + "4\n", + "3 squared is:\n", + "9\n", + "4 squared is:\n", + "16\n", + "5 squared is:\n", + "25\n", + "all done!\n" + ] + } + ], + "source": [ + "# TODO write a function using a for loop that prints the square of all positive numbers <= 5\n", + "# the output should be identical to the output of the cell above\n", + "\n", + "# x = 1 # we need to initialize x for a while loop, but a for loop automatically\n", + "# initializes x\n", + "\n", + "for x in range(1, 6):\n", + " print(str(x) + \" squared is:\")\n", + " print(str (x ** 2))\n", + "print(\"all done!\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "9df8c834", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "after for, x is 5\n" + ] + } + ], + "source": [ + "# TODO what value does x have after the for loop finishes? What about after the while loop finishes?\n", + "print(\"after for, x is \", str(x))" + ] + }, + { + "cell_type": "markdown", + "id": "cdc66ffa", + "metadata": {}, + "source": [ + "### Example 3: Find the max value of a function on an interval\n", + "\n", + "<div>\n", + "<img src=\"attachment:Curve_peak.png\" width=\"600\"/>\n", + "</div>" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "2ec27141", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n" + ] + } + ], + "source": [ + "def f(x):\n", + " return 5 - (x - 2) ** 2\n", + " \n", + "print(f(1))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0098b6aa", + "metadata": {}, + "outputs": [], + "source": [ + "# TODO: for what value of x will f(x) produce the maximum y value?\n", + "print(f(???))" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "27298992", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Best x: 1.9999999999999392\n", + "Best y: 5.0\n" + ] + } + ], + "source": [ + "# Goal: find the x that maximizes the y = f(x)\n", + "\n", + "# Let's try the values from -5 to 5\n", + "\n", + "# Goal: after the loop, best_x and best_y should contain just that\n", + "best_x = 0\n", + "best_y = -99999999\n", + "\n", + "# Try out increasing increments, make sure to comment the other increment\n", + "# delta_x = 1\n", + "# delta_x = 0.1\n", + "delta_x = 0.01\n", + "# delta_x = 0.001\n", + "\n", + "# this is fine, but only lets us check integers\n", + "# for x in range(-5, 6):\n", + "# fx = f(x)\n", + "# if fx > best_y:\n", + "# best_x = x\n", + "# best_y = fx\n", + "\n", + "x = -5 \n", + "while x <= 5:\n", + " fx = f(x)\n", + " if fx > best_y:\n", + " best_x = x\n", + " best_y = fx\n", + " x += delta_x\n", + "\n", + "print(\"Best x:\", best_x)\n", + "print(\"Best y:\", best_y)" + ] + }, + { + "cell_type": "markdown", + "id": "249f2aa7", + "metadata": {}, + "source": [ + "### Example 4: Integration (Riemann Sum)\n", + "\n", + "<div>\n", + "<img src=\"attachment:ReimannSum.png\" width=\"600\"/>\n", + "</div>" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "96b98336", + "metadata": {}, + "outputs": [], + "source": [ + "# Let's try the values from 1 to 5\n", + "start_x = 1\n", + "end_x = 5\n", + "total_area = 0\n", + "current_x = start_x\n", + "# Try out increasing values of width, make sure to comment the other width values\n", + "# delta_x = 1\n", + "delta_x = 0.1\n", + "# delta_x = 0.01\n", + "# delta_x = 0.001\n", + "\n", + "while current_x <= end_x:\n", + " y = ??? # TODO: use f(x) defined previously\n", + " rect_area = ???\n", + " total_area += ???\n", + " current_x += delta_x\n", + " \n", + "print(\"Area found using approximation is:\", total_area)" + ] + }, + { + "cell_type": "markdown", + "id": "3e8d609b", + "metadata": {}, + "source": [ + "### Example 5: Find primes" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "f2d0c381", + "metadata": {}, + "outputs": [], + "source": [ + "def is_prime(num):\n", + " \"\"\" returns True if x is prime, false otherwise. Assumes x is positive\"\"\"\n", + " \n", + " # try all divisors from 2 to sqrt(num) to check if num is prime\n", + " divisor = 2\n", + " while divisor <= math.sqrt(num):\n", + " # check if num is divisible by divisor\n", + " if num % divisor == 0:\n", + " return False\n", + " divisor += 1\n", + " \n", + " return True" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "e7aea11c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n", + "True\n", + "True\n", + "True\n", + "False\n", + "True\n", + "False\n" + ] + } + ], + "source": [ + "print(is_prime(1))\n", + "print(is_prime(2))\n", + "print(is_prime(3))\n", + "print(is_prime(7))\n", + "print(is_prime(16))\n", + "print(is_prime(23))\n", + "print(is_prime(1000000))" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "d26d790c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Prime numbers:\n", + "2 is prime\n", + "3 is prime\n", + "4 is not prime\n", + "5 is prime\n", + "6 is not prime\n", + "7 is prime\n", + "8 is not prime\n", + "9 is not prime\n", + "10 is not prime\n", + "11 is prime\n", + "12 is not prime\n", + "13 is prime\n", + "14 is not prime\n", + "15 is not prime\n", + "16 is not prime\n", + "17 is prime\n", + "18 is not prime\n", + "19 is prime\n", + "20 is not prime\n", + "21 is not prime\n", + "22 is not prime\n", + "23 is prime\n", + "24 is not prime\n", + "25 is not prime\n", + "26 is not prime\n", + "27 is not prime\n", + "28 is not prime\n", + "29 is prime\n", + "30 is not prime\n", + "31 is prime\n", + "32 is not prime\n", + "33 is not prime\n", + "34 is not prime\n", + "35 is not prime\n", + "36 is not prime\n", + "37 is prime\n", + "38 is not prime\n", + "39 is not prime\n", + "40 is not prime\n", + "41 is prime\n", + "42 is not prime\n", + "43 is prime\n", + "44 is not prime\n", + "45 is not prime\n", + "46 is not prime\n", + "47 is prime\n", + "48 is not prime\n", + "49 is not prime\n", + "50 is not prime\n" + ] + } + ], + "source": [ + "print(\"Prime numbers:\")\n", + "number = 2\n", + "# TODO: comment out this while loop and write equivalent for loop using range\n", + "# while number <= 50: \n", + "# if is_prime(number):\n", + "# print(number, \"is prime\")\n", + "# else:\n", + "# print(number, \"is not prime\")\n", + "# number += 1\n", + "\n", + "for number in range(2, 51):\n", + " if is_prime(number):\n", + " print(number, \"is prime\")\n", + " else:\n", + " print(number, \"is not prime\")" + ] + }, + { + "cell_type": "markdown", + "id": "0f29c848", + "metadata": {}, + "source": [ + "## `break` and `continue`\n", + "`break` and `continue` are python keywords that let us end loop execution early" + ] + }, + { + "cell_type": "markdown", + "id": "9dc76b8a", + "metadata": {}, + "source": [ + "### `break` example\n", + "- `break` enables to terminate execution of a while loop\n", + "- typically used with a conditional; that is you break when condition evaluates to `True`" + ] + }, + { + "cell_type": "markdown", + "id": "81abdb38", + "metadata": {}, + "source": [ + "def is_prime(num):\n", + " \"\"\" returns True if x is prime, false otherwise. \n", + " Assumes x is positive\"\"\"\n", + " \n", + " # try all divisors from 2 to sqrt(num) to check if num is prime\n", + " divisor = ???\n", + " while ???:\n", + " # check if num is divisible by divisor\n", + " if num % divisor == ???:\n", + " return ???\n", + " divisor ???\n", + " \n", + " return ???" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e432722e", + "metadata": {}, + "outputs": [], + "source": [ + "print(is_prime(1))\n", + "print(is_prime(2))\n", + "print(is_prime(3))\n", + "print(is_prime(7))\n", + "print(is_prime(16))\n", + "print(is_prime(23))\n", + "print(is_prime(1000000))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c69150ed", + "metadata": {}, + "outputs": [], + "source": [ + "def has_prime(start, end):\n", + " # TODO: write a for loop using range, to:\n", + " # 1. iterate over every number from start to end\n", + " # 2. call is_prime function, to determine if it is prime\n", + " # 3. if you find at least one prime, has_prime should\n", + " # return True, False otherwise\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd3e2027", + "metadata": {}, + "outputs": [], + "source": [ + "has_prime(14, 16)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0429022b", + "metadata": {}, + "outputs": [], + "source": [ + "has_prime(1000000, 1001000)" + ] + }, + { + "cell_type": "markdown", + "id": "32ba3308", + "metadata": {}, + "source": [ + "### `continue` example\n", + "- `continue` enables to move on to the next iteration of the while loop\n", + "- typically used with a conditional; that is you continue when condition evaluates to `True`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb569b21", + "metadata": {}, + "outputs": [], + "source": [ + "# TODO: write an infinite loop using while\n", + "\n", + " # TODO: get user input for age\n", + " \n", + " # Goal: to compute running average\n", + " # It is easy to keep track of total and number of user\n", + " # inputs to compute running average\n", + " \n", + " # TODO: discuss what is acceptable range for age\n", + " # What is the guinness world record for oldest person?\n", + " \n", + " # TODO: discuss where you will initialize variables to keep track\n", + " # of total and number of user inputs so far and then type the\n", + " # computation lines to compute updated total and running average\n", + " \n", + " # Now, try entering input as a large number outside of your\n", + " # acceptable age range. What happens to your average?\n", + " # TODO: handle this by writing a conditional and use continue,\n", + " # when user enters invalid age\n", + " \n", + " # Finally, how do we terminate the infinite while loop\n", + " # Let's accept \"q\" as user input for termination\n", + " # TODO: handle that using another conditional\n", + " # Think carefully about where this conditional needs to be in \n", + " # terms of control flow" + ] + }, + { + "cell_type": "markdown", + "id": "eb5bcba6", + "metadata": {}, + "source": [ + "## After lecture practice\n", + "\n", + "How many times is the while loop condition line executed?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f48b50f", + "metadata": {}, + "outputs": [], + "source": [ + "n = 7\n", + "while n >= 5:\n", + " print(n)\n", + " n -= 1\n", + " \n", + "# Answer is 4. \n", + "# Loop condition line always gets executed number of \n", + "# iterations + 1 times." + ] + }, + { + "cell_type": "markdown", + "id": "bb90cb11", + "metadata": {}, + "source": [ + "Refactor the below function." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "47a87068", + "metadata": {}, + "outputs": [], + "source": [ + "def is_between(a, b, c):\n", + " \"\"\"Return True if b is between a and c (exclusive), \n", + " False otherwise\"\"\"\n", + " if a < c:\n", + " if a < b and b < c:\n", + " return True\n", + " else:\n", + " return False\n", + " elif c <= a:\n", + " if c < b and b < a:\n", + " return True\n", + " else:\n", + " return False\n", + " else:\n", + " return False\n", + " \n", + "print(is_between(1, 3, 2)) # False\n", + "print(is_between(5, 11, 20)) # True\n", + "print(is_between(20, 3, 5)) # False\n", + "print(is_between(50, 11, 9)) # True\n", + "print(is_between(4, 4, 4)) # False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73f6ad82", + "metadata": {}, + "outputs": [], + "source": [ + "def is_between_v2(a, b, c):\n", + " return ???\n", + "\n", + "print(is_between_v2(1, 3, 2)) # False\n", + "print(is_between_v2(5, 11, 20)) # True\n", + "print(is_between_v2(20, 3, 5)) # False\n", + "print(is_between_v2(50, 11, 9)) # True\n", + "print(is_between_v2(4, 4, 4)) # False" + ] + }, + { + "cell_type": "markdown", + "id": "11a9f3ce", + "metadata": {}, + "source": [ + "Trace the output without using Python interpreter" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0cac75c", + "metadata": {}, + "outputs": [], + "source": [ + "x = 1\n", + "while x < 5:\n", + " y = 1\n", + " while y < 10:\n", + " print (x * y, \"\\t\", end=\"\")\n", + " y += 1\n", + " print()\n", + " x += 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb1dc7f0", + "metadata": {}, + "outputs": [], + "source": [ + "width = 9\n", + "height = 4\n", + "symbol = '#'\n", + "row = 0\n", + "while row < height:\n", + " col = 0\n", + " if row % 2 == 1:\n", + " print(\" \", end=\"\")\n", + " while col < width:\n", + " print(symbol + ' ', end=\"\")\n", + " col += 1\n", + " # displays just a newline\n", + " print() # recall default value for end parameter is \"\\n\"\n", + " row += 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d572d8b0", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}