{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Iteration" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" }, "tags": [ "remove-cell" ] }, "source": [ "**CS1302 Introduction to Computer Programming**\n", "___" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2020-11-27T11:20:04.656873Z", "start_time": "2020-11-27T11:20:04.651575Z" }, "slideshow": { "slide_type": "fragment" }, "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "%reload_ext mytutor\n", "from ipywidgets import interact" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Motivation" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Many tasks are repetitive:\n", "- To print from 1 up to a user-specified number *arbitrarily large*.\n", "- To compute the maximum of a sequence of numbers *arbitrarily long*.\n", "- To get user input *repeatedly until* it is within a certain range." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**How to write code to perform repetitive tasks?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "E.g., can you complete the following code to print from 1 up to a user-specified number?" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:15:26.295495Z", "start_time": "2020-09-12T02:15:25.202198Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 400\n", "num = int(input(\">\"))\n", "if 1 <= num:\n", " print(1)\n", "if 2 <= num:\n", " print(2)\n", "if 3 <= num:\n", " print(3)\n", "# YOUR CODE HERE" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "*Code duplication* is not good because: \n", "- Duplicate code is hard to read/write/maintain. \n", " (Imagine what you need to do to change some code.)\n", "- The number of repetitions may not be known before runtime." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Instead, programmers write a *loop* which specifies a piece of code to be executed iteratively." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## For Loop" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Iterate over a sequence" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**How to print from 1 up to 4?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "We can use a [`for` statement](https://docs.python.org/3.3/tutorial/controlflow.html#for-statements) as follows:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2020-09-21T14:40:09.733612Z", "start_time": "2020-09-21T14:40:09.713133Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "for i in 1, 2, 3, 4:\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- `i` is automatically assigned to each element in the sequence `1, 2, 3, 4` one-by-one from left to right.\n", "- After each assignment, the body `print(i)` is executed. \n", "\n", "N.b., if `i` is defined before the for loop, its value will be overwritten. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "The assignment is not restricted to integers and can also be a tuple assignment. The expression list can also be an [iterable object](https://docs.python.org/3.3/glossary.html#term-iterable) instead." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2020-09-21T14:41:01.344433Z", "start_time": "2020-09-21T14:41:01.333522Z" }, "scrolled": true, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 l\n", "1 o\n", "2 o\n", "3 p\n" ] } ], "source": [ "tuples = (0, \"l\"), (1, \"o\"), (2, \"o\"), (3, \"p\")\n", "for i, c in tuples:\n", " print(i, c)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "An even shorter code..." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2020-09-21T14:41:08.799668Z", "start_time": "2020-09-21T14:41:08.790110Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 l\n", "1 o\n", "2 o\n", "3 p\n" ] } ], "source": [ "for i, c in enumerate(\"loop\"):\n", " print(i, c)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Iterate over a range" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**How to print up to a user-specified number?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "We can use [`range`](https://docs.python.org/3/library/stdtypes.html#range):" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:15:06.124643Z", "start_time": "2020-09-12T02:15:03.879119Z" }, "slideshow": { "slide_type": "-" }, "tags": [ "remove-output" ] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "stop = int(input(\">\")) + 1\n", "for i in range(stop):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Why add 1 to the user input number?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "`range(stop)` generates a sequence of integers from `0` up to *but excluding* `stop`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**How to start from a number different from `0`?**" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:16:04.698262Z", "start_time": "2020-09-12T02:16:04.691449Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "for i in range(1, 5):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**What about a step size different from `1`?**" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:16:11.858443Z", "start_time": "2020-09-12T02:16:11.852378Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "2\n", "4\n" ] } ], "source": [ "for i in range(0, 5, 2): print(i) # starting number must also be specified. Why?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** How to count down from 4 to 0? Try doing it without addition or subtraction." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:16:21.291051Z", "start_time": "2020-09-12T02:16:21.284902Z" }, "nbgrader": { "grade": false, "grade_id": "count-down", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4\n", "3\n", "2\n", "1\n", "0\n" ] } ], "source": [ "### BEGIN SOLUTION\n", "for i in range(4, -1, -1):\n", " print(i)\n", "### END SOLUTION" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Print from `0` to a user-specified number but in steps of `0.5`. \n", "E.g., if the user inputs `2`, the program should print:\n", "```\n", "0.0\n", "0.5\n", "1.0\n", "1.5\n", "2.0\n", "```\n", "\n", "*Note:* `range` only accepts integer arguments." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:16:56.696693Z", "start_time": "2020-09-12T02:16:53.508468Z" }, "nbgrader": { "grade": false, "grade_id": "fractional-step", "locked": false, "schema_version": 3, "solution": true, "task": false }, "scrolled": true, "slideshow": { "slide_type": "-" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "num = int(input(\">\"))\n", "### BEGIN SOLUTION\n", "for i in range(0, 2 * num + 1, 1):\n", " print(i / 2)\n", "### END SOLUTION" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "**Exercise** How to print the character `'*'` repeatedly for `m` rows and `n` columns? \n", "Try using a *nested for loop*: Write a for loop (*inner loop*) inside the body of another for loop (*outer loop*)." ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:17:26.930731Z", "start_time": "2020-09-12T02:17:26.882085Z" }, "nbgrader": { "grade": false, "grade_id": "nested-loop", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "1de9ee5aa05d4684903224749dd4bab3", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(IntSlider(value=5, description='m', max=10), IntSlider(value=5, description='n', max=10)…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@interact(m=(0, 10), n=(0, 10))\n", "def draw_rectangle(m=5, n=5):\n", " ### BEGIN SOLUTION\n", " for i in range(m):\n", " for j in range(n):\n", " print(\"*\", end=\"\")\n", " print()\n", " ### END SOLUTION" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Iterate over a string" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**What does the following do?**" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2020-09-21T14:44:52.568078Z", "start_time": "2020-09-21T14:44:52.560424Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "for character in \"loop\":\n", " print(character)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "`str` is a [sequence type](https://docs.python.org/3/library/stdtypes.html#textseq) because a string is regarded as a sequence of characters.\n", "- The function [`len`](https://docs.python.org/3/library/functions.html#len) can return the length of a string.\n", "- The indexing operator `[]` can return the character of a string at a specified location." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:19:37.057820Z", "start_time": "2020-09-12T02:19:37.050524Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "length: 4\n", "characters: l o o p\n" ] } ], "source": [ "message = \"loop\"\n", "print(\"length:\", len(message))\n", "print(\"characters:\", message[0], message[1], message[2], message[3])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "We can also iterate over a string as follows although it is less elegant:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:20:05.326619Z", "start_time": "2020-09-12T02:20:05.320063Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "l\n", "o\n", "o\n", "p\n" ] } ], "source": [ "for i in range(len(\"loop\")):\n", " print(\"loop\"[i])" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Print a string assigned to `message` in reverse. \n", "E.g., `'loop'` should be printed as `'pool'`. Try using the for loop and indexing operator." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:20:21.886787Z", "start_time": "2020-09-12T02:20:21.855189Z" }, "nbgrader": { "grade": false, "grade_id": "reverse-string", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "3e1ef37940a5449b8d0efe0548e1221e", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(Text(value='loop', description='message'), Output()), _dom_classes=('widget-interact',))" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@interact(message=\"loop\")\n", "def reverse_print(message):\n", " ### BEGIN SOLUTION\n", " for i in range(len(message)):\n", " print(message[-i - 1], end=\"\")\n", " print('') # in case message is empty\n", " ### END SOLUTION" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## While Loop" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**How to ensure user input is non-empty?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Python provides the [`while` statement](https://docs.python.org/3/reference/compound_stmts.html#while) to loop until a specified condition is false." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:21:16.272650Z", "start_time": "2020-09-12T02:21:10.921514Z" }, "slideshow": { "slide_type": "-" }, "tags": [ "remove-output" ] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "while not input(\"Input something please:\"):\n", " pass" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "As long as the condition after `while` is true, the body gets executed repeatedly. In the above example,\n", "- if user inputs nothing, \n", "- `input` returns an empty string `''`, which is [regarded as `False`](https://docs.python.org/3/reference/expressions.html#booleans), and so\n", "- the looping condition `not input('...')` is `True`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Is it possible to use a for loop instead of a while loop?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- Not without hacks because the for loop is a *definite loop* which has a definite number of iterations before the execution of the loop.\n", "- `while` statement is useful for an *indefinite loop* where the number of iterations is unknown before the execution of the loop." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "It is possible, however, to replace a for loop by a while loop. \n", "E.g., the following code prints from `0` to `4` using a while loop instead of a for loop." ] }, { "cell_type": "code", "execution_count": 72, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:23:02.642597Z", "start_time": "2020-09-12T02:23:02.636660Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "i = 0\n", "while i <= 4:\n", " print(i)\n", " i += 1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- A while loop may not be as elegant, c.f., \n", " ```Python\n", " for i in range(5): print(i)\n", " ```\n", "- but it can be as efficient." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Should we just use while loop?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Consider using the following while loop to print from `0` to a user-specified value." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:28:59.075109Z", "start_time": "2020-09-12T02:28:51.272451Z" }, "scrolled": true, "slideshow": { "slide_type": "-" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 310\n", "num = int(input(\">\"))\n", "i = 0\n", "while i != num + 1:\n", " print(i)\n", " i += 1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Exercise** Is the above while loop doing the same thing as the for loop below?" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:24:58.735012Z", "start_time": "2020-09-12T02:24:55.351536Z" }, "slideshow": { "slide_type": "-" }, "tags": [] }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "for i in range(int(input(\">\")) + 1):\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": { "nbgrader": { "grade": true, "grade_id": "infinite-loop", "locked": false, "points": 0, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "source": [ "When the input corresponds to an integer $\\leq -2$,\n", "- the while loop becomes an infinite loop, but\n", "- the for loop terminates without printing any number." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "We have to be careful not to create unintended *infinite loops*. \n", "The computer can't always detect whether there is an infinite loop. ([Why not?](https://en.wikipedia.org/wiki/Halting_problem))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Break/Continue/Else Constructs of a Loop" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Breaking out of a loop" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Is the following an infinite loop?**" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:31:40.571589Z", "start_time": "2020-09-12T02:31:34.464485Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 310\n", "while True:\n", " message = input(\"Input something please:\")\n", " if message:\n", " break\n", "print(\"You entered:\", message)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The loop is terminated by the [`break` statement](https://docs.python.org/3/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops) when user input is non-empty." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Why is the `break` statement useful?**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ " Recall the earlier `while` loop:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:32:29.802277Z", "start_time": "2020-09-12T02:32:24.259120Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 300\n", "while not input(\"Input something please:\"):\n", " pass" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This while loop is not useful because it does not store the user input." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Is the `break` statement strictly necessary?** " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- We can use the assignment expression but it is not supported by Python version <3.8." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- We can avoid `break` statement by using *flags*, which are boolean variables for flow control:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:33:25.270345Z", "start_time": "2020-09-12T02:33:20.380440Z" }, "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 350\n", "has_no_input = True\n", "while has_no_input:\n", " message = input(\"Input something please:\")\n", " if message:\n", " has_no_input = False\n", "print(\"You entered:\", message)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Using flags makes the program more readable, and we can use multiple flags for more complicated behavior. \n", "The variable names for flags are often `is_...`, `has_...`, etc." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Continue to Next Iteration" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**What does the following program do? \n", "Is it an infinite loop?**" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:37:31.562800Z", "start_time": "2020-09-12T02:35:51.649703Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 310\n", "while True:\n", " message = input(\"Input something please:\")\n", " if not message:\n", " continue\n", " print(\"You entered:\", message)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- The program repeatedly asks the user for input.\n", "- If the input is empty, the `continue` statement will skip to the next iteration.\n", "- The loop can only be terminated by interrupting the kernel.\n", "- Such an infinite loop can be useful. E.g., your computer clock continuously updates the current time." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Exercise** Is the `continue` statement strictly necessary? Can you rewrite the above program without the `continue` statement? " ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "ExecuteTime": { "end_time": "2020-09-12T02:37:39.345421Z", "start_time": "2020-09-12T02:37:32.939865Z" }, "nbgrader": { "grade": false, "grade_id": "avoid-continue", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 350\n", "while True:\n", " message = input(\"Input something please:\")\n", " ### BEGIN SOLUTION\n", " if message:\n", " print(\"You entered:\", message)\n", " ### END SOLUTION" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Else construct for a loop" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "The following program checks whether a number is composite, namely, \n", "- a positive integer that is\n", "- a product of two strictly smaller positive integers." ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "ExecuteTime": { "end_time": "2020-09-21T14:53:16.423937Z", "start_time": "2020-09-21T14:53:16.388975Z" }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "81f8ceaaf51d4066ac48235c5f654406", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(Text(value='1', description='num'), Output()), _dom_classes=('widget-interact',))" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@interact(num=\"1\")\n", "def check_composite(num):\n", " if num.isdigit():\n", " num = int(num)\n", " for divisor in range(2, num): # why starts from 2 instead of 1\n", " if num % divisor:\n", " continue # where will this go?\n", " else:\n", " print(\"It is composite.\")\n", " break # where will this go?\n", " else:\n", " print(\"It is not composite.\") # how to get here?\n", " else:\n", " print(\"Not a positive integer.\") # how to get here?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "**Exercise** There are three else claues in the earlier code. Which one is for the loop?" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "- The second else clause that `print('It is not composite.')`.\n", "- The clause is called when there is no divisor found in the range from `2` to `num`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "If program flow is confusing, try stepping through executation:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%mytutor -h 520\n", "def check_composite(num):\n", " if num.isdigit():\n", " num = int(num)\n", " for divisor in range(2, num):\n", " if num % divisor:\n", " continue\n", " else:\n", " print(\"It is composite.\")\n", " break\n", " else:\n", " print(\"It is not composite.\")\n", " else:\n", " print(\"Not a positive integer.\")\n", "\n", "\n", "check_composite(\"1\")\n", "check_composite(\"2\")\n", "check_composite(\"3\")\n", "check_composite(\"4\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "- In addition to using `continue` and `break` in an elegant way, \n", "- the code also uses an else clause that is executed only when the loop terminates *normally* not by `break`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Convert the for loop to a while loop. Try to make the code as efficient as possible with less computation and storage." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "ExecuteTime": { "end_time": "2020-09-27T08:55:33.231171Z", "start_time": "2020-09-27T08:55:33.193049Z" }, "nbgrader": { "grade": false, "grade_id": "for-to-while", "locked": false, "schema_version": 3, "solution": true, "task": false }, "slideshow": { "slide_type": "-" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e01bb8e34c784f38a32115455b1c883e", "version_major": 2, "version_minor": 0 }, "text/plain": [ "interactive(children=(Text(value='1', description='num'), Output()), _dom_classes=('widget-interact',))" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@interact(num=\"1\")\n", "def check_composite(num):\n", " if num.isdigit():\n", " num = int(num)\n", " ### BEGIN SOLUTION\n", " # for divisor in range(2,num):\n", " divisor = int(num ** 0.5) # biggest possible divisor\n", " while divisor > 1:\n", " if num % divisor:\n", " divisor -= 1 # why not go from 2 to int(num ** 0.5)?\n", " else:\n", " print(\"It is composite.\")\n", " break\n", " else:\n", " print(\"It is not composite.\")\n", " ### END SOLUTION\n", " else:\n", " print(\"Not a positive integer.\")" ] } ], "metadata": { "celltoolbar": "Slideshow", "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.8.8" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "rise": { "enable_chalkboard": true, "scroll": true, "theme": "white" }, "toc": { "base_numbering": 1, "nav_menu": { "height": "195px", "width": "330px" }, "number_sections": true, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "454.418px", "left": "1533px", "top": "110.284px", "width": "435.327px" }, "toc_section_display": true, "toc_window_display": false }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }