{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "cf3408d1e3a45641f78d7858696864a8",
     "grade": false,
     "grade_id": "cell-d3917cf691ff056c",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# Python Basics - Variables and Functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "e17d31bcc816f46ee2121754064627e0",
     "grade": false,
     "grade_id": "cell-4367d53c03c57930",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# You must run this cell, but you can ignore its contents.\n",
    "\n",
    "import hashlib\n",
    "\n",
    "def ads_hash(ty):\n",
    "    \"\"\"Return a unique string for input\"\"\"\n",
    "    ty_str = str(ty).encode()\n",
    "    m = hashlib.sha256()\n",
    "    m.update(ty_str)\n",
    "    return m.hexdigest()[:10]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "52c8b1602d2996fad0fdad39dc324ae8",
     "grade": false,
     "grade_id": "cell-a396e1b67f65db5a",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Problem 1 - variable assignment\n",
    "\n",
    "Assign a value of 42 to the variable named `x`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "d33600594c70d12cb316c58380f0b8ed",
     "grade": false,
     "grade_id": "cell-ae28d599cff14ed6",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# YOUR CODE HERE\n",
    "raise NotImplementedError()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "25e2fa08766780c594f2fba09876024a",
     "grade": true,
     "grade_id": "cell-0e037ae0dbd9b1ad",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# This checks that the above worked\n",
    "assert ads_hash(x)=='73475cb40a'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "cb9fba32ae4ca338a285fb3649117521",
     "grade": false,
     "grade_id": "cell-c4b55ac9cdc77304",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Problem 2 - solving exceptions\n",
    "\n",
    "Modify the following so that it runs without an \"exception\" (an error in Python):\n",
    "\n",
    "\n",
    "```python\n",
    "y = 2 plus 2\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "7077eeea6fd5b76898892e27fb049ac2",
     "grade": false,
     "grade_id": "cell-c4b1b65a81fbe0ae",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# YOUR CODE HERE\n",
    "raise NotImplementedError()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "417459c798e32bb2c978ee95ba027cf5",
     "grade": true,
     "grade_id": "cell-f25ca0617c9fefdf",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# This checks that the above worked\n",
    "assert ads_hash(y)=='4b227777d4'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "f014700590c215a3ddf78e557914afca",
     "grade": false,
     "grade_id": "cell-d2ec8851f4e990e5",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Problem 3 - using the Python Tutor\n",
    "\n",
    "Run the following code at the [Python Tutor](http://pythontutor.com/).\n",
    "\n",
    "1. Click on \"Visualize your code and get live help now\" in the Python Tutor website.\n",
    "2. Copy this code into your clipboard:\n",
    "```python\n",
    "x = 42\n",
    "y = x + 42\n",
    "```\n",
    "3. Paste it into the edit window of the Python Tutor.\n",
    "4. Click the \"Visualize Execution\" button of the Python Tutor.\n",
    "5. Click the \"Next button\" until all steps are done.\n",
    "\n",
    "**For great insight, run all the problems in this exercise in the Python Tutor and carefully watch what is happening. This will be a massive help for you understand what your programs are doing**\n",
    "\n",
    "How many variables are in the global frame? Assign the answer to the variable named `answer`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "ff50dbf79b87fb3bdf4e72670e6fb7a6",
     "grade": false,
     "grade_id": "cell-c90583224070d298",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# YOUR CODE HERE\n",
    "raise NotImplementedError()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "de43ead478c6cead06e44632c52cf9e1",
     "grade": true,
     "grade_id": "cell-4a36c43c001f4d04",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# This checks that the above worked\n",
    "assert ads_hash(answer)=='d4735e3a26'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "bc190a7c395423c80634e904355187af",
     "grade": false,
     "grade_id": "cell-a8185ffe231c0ce4",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Problem 4 - functions\n",
    "\n",
    "Here is an example function named `double` that has one input named `x` and returns `x*2` (`x` times two).\n",
    "\n",
    "```python\n",
    "def double(x):\n",
    "    return x*2\n",
    "```\n",
    "\n",
    "Remember that all functions in python are defined with the `def` word, then the name of the function, then zero, one, two, or more arguments in parentheses, then a colon. The body of the function must be in a block - a group of lines with the same indentation.\n",
    "\n",
    "Now, make a function named `triple` that has one input named `x` and returns `x*3`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "60b9c24367737189ce8c2299aca2c1e6",
     "grade": false,
     "grade_id": "cell-69c4b1cf7dfd376f",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# YOUR CODE HERE\n",
    "raise NotImplementedError()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "8853c152f9aa1854369cec5bb45c5901",
     "grade": true,
     "grade_id": "cell-c2eb28444382a954",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# This checks that the above worked\n",
    "assert ads_hash(triple(3))=='19581e27de' \n",
    "assert ads_hash(triple(4))=='6b51d431df'\n",
    "assert ads_hash(triple(5))=='e629fa6598'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "af02828c7a0a1d4c68a2cfd266af5a66",
     "grade": false,
     "grade_id": "cell-5c7cd3a6ef33c261",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Problem 5 - functions with multiple arguments\n",
    "\n",
    "Here is an example function named `my_func` that takes two inputs, `x` and `y` and does a bit of math on the inputs:\n",
    "\n",
    "```python\n",
    "def my_func(x,y):\n",
    "    return x + 2*y\n",
    "```\n",
    "\n",
    "Make a function named `foo` which returns five times the first argument plus three times the second argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "df02e7e195e3beeb14dd0ac6b5743704",
     "grade": false,
     "grade_id": "cell-a7218905d3eb7d0d",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# YOUR CODE HERE\n",
    "raise NotImplementedError()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "5145a593d8183cf9a25132c733778575",
     "grade": true,
     "grade_id": "cell-a417fcd5f3319f27",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# This checks that the above worked\n",
    "assert ads_hash(foo(3,10))=='811786ad1a'\n",
    "assert ads_hash(foo(10,3))=='3e1e967e9b'\n",
    "assert ads_hash(foo(13,2302))=='5f7635b6a1'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "719f7021bb84ce24b25e4ef01dd7824e",
     "grade": false,
     "grade_id": "cell-8f0143cd8208922f",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Problem 6 - calling functions from functions\n",
    "\n",
    "We can call functions from within functions.\n",
    "\n",
    "Here are two example functions named `double` and `double_twice`\n",
    "\n",
    "```python\n",
    "def double(x):\n",
    "    return x*2\n",
    "\n",
    "def double_twice(x):\n",
    "    y = double(x)\n",
    "    z = double(y)\n",
    "    return z\n",
    "```\n",
    "\n",
    "Re-use your function `triple` from above and make a function named `triple_thrice` which calls `triple` three times repeatedly on its input value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "62c5724a2440f89dfb9624ab5ce8703e",
     "grade": false,
     "grade_id": "cell-aa0cfdb16d440f6b",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# YOUR CODE HERE\n",
    "raise NotImplementedError()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "38e9e8e38f32f83d67593876817efb0f",
     "grade": true,
     "grade_id": "cell-ee28ca6d0fc146ee",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "assert ads_hash(triple_thrice(3))=='5316ca1c5d'\n",
    "assert ads_hash(triple_thrice(4))=='9537f32ec7'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "bb89f7b73ee210cd1f35300adf30f4e2",
     "grade": false,
     "grade_id": "cell-66fac9b6dafd5cd6",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Problem 7 - variable scopes\n",
    "\n",
    "Functions are also useful because they let you \"hide\" variables so they do not \"pollute\" other parts of your code. In other words, functions let you make modular pieces of code which do not affect each other.\n",
    "\n",
    "Consider this piece of code, and think about the value of `x` throughout the code.\n",
    "\n",
    "```python\n",
    "x = 43\n",
    "\n",
    "def blah(x):\n",
    "    x = x - 26\n",
    "    return x\n",
    "\n",
    "blah(2)\n",
    "\n",
    "x\n",
    "```\n",
    "\n",
    "In the very last line, what is the value of `x`?\n",
    "\n",
    "In the very last line, `x` has a value of `43`. However, inside the function there is a *local* variable, also named `x`, which can have a different value. Changes to this local variable `x` in the function do not affect the `x` in the *global frame*. (This could also be called the *global scope*. \"Frame\" and \"scope\" are synonyms.)\n",
    "\n",
    "Inside a function, variable from the outside frame can be *read* if there is no local variable in the function with the same name. Consider this code. Here we will read the variable `x` inside the function because we have no argument or other local variable named `x`.\n",
    "\n",
    "```python\n",
    "x = 43\n",
    "\n",
    "def blah(y):\n",
    "    z = x - y\n",
    "    return z\n",
    "\n",
    "q = blah(2)\n",
    "```\n",
    "\n",
    "What is the value of `q`?\n",
    "\n",
    "The value of `q` here will be 41.\n",
    "\n",
    "*Advanced*: Frames can be nested - for example if you call a function named `function2` from another function named `function1`, the frame of `function2` will be created while the frame of `function1` continues to exist.\n",
    "\n",
    "In this second example, `y` is defined only inside the function. What is it's value in the function? Assign your answer to the variable `y`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "aea2a9a276437e340a4e8af8453970b8",
     "grade": false,
     "grade_id": "cell-cdc1a3f2940f028c",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# YOUR CODE HERE\n",
    "raise NotImplementedError()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "20fab6e2c79881c84c4178dc942a9952",
     "grade": true,
     "grade_id": "cell-93d460ecce09dcfd",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "assert ads_hash(y)=='d4735e3a26'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "b1e7c21f388151f457c9477ed79325ab",
     "grade": false,
     "grade_id": "cell-56a56e248a2320f1",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Problem 8 - return values of functions\n",
    "\n",
    "To return a value, a function must use the keyword `return`. Otherwise, the special python type `None` is returned. Check these two functions out:\n",
    "\n",
    "```python\n",
    "def func_one(x):\n",
    "    return x*10\n",
    "\n",
    "def func_two(x):\n",
    "    x*10\n",
    "```\n",
    "\n",
    "What is the result of `func_one(10)`? It is `100`. What is the result of `func_two(10)`? It is `None`, a special type in Python which means \"nothing\".\n",
    "\n",
    "Taking this as a starting point, fix the `my_triple` function so that it returns the value of `x*3`.\n",
    "\n",
    "```\n",
    "def my_triple(x):\n",
    "    x*3\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "8d35a4922df3598cb1e8da453a64cd51",
     "grade": false,
     "grade_id": "cell-3d76a38f83df69ce",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# YOUR CODE HERE\n",
    "raise NotImplementedError()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "1f975aebc553039503e03b7480621d48",
     "grade": true,
     "grade_id": "cell-f70296c24b543ae5",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "assert ads_hash(my_triple(100))=='983bd614bb'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "markdown",
     "checksum": "184af9b260021fe31f91b6eb4893ec11",
     "grade": false,
     "grade_id": "cell-0748880c1c3a5b6f",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Problem 9 - `print()` is not return\n",
    "\n",
    "One thing that can be confusing is the difference between the return value of a cell in Jupyter notebook - which gets displayed automatically and the use of the built-in `print()` function.\n",
    "\n",
    "```python\n",
    "print(1234)\n",
    "```\n",
    "\n",
    "Will print `1234` but has no return value. This can be tricky in functions.\n",
    "\n",
    "Consider this function\n",
    "\n",
    "```python\n",
    "def my_great_function(a):\n",
    "    print(a*30)\n",
    "```\n",
    "\n",
    "What does this function return?\n",
    "\n",
    "It returns `None`.\n",
    "\n",
    "Now make a function called `my_even_better_function` which returns the value of its input times thirty."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "3be3337b633051d62badc2ed20bec9ff",
     "grade": false,
     "grade_id": "cell-25d97b85b08d5a2c",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# YOUR CODE HERE\n",
    "raise NotImplementedError()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "deletable": false,
    "editable": false,
    "nbgrader": {
     "cell_type": "code",
     "checksum": "ce83ca5daaf52deb49f7124b31ceafe2",
     "grade": true,
     "grade_id": "cell-b2fc619e60513768",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "assert ads_hash(my_even_better_function(32))=='7f5642cd0c'"
   ]
  }
 ],
 "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.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
