├── .gitignore ├── 01-lesson_notebooks ├── 00a-Mac_Setup.ipynb ├── 00b-Windows_Setup.ipynb ├── 00c-Get_The_Materials.ipynb ├── 01a-Some_Context.ipynb ├── 01b-How_to_Use_the_Class_Materials.ipynb ├── 02a-Print_Statements_and_Types.ipynb ├── 02b-Variables_and_Assignment.ipynb ├── 02c-Comments_Arithmetic_and_String_Concatenation.ipynb ├── 02d-Input_and_Casting.ipynb ├── 02e-Example_Error_Messages.ipynb ├── 02f-Problem_Solving.ipynb ├── 02g-Exercise_Solutions.ipynb ├── 03a-Comparison_Operators_And_Logical_Operators.ipynb ├── 03b-Conditional_Execution.ipynb ├── 03c-Iteration_(looping).ipynb ├── 03d-Code_Tracing.ipynb ├── 03e-Exercise_Solutions.ipynb ├── 04a-Functions.ipynb ├── 04b-Exercise_Solutions.ipynb ├── 05a-Recursion.ipynb ├── 05b-Classes_and_Objects.ipynb ├── 05c-Exercise_Solutions.ipynb ├── 06a-String_Manipulation.ipynb ├── 06b-Lists.ipynb ├── 06c-Exercise_Solutions.ipynb ├── 07a-Tuples_and_Mutability_vs_Immutability.ipynb ├── 07b-Object_References_and_Identity.ipynb ├── 07c-Exercise_Solutions.ipynb ├── 08a-Dictionaries.ipynb ├── 08b-Sets.ipynb └── 08c-Exercise_Solutions.ipynb ├── 02-IDE_exercises ├── 01-project │ └── README.md ├── 02a-project │ └── README.md ├── 02b-project │ └── README.md ├── 02c-project │ └── README.md ├── 03a-project │ └── README.md ├── 03b-project │ └── README.md ├── 03c-project │ └── README.md ├── 04a-project │ └── README.md ├── 04b-project │ └── README.md ├── 04c-project │ └── README.md ├── 05a-project │ └── README.md ├── 05b-project │ └── README.md ├── 06a-project │ └── README.md ├── 06b-project │ └── README.md ├── 06c-project │ └── README.md ├── 07a-project │ └── README.md ├── 07b-project │ └── README.md ├── 08a-project │ └── README.md ├── 08b-project │ └── README.md ├── 08c-project │ └── README.md ├── 09-project │ ├── README.md │ └── test_AddThreeGame.py ├── 10-project │ ├── README.md │ └── test_BuildersGame.py └── solutions │ ├── 01-project │ └── my_color.py │ ├── 02a-project │ └── calculate_average.py │ ├── 02b-project │ └── temp_conversion.py │ ├── 02c-project │ └── coin_change.py │ ├── 03a-project │ └── min_max_number.py │ ├── 03b-project │ └── find_factors.py │ ├── 03c-project │ └── guess_num.py │ ├── 04a-project │ └── distance_fallen.py │ ├── 04b-project │ └── fibonacci.py │ ├── 04c-project │ └── hailstone_step.py │ ├── 05a-project │ └── multiply_recur.py │ ├── 05b-project │ └── Taxicab.py │ ├── 06a-project │ └── find_median.py │ ├── 06b-project │ └── add_surname.py │ ├── 06c-project │ └── std_dev.py │ ├── 07a-project │ └── square_list.py │ ├── 07b-project │ └── reverse_list.py │ ├── 08a-project │ └── count_letters.py │ ├── 08b-project │ └── words_in_both.py │ ├── 08c-project │ └── make_employee_dict.py │ ├── 09-project │ └── AddThreeGame.py │ └── 10-project │ └── BuildersGame.py ├── 03-additional_material ├── 00a-Tools_You_Will_Need.ipynb ├── 01b-Git_Terminology_Commands_And_Workflow.ipynb ├── 01b-The_Terminal.ipynb ├── 01b-Updating_Forked_Projects.ipynb ├── 06b-Lists.ipynb ├── 07a-Tuples_and_Mutability_vs_Immutability.ipynb ├── 08a-Dictionaries.ipynb └── 08b-Sets.ipynb ├── README.md ├── install_dependencies.sh └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # personal directories 2 | lecture_slides 3 | pictures 4 | old_lessons 5 | Getting Started.docx 6 | 7 | # settings and other directoreis 8 | __pycache__/ 9 | .ipynb_checkpoints/ 10 | .idea/ 11 | .vscode/ 12 | .python-version 13 | 14 | # virtual environments 15 | .env/ 16 | env/ 17 | .venv/ 18 | venv/ 19 | -------------------------------------------------------------------------------- /01-lesson_notebooks/00a-Mac_Setup.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Mac setup\n", 9 | "## Tools you will need\n", 10 | "We're also recommending tools and steps that will give a good baseline to grow as a developer. You will need the following tools and application for this course:\n", 11 | "- [Homebrew](https://brew.sh/) is a package manager for macOS that allows you to easily install and manage software packages from the command line. It provides a convenient way to install and update common development tools, programming languages, and other utilities.\n", 12 | "- [pyenv](https://github.com/pyenv/pyenv) is a simple Python version manager that allows you to easily switch between multiple versions of Python on your local machine. It provides a way to install and manage different versions of Python, as well as the ability to create virtual environments for specific projects.\n", 13 | "- [Visual Studio Code](https://code.visualstudio.com/) (often referred to as VS Code) is a free and open-source cross-platform code editor developed by Microsoft. It provides a rich set of features for editing, debugging, and working with code, including support for multiple programming languages, code completion, and Git integration. It is also highly customizable through extensions and themes.\\*\n", 14 | "- [Jupyter Notebook](https://jupyter.org/install) is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations, and narrative text. It is often used for data analysis, scientific computing, and machine learning.\n", 15 | "- [Git](https://git-scm.com/) is a free and open-source distributed version control system that allows you to track changes to your code over time. It is widely used in software development to collaborate on projects and manage code changes.\n", 16 | "- [Github](https://github.com/) is a web-based platform that provides hosting for software development and version control using Git. It allows developers to collaborate on projects, track issues and bugs, and contribute to open-source projects. It is also a popular platform for hosting documentation and project websites.\n", 17 | "\n", 18 | "\\*If you want to **fight the power**, you can download [VS Codium]((https://vscodium.com/)), essentially open source VS Code without the Microsoft.\n", 19 | "\n", 20 | "## Installing\n", 21 | "We can get all of these tools via the Mac's [terminal](https://support.apple.com/guide/terminal/welcome/mac). We describe terminals and command line interfaces in the notebook [01a-Some_Context](../01-lesson_notebooks/01a-Some_Context.ipynb) and give even more detail in the 03-additional_material section [01b-The_Terminal](../03-additional_material/01b-The_Terminal.ipynb). \n", 22 | "\n", 23 | "You can find your terminal with the \"Spotlight Search\". You can pull it up easily by clicking the `` + `` keys together and typing \"terminal\" and select.\n", 24 | "\n", 25 | "### Download and install Homebrew\n", 26 | "Make sure you have administrative privileges and then copy the installation command from [Homebrew](https://brew.sh/) into your terminal and hit enter to run:\n", 27 | "```bash\n", 28 | "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n", 29 | "```\n", 30 | "\n", 31 | "### Add `brew` to your PATH\n", 32 | "The PATH is used to help your computer know where to look for the software programs that you want to use.\n", 33 | "\n", 34 | "After `brew` is finished installing you'll probably receive a prompt that is roughly like the following:\n", 35 | "```bash\n", 36 | "==> Next steps:\n", 37 | "- Add Homebrew to your PATH in /Users/ralphjsmit/.zprofile:\n", 38 | " echo 'eval \"$(/opt/homebrew/bin/brew shellenv)\"' >> /Users//.zprofile\n", 39 | " eval \"$(/opt/homebrew/bin/brew shellenv)\"\n", 40 | "```\n", 41 | "\n", 42 | "You can open a new terminal with `` + `` keys. Go ahead and close out of your old one. Check that brew downloaded successfully by calling the command `brew update` in your terminal.\n", 43 | "\n", 44 | "### Download and install `pyenv`\n", 45 | "You can find [pyenv](https://github.com/pyenv/pyenv)'s installation instructions on their GitHub repository.\n", 46 | "\n", 47 | "Following their installation instructions via `brew` we an perform the following commands:\n", 48 | "```bash\n", 49 | "brew update\n", 50 | "brew install pyenv\n", 51 | "```\n", 52 | "### Add `pyenv` to your PATH and shell environment\n", 53 | "We're assuming you're using the [`zsh`](https://linux.die.net/man/1/zsh#:~:text=Zsh%20is%20a%20UNIX%20command,ksh%20but%20includes%20many%20enhancements.) shell (default on Macs). Therefore, you'd run:\n", 54 | "```bash\n", 55 | "echo 'export PYENV_ROOT=\"$HOME/.pyenv\"' >> ~/.zshrc\n", 56 | "echo 'command -v pyenv >/dev/null || export PATH=\"$PYENV_ROOT/bin:$PATH\"' >> ~/.zshrc\n", 57 | "echo 'eval \"$(pyenv init -)\"' >> ~/.zshrc\n", 58 | "```\n", 59 | "\n", 60 | "We can refresh our shell with the command `source ~/.zshrc`.\n", 61 | "\n", 62 | "We can confirm the `pyenv` commands work by running `pyenv version`. There shouldn't be anything, but if the command is recognized, we should be good.\n", 63 | "\n", 64 | "### Install Python with `pyenv`\n", 65 | "Depending on which version of the Mac you're running you probably already have Python 2 or Python 3 installed. You can confirm by running the command `python --version` and/or `python3 --version`.\n", 66 | "\n", 67 | "However, we want more control over which python versions we have, and at some point in our journey as developers, an easy way to switch between different versions of Python to work with the latest and greatest or the legacy versions that the applications we end up working on require.\n", 68 | "\n", 69 | "At the time this is written, Python version `3.11.1` is the latest version.\n", 70 | "\n", 71 | "Let's install it in our terminal with the command:\n", 72 | "```bash\n", 73 | "pyenv install 3.11.1\n", 74 | "```\n", 75 | "\n", 76 | "Let's set this as our \"global\" version with the command:\n", 77 | "```bash\n", 78 | "pyenv global 3.11.1\n", 79 | "```\n", 80 | "Now we can refresh our shell again with the command `source ~/.zshrc`. If we call `python --version` we should see `3.11.1` being called from the `.pyenv` directory.\n", 81 | "\n", 82 | "Let's also check that `pip`, the default package installer for Python that allows you to easily install and manage Python packages and dependencies is linked correction by running the command `which pip` in our terminal. It should match the same directory when we run the command `which python`.\n", 83 | "\n", 84 | "This setup is good enough for our purposes, but if you're interested in understanding `pyenv` broader use case [*Real Python*](https://realpython.com/intro-to-pyenv/) has a pretty good rundown.\n", 85 | "\n", 86 | "### Download and install `jupyter`\n", 87 | "To access and interact the workbook materials for this course, we'll need a Python package [Jupyter Notebook](https://jupyter.org/install). Python has a convenient way to pull its own packages with `pip`. Let's install it in our global site-packages for Python 3.11.1 (which we should have set previously).\n", 88 | "\n", 89 | "It's as simple as running the command:\n", 90 | "```bash\n", 91 | "pip install notebook\n", 92 | "```\n", 93 | "\n", 94 | "Check that you have it by running `jupyter --version`. We'll go over how to use this application in future workbooks. It's enough that we have it successfully downloaded.\n", 95 | "\n", 96 | "### Download and install VS Code\n", 97 | "Since we're pros at installing with `brew` we can do it again.\n", 98 | "\n", 99 | "Let's follow [HomeBrew's documentation](https://formulae.brew.sh/cask/visual-studio-code) and run the command:\n", 100 | "```bash\n", 101 | "brew install --cask visual-studio-code\n", 102 | "```\n", 103 | "\n", 104 | "Once it's done installing, you should be able to search for it in your applications. We can also verify that VS Code commands have been properly applied to our PATH. Try running `code --version`.\n", 105 | "\n", 106 | "You can also try the command `code .` (`.` is short hand for our current directory) to see all of our files and folders inside VS Code. We'll go over how to use this when we download our materials in an upcoming notebook\n", 107 | "\n", 108 | "### Check that you have git installed\n", 109 | "Git is a free and open-source distributed version control system that allows you to track changes to your code over time and collaborate with others on projects. You should already have it on your system. Confirm by typing the command below in your terminal:\n", 110 | "```bash\n", 111 | "git --version\n", 112 | "```\n", 113 | "If you don't have it, consult the official [Git documentation](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).\n", 114 | "\n", 115 | "### Create a Github account\n", 116 | "All of these materials are available at https://github.com/branhoff/python_class_101. Create a [Github](https://github.com/) account. We'll explain how to download the materials in a future workbook." 117 | ] 118 | } 119 | ], 120 | "metadata": { 121 | "kernelspec": { 122 | "display_name": "Python 3", 123 | "language": "python", 124 | "name": "python3" 125 | }, 126 | "language_info": { 127 | "name": "python", 128 | "version": "3.10.8 (main, Jan 16 2023, 21:17:14) [GCC 10.2.1 20210110]" 129 | }, 130 | "orig_nbformat": 4, 131 | "vscode": { 132 | "interpreter": { 133 | "hash": "043be558b016b9409e347fbe78a27f8cd8e6dd0e74b01ce2dd00b7a6b6cbae6b" 134 | } 135 | } 136 | }, 137 | "nbformat": 4, 138 | "nbformat_minor": 2 139 | } 140 | -------------------------------------------------------------------------------- /01-lesson_notebooks/00b-Windows_Setup.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Windows setup\n", 9 | "## Tools you will need" 10 | ] 11 | }, 12 | { 13 | "attachments": {}, 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "This is a work in progress. In the meantime, see: [00a-Tools_You_Will_Need.ipynb](../03-additional_material/00a-Tools_You_Will_Need.ipynb)" 18 | ] 19 | } 20 | ], 21 | "metadata": { 22 | "kernelspec": { 23 | "display_name": "Python 3", 24 | "language": "python", 25 | "name": "python3" 26 | }, 27 | "language_info": { 28 | "name": "python", 29 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 30 | }, 31 | "orig_nbformat": 4, 32 | "vscode": { 33 | "interpreter": { 34 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 35 | } 36 | } 37 | }, 38 | "nbformat": 4, 39 | "nbformat_minor": 2 40 | } 41 | -------------------------------------------------------------------------------- /01-lesson_notebooks/01b-How_to_Use_the_Class_Materials.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# How to use the class materials\n", 9 | "The material is composed of two parts:\n", 10 | "1. A series of Jupyter notebooks that contain all of the instructional content\n", 11 | "2. A series of projects that are to be practiced on your IDE (Visual Studio Code)\n", 12 | "\n", 13 | "In the notebooks and projects directories, there is a common convention of materials containing a numbered label, for example `01`, or `03c`. The ## portion represents the week you should expect to complete the material and the letters represent the order you should work through the material. \n", 14 | "\n", 15 | "For instance, the first week you should read through all the materials under the `01-lesson_notebooks` directory and work through all the exercises contained within the notebooks that start with the convention `01-...`. Then under the `02-IDE_Exercises` complete all the projects with the `01` label (In this case there is only one project).\n", 16 | "\n", 17 | "Note, that your last two weeks will have two projects without any lessons. These projects represent the application of the culminated knowledge throughout the course.\n", 18 | "\n", 19 | "## How to use Jupyter Notebooks\n", 20 | "We can open Jupyter Notebooks in our browser window as well as an IDE that has the correct add-ins. Let's try opening it in our browser first.\n", 21 | "\n", 22 | "In your terminal equivalent (git bash is recommended for Windows) navigate to the `python_class_101` directory. Now in our terminal windows we can type in the command `jupyter notebook`. The application should launch in your default browser. It's important to understand that jupyter notebooks is running locally and using your browser as a display mechanism, it is not connecting to the internet.\n", 23 | "\n", 24 | "Let's checkout a particular notebook and how we progress through the material. Navigate in your browser window to the beginning of week 2 with the notebook `02a-Print_Statements_and_Types`.\n", 25 | "\n", 26 | "We can see that each notebook is essentially composed of two parts: blocks of text and blocks of code.\n", 27 | "\n", 28 | "Read through the text and engage with the code blocks as they generally instruct you to.\n", 29 | "\n", 30 | "For instance, in this first block we see above, we can just run the block by clicking the `Shift` + `Enter` keys.\n", 31 | "\n", 32 | "We can see a couple of indications that the cell ran. Firstly, we can see the result printed out below the cell. Also, to the left of the block we can see a label `In []`. When run it the first time, it should looks something like `1[*]` while its calculating and then look like `In [1]` once completed.\n", 33 | "\n", 34 | "Jupyter notebook cells are connected to each other on a given notebook. So the next cell we run, or if we were to run this cell again, would have the notation `In [2]`. It's important to remember that these cells are connected to each other, and that previous states are remembered. So, if you run these cells multiple times and make changes along the way, you may start to see unexpected behavior. This is important when you start defining variables, something we'll cover in `02b-Variables_and_Assignment`.\n", 35 | "\n", 36 | "Due to this, it's not a bad idea that if you start having to run a cell multiple times, it may be best to consider resetting your \"Kernel\". You can do this by selecting the drop-down labeled \"Kernel\" and selecting \"Restart\".\n", 37 | "\n", 38 | "## How to use Visual Studio Code\n", 39 | "You can run Jupyter Notebooks in VS Code as well with the appropriate extension installed. The primary purpose of our need for Visual Studio Code is to build, manage, and run our projects.\n", 40 | "\n", 41 | "Once you have completed your readings and you feel comfortable applying the lessons, you can begin the IDE project(s) associated with that particular week.\n", 42 | "Open your Visual Studio Code IDE application. Then navigate to the file tab at the top and select open folder. Then it is just a matter of navigating to the corresponding IDE project folder you’d like to work on.\n", 43 | "\n", 44 | "Here, each project will have a README that outlines the problem you should code a solution for. Every README is written in a formatting language called Markdown (so are the notebooks actually), so it won’t look very readable if you're not used to it.\n", 45 | "\n", 46 | "This can be solved by either reading the relevant README on github where the file is actually stored, or a better solution is to add a VS Code extension that allows to view formatted markdown files.\n", 47 | "\n", 48 | "On the left hand panel you’ll see a number of tools. The one that looks like a tetris block at the bottom is how we can add additional extensions to enhance our experience. So let’s click that and then in search window that pops up let’s type “Markdown Preview Enhanced” to find one made by Yiyi Wang.\n", 49 | "\n", 50 | "In my window it’s 2nd from the top. I’ve already installed it so you don’t see the little install box in my picture, but you should see an install option on yours. Simply click that install button to get the extension.\n", 51 | "\n", 52 | "Now We can click back on the explorer window to get our original view. And if we right click on our README.md display we will see an option to use our preview markdown functionality. Select that option and you should see a prettily formatted version of the file.\n", 53 | "\n", 54 | "There… much better.\n", 55 | "\n", 56 | "You can see that the problem wants to write a program that takes an input of five numbers and then prints out the average of those five numbers.\n", 57 | "\n", 58 | "It suggests you name your solution average.py. Once we’ve read the question we can close the preview and go back to our panel. Let’s start by creating a new.py file to house our answer.\n", 59 | "\n", 60 | "If I hover over the `Project-02a` folder I’ll see an icon that will let me add a new file and new folder. Select the new file button. Then simply type in the name of your file. In our case, we will call it `calculate_average.py` as suggested.\n", 61 | "\n", 62 | "Now we have a `.py` file we can write our code in to solve the problem given in the README. We can run the our code with a green arrow at the top of the IDE and any printed results in the terminal that will be displayed below.\n", 63 | "\n", 64 | "In the `02-IDE_Exercises` directory you will see a folder called `solutions`. Here you can find an example of a solution to the problem you were trying to solve. Try very hard to avoid reviewing until you have completed your attempt as fully as you can. The struggle is all part of the learning process... embrace it.\n", 65 | "\n", 66 | "\n", 67 | "\n" 68 | ] 69 | } 70 | ], 71 | "metadata": { 72 | "kernelspec": { 73 | "display_name": "Python 3", 74 | "language": "python", 75 | "name": "python3" 76 | }, 77 | "language_info": { 78 | "name": "python", 79 | "version": "3.10.8 (main, Jan 16 2023, 21:17:14) [GCC 10.2.1 20210110]" 80 | }, 81 | "orig_nbformat": 4, 82 | "vscode": { 83 | "interpreter": { 84 | "hash": "043be558b016b9409e347fbe78a27f8cd8e6dd0e74b01ce2dd00b7a6b6cbae6b" 85 | } 86 | } 87 | }, 88 | "nbformat": 4, 89 | "nbformat_minor": 2 90 | } 91 | -------------------------------------------------------------------------------- /01-lesson_notebooks/02c-Comments_Arithmetic_and_String_Concatenation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Comments, Arithmetic, & String Concatenation\n", 8 | "## Comments\n", 9 | "Comments are notes for those reading the code, and are ignored by the Python interpreter. A comment begins with #. A comment can be either on its own line or on the same line as other code. Either way, the compiler ignores everything between the # and the end of the line." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "# this is a comment\n", 19 | "height: float = 1.8 # this is also a comment" 20 | ] 21 | }, 22 | { 23 | "cell_type": "markdown", 24 | "metadata": {}, 25 | "source": [ 26 | "You should write comments that explain non-obvious aspects of your code, such as the purpose of a particular section, the units for the value of some variable, the reason for a certain design choice, etc. You certainly don't need to comment every line, but keep in mind that how your code works may not be obvious to other people, or even to yourself in a few months." 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "## Arithmetic\n", 34 | "Addition, subtraction, multiplication and division are done with the +, -, *, and / symbols." 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "The floor division operation is done with the // symbol, and gives you the rounded down result of division." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "floor_1: int = 7 // 2 # 3\n", 51 | "floor_2: int = -7 // 2 # -4" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "**Normal division results in a float value, even if the result is an integer. For example 8 / 4 would give you 2.0. If you need an integer remainder, use floor division.**" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "The mod operation is done with the % symbol, and gives you the **remainder** of division." 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": null, 71 | "metadata": {}, 72 | "outputs": [], 73 | "source": [ 74 | "remainder_1: int = 14 % 3 # 2\n", 75 | "remainder_2: int = 3 % 5 # 3" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "Exponentiation is done with the ** symbol." 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": null, 88 | "metadata": {}, 89 | "outputs": [], 90 | "source": [ 91 | "power_1: int = 3 ** 4 # 81\n", 92 | "power_2: int = 2 ** -3 # 0.125" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": {}, 98 | "source": [ 99 | "The order of operations is exponentiation, followed by multiplication, division, floor, and mod, followed by addition and subtraction. However parentheses can be used to give whatever order is needed, since operations in parentheses happen first." 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": null, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "result_1: int = 3 * 5 + 1 # 16, multiplication happens first\n", 109 | "result_2: int = 3 * (5 + 1) # 18, addition happens first" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "The += operator is a slightly shorter way to express that you want to add something to an existing value. The following statements do exactly the same thing:" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": null, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "my_sum: int = 0\n", 126 | "my_sum = my_sum + 8\n", 127 | "# the notation below is the equivalent of the notation above\n", 128 | "my_sum += 8" 129 | ] 130 | }, 131 | { 132 | "cell_type": "markdown", 133 | "metadata": {}, 134 | "source": [ 135 | "You can combine = with each of the operators above to get the following shortcut operators. See for yourself by typing in the following examples and then checking the value of 'num'." 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": null, 141 | "metadata": {}, 142 | "outputs": [], 143 | "source": [ 144 | "num: int = 1" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": {}, 151 | "outputs": [], 152 | "source": [ 153 | "num += 3 # same as num = num + 3\n", 154 | "num -= 3 # same as num = num - 3\n", 155 | "num *= 3 # same as num = num * 3\n", 156 | "num /= 3 # same as num = num / 3\n", 157 | "num //= 3 # same as num = num // 3\n", 158 | "num %= 3 # same as num = num % 3\n", 159 | "num **= 3 # same as num = num ** 3" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "The += operator is the most commonly used of these, since it's handy for accumulating totals.\n", 167 | "\n", 168 | "You can get the absolute value of a number like this:" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": null, 174 | "metadata": {}, 175 | "outputs": [], 176 | "source": [ 177 | "answer: int = abs(-12)" 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "In the above line, the variable answer is assigned the value 12." 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "## Concatenation\n", 192 | "The + operator can also be used with strings to concatenate them together." 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "metadata": {}, 199 | "outputs": [], 200 | "source": [ 201 | "first_name: str = \"Carol\"\n", 202 | "last_name: str = \"Danvers\"\n", 203 | "full_name: str = first_name + \" \" + last_name\n", 204 | "print(full_name)" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "## Exercises\n", 212 | "1. Write a statement that prints out the remainder of 17 divided by 3." 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": null, 218 | "metadata": {}, 219 | "outputs": [], 220 | "source": [ 221 | "# type code below\n" 222 | ] 223 | }, 224 | { 225 | "cell_type": "markdown", 226 | "metadata": {}, 227 | "source": [ 228 | "2. Write a statement that prints out 3 to the 4th power." 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": null, 234 | "metadata": {}, 235 | "outputs": [], 236 | "source": [ 237 | "# type code below\n" 238 | ] 239 | }, 240 | { 241 | "cell_type": "markdown", 242 | "metadata": {}, 243 | "source": [ 244 | "3. Write a statement that finds the result of 17 divided by 6 and assigns it to a variable named conversion_ratio." 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": null, 250 | "metadata": {}, 251 | "outputs": [], 252 | "source": [ 253 | "# type code below\n" 254 | ] 255 | }, 256 | { 257 | "cell_type": "markdown", 258 | "metadata": {}, 259 | "source": [ 260 | "4. Write code that first assigns 9 to a variable called num_planets, then subtracts 1 from it, so that num_planets will now equal 8." 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": null, 266 | "metadata": {}, 267 | "outputs": [], 268 | "source": [ 269 | "# type code below\n" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "5. Write code that assigns \"Doctor\" to a variable named title, assigns \"Strange\" to a variable called last_name, and then uses string concatenation to print out \"Doctor Strange\"." 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": {}, 283 | "outputs": [], 284 | "source": [ 285 | "# type code below\n" 286 | ] 287 | } 288 | ], 289 | "metadata": { 290 | "kernelspec": { 291 | "display_name": "Python 3", 292 | "language": "python", 293 | "name": "python3" 294 | }, 295 | "language_info": { 296 | "codemirror_mode": { 297 | "name": "ipython", 298 | "version": 3 299 | }, 300 | "file_extension": ".py", 301 | "mimetype": "text/x-python", 302 | "name": "python", 303 | "nbconvert_exporter": "python", 304 | "pygments_lexer": "ipython3", 305 | "version": "3.10.8" 306 | }, 307 | "vscode": { 308 | "interpreter": { 309 | "hash": "043be558b016b9409e347fbe78a27f8cd8e6dd0e74b01ce2dd00b7a6b6cbae6b" 310 | } 311 | } 312 | }, 313 | "nbformat": 4, 314 | "nbformat_minor": 4 315 | } 316 | -------------------------------------------------------------------------------- /01-lesson_notebooks/02d-Input_and_Casting.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Input & Casting\n", 8 | "## Input Function\n", 9 | "The input() function reads typed input from the user. You can use it in a couple of ways. For example, if you want to ask the user for their name, you can do this:" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "print(\"Please enter your name.\")\n", 19 | "name: str = input()\n", 20 | "print(\"Hi\", name)\n", 21 | "# make sure you actually enter something or this cell will keep running" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "Or you can do this:" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "name: str = input(\"Please enter your name: \")\n", 38 | "# make sure you actually enter something or this cell will keep running" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "Notice that with the first way, your input will appear on the line after the prompt, and with the second way, your input would appear on the same line as the prompt.\n", 46 | "\n", 47 | "User input is always a string. If you want a numeric value from user input, then you need to cast the string to an int or a float." 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "age: int = int(input(\"Please enter your age: \"))\n", 57 | "height_in_meters: float = float(input(\"Please enter your height in meters: \"))\n", 58 | "# make sure you actually enter something or this cell will keep running" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "Each of the lines above combines two functions. First the input function gets a string from the user. Next the int() or float() function casts that string to a numeric value. That value is then assigned to the variable. We can call those functions on separate lines if we want:" 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": null, 71 | "metadata": {}, 72 | "outputs": [], 73 | "source": [ 74 | "str_age = input(\"Please enter your age: \") # str_age will refer to a string value\n", 75 | "int_age = int(str_age) # int_age will refer to an int value\n", 76 | "# make sure you actually enter something or this cell will keep running" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "If the user enters a string that cannot be cast to the specified type, that causes an error. For example, if for height in meters we try to enter \"hi\", what happens?\n", 84 | "\n", 85 | "Here's an example that asks the user for two numbers and prints out their sum:" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": null, 91 | "metadata": {}, 92 | "outputs": [], 93 | "source": [ 94 | "print(\"Please enter two numbers.\")\n", 95 | "num_1 = float(input())\n", 96 | "num_2 = float(input())\n", 97 | "print(\"The sum is\", num_1 + num_2)" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "You can also cast an int to a float:" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "float(18) " 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "Or a float to an int, which truncates everything after the decimal point:" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": null, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "int(3.25)" 130 | ] 131 | }, 132 | { 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "You can also cast values to strings with str()." 137 | ] 138 | }, 139 | { 140 | "cell_type": "code", 141 | "execution_count": null, 142 | "metadata": {}, 143 | "outputs": [], 144 | "source": [ 145 | "str(-9.4) " 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": null, 151 | "metadata": {}, 152 | "outputs": [], 153 | "source": [ 154 | "str(43)" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "## Exercises\n", 162 | "1. Write code that asks the user for their name and then prints out \"Hello\" followed by their name." 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "metadata": {}, 169 | "outputs": [], 170 | "source": [ 171 | "# type code here\n" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "2. Write code that asks the user for two numbers and then prints out \"The result is\" followed by the result of multiplying those numbers." 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "# type code here\n" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "3. Take two integers as inputs with variables called `dividend` and `divisor`. Then print out a statement replacing the variables (noted with <> brackets) with your inputs:\n", 195 | "\n", 196 | " `Please enter your dividend:`\n", 197 | " \n", 198 | " `Please enter your divisor:`\n", 199 | "\n", 200 | " ` goes into times with as the remainder.`" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": null, 206 | "metadata": {}, 207 | "outputs": [], 208 | "source": [ 209 | "# type code here\n" 210 | ] 211 | } 212 | ], 213 | "metadata": { 214 | "kernelspec": { 215 | "display_name": "Python 3", 216 | "language": "python", 217 | "name": "python3" 218 | }, 219 | "language_info": { 220 | "codemirror_mode": { 221 | "name": "ipython", 222 | "version": 3 223 | }, 224 | "file_extension": ".py", 225 | "mimetype": "text/x-python", 226 | "name": "python", 227 | "nbconvert_exporter": "python", 228 | "pygments_lexer": "ipython3", 229 | "version": "3.10.8" 230 | }, 231 | "vscode": { 232 | "interpreter": { 233 | "hash": "043be558b016b9409e347fbe78a27f8cd8e6dd0e74b01ce2dd00b7a6b6cbae6b" 234 | } 235 | } 236 | }, 237 | "nbformat": 4, 238 | "nbformat_minor": 4 239 | } 240 | -------------------------------------------------------------------------------- /01-lesson_notebooks/02e-Example_Error_Messages.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Example Error Messages" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "Here are a few examples of problems and their corresponding error messages:" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## EOF" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "See what happens when you try to execute the cell below" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "print(\"hello\"" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "We omitted the closing parenthesis. EOF stands for \"end of file\" - the interpreter got to the end of the file and never found the missing parenthesis." 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "## EOL" 52 | ] 53 | }, 54 | { 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "Here's another example. See what happens when you try to execute the cell below" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "print(\"hello)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "We omitted the closing quotation mark for the string. EOL stands for \"end of line\" - the interpreter got to the end of the line without finding the missing quotation mark. Because strings can't be split across lines, the interpreter doesn't need to look all the way to the end of the file." 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "## NameError" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "print(phrase)" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "We didn't assign a value to phrase before trying to print it." 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "## SyntaxError" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "32 = age" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "We have to have a variable on the left side of an assignment statement, not a literal value." 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "metadata": {}, 126 | "source": [ 127 | "## TypeError" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": null, 133 | "metadata": {}, 134 | "outputs": [], 135 | "source": [ 136 | "num_1 = input(\"Enter first operand: \")\n", 137 | "num_2 = input(\"Enter second operand: \")\n", 138 | "print(\"The result is\", num_1 ** num_2)" 139 | ] 140 | }, 141 | { 142 | "attachments": {}, 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "We didn't cast the input strings to numbers before trying to do math with them - the ** operator isn't defined for strings. As we learned in section 2d, we can concatenate strings with a + operator, but the ** operator is not defined on the string type." 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "## Concatenation" 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "metadata": {}, 159 | "source": [ 160 | "In the Repl above, try running the code again after changing the ** in line 3 to a + sign, so that the last line looks like" 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": null, 166 | "metadata": {}, 167 | "outputs": [], 168 | "source": [ 169 | "print(\"The result is\", num_1 + num_2)" 170 | ] 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "metadata": {}, 175 | "source": [ 176 | "The reason this doesn't cause an error message is because + is defined for strings as concatenation. If you enter 3 for num_1 and 4 for num_2, then the third line will print that the result is 34, which is the concatenation of \"3\" and \"4\"." 177 | ] 178 | } 179 | ], 180 | "metadata": { 181 | "kernelspec": { 182 | "display_name": "Python 3", 183 | "language": "python", 184 | "name": "python3" 185 | }, 186 | "language_info": { 187 | "codemirror_mode": { 188 | "name": "ipython", 189 | "version": 3 190 | }, 191 | "file_extension": ".py", 192 | "mimetype": "text/x-python", 193 | "name": "python", 194 | "nbconvert_exporter": "python", 195 | "pygments_lexer": "ipython3", 196 | "version": "3.10.8" 197 | }, 198 | "vscode": { 199 | "interpreter": { 200 | "hash": "043be558b016b9409e347fbe78a27f8cd8e6dd0e74b01ce2dd00b7a6b6cbae6b" 201 | } 202 | } 203 | }, 204 | "nbformat": 4, 205 | "nbformat_minor": 4 206 | } 207 | -------------------------------------------------------------------------------- /01-lesson_notebooks/02f-Problem_Solving.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Problem Solving" 8 | ] 9 | }, 10 | { 11 | "attachments": {}, 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "## Introduction\n", 16 | "\n", 17 | "How do you get from a set of requirements to a working program? Sadly, there is no single solution or approach. Your first instinct might just be to sit down at the keyboard and start typing out code, and that might work okay for tiny problems, but for bigger problems, it can easily get you into a time-wasting spiral of errors that you're not sure how to fix. To help you avoid that outcome, here are some general principles you can follow to help guide you toward a solution:\n", 18 | "\n", 19 | " 1. Understand the requirements\n", 20 | " 2. Design tests that anticipate problems you need your code to solve\n", 21 | " 3. Outline how you would approach the problem\n", 22 | " 4. Translate your plan into code\n", 23 | " 4b. Add and run tests for each piece of your code's functionality\n", 24 | " 4c. Debug/Revise your code accordingly\n", 25 | " 4d. Iterate steps in 4 till your solution meets your requirements\n", 26 | " 5. Reflect on your approach and process\n", 27 | "\n", 28 | "You may find all of these steps overkill for very small programs, but you should practice them throughout all the provided material." 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "## 1. Understand the requirements\n", 36 | "\n", 37 | "In real life this is sometimes the most challenging part, since sometimes your clients themselves won't have a super clear idea of exactly what they want, but for the assignments you'll of course have clear guidelines of requirements. However you may find it useful to go through the assignment specifications and put them in the form of a checklist. Naturally, you may come across a scenario that the current version of this repo doesn't consider. In which case, do your best to logic through it or feel free to leave a comment or submit an issue to try and get an answer." 38 | ] 39 | }, 40 | { 41 | "attachments": {}, 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "## 2. Design tests\n", 46 | "\n", 47 | "It's important to come up with test cases that are representative of how your code could be used. You want them to be good enough that if your code passes all your tests, you will feel confident that it correctly meets all of the requirements. It's also important that for each test, you decide what result(s) you expect from that test. If you don't do that ahead of time, then it can be easy to run a test, briefly look at the output, and convince yourself that it looks reasonable.\n", 48 | "\n", 49 | "How do you know what cases to test?\n", 50 | "\n", 51 | "* Special cases: for example if your program should compute the factorial of a number, the general rule is that you take the product of all integers from 1 to that number, but zero is a special case, since the factorial of zero is 1, so zero should definitely be one of the test cases.\n", 52 | "\n", 53 | "* Boundary values: for example if a customer gets a special discount when they order 10 or more items, then you should check the numbers on both sides of that boundary (9 and 10) to make sure they're handled correctly.\n", 54 | "\n", 55 | "* Path coverage: you should have test cases that check different possible paths through your logic, to make sure the different paths give correct results.\n", 56 | "\n", 57 | "* Edge cases: extreme or unusual cases that might expose problems.\n", 58 | "\n", 59 | "* Unit tests: when your solution consists of multiple parts that each solve a piece of the problem, it's good to test each part separately, since it's easier to debug a small part at a time.\n", 60 | "\n", 61 | "* Integration tests: once you're satisfied that the different parts work correctly on their own, you need to make sure they work correctly together.\n", 62 | "\n", 63 | "It's always better for you to find cases that break your code than for a customer (or employer) to do so." 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "## 3. Outline your approach\n", 71 | "\n", 72 | "You will want come up with an outline of the steps your code will need to take to meet the requirements. Two useful strategies to help with this are stepwise refinement and working through examples of the problem by hand.\n", 73 | "\n", 74 | "### Stepwise refinement\n", 75 | "\n", 76 | "One of the most common methods for outlining your problem-solving approach is stepwise refinement. This is a process of breaking up the original problem into some number of smaller sub-problems. Next, you take each sub-problem and break it up into even smaller sub-problems. This is repeated until you get a list of steps that are detailed enough to be translated into code. This list of steps is often referred to as pseudocode.\n", 77 | "\n", 78 | "As an example of stepwise refinement, consider the problem of wanting to paint your house, which is a big job. It might seem overwhelming at first, but you can break that top-level task into the following sub-tasks:\n", 79 | "\n", 80 | "* buy paint\n", 81 | "* paint house\n", 82 | "* clean up\n", 83 | "\n", 84 | "Those sub-tasks can in turn be broken down further:\n", 85 | "\n", 86 | "* buy paint\n", 87 | " * choose colors\n", 88 | " * choose brand of paint\n", 89 | "* paint house\n", 90 | " * tape over parts that shouldn't get painted\n", 91 | " * purchase/borrow supplies (ladders, rollers, etc.)\n", 92 | " * bribe friends with pizza\n", 93 | " * schedule a day/time\n", 94 | " * actually paint the house\n", 95 | "* clean up\n", 96 | " * return/put away supplies\n", 97 | " * un-tape the taped bits\n", 98 | " * finish any fine detail work\n", 99 | "\n", 100 | "This process continues until you've defined everything to a level of detail where you feel comfortable that you know every small step that needs to happen.\n", 101 | "\n", 102 | "### Work through examples by hand\n", 103 | "\n", 104 | "Brains are pretty smart (most of the time). They know how to do lots of stuff without us really being conscious of the steps we're going through to make that stuff happen. In this method, you solve multiple examples of the problem yourself with pencil and paper, paying close attention to each tiny step. Doing this will often help you notice the pattern(s) in how you solve different examples of that problem. This strategy can be used together with stepwise refinement, to help you figure out what the sub-tasks should be." 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "## 4a. Translate your outline into code\n", 112 | "\n", 113 | "Take the outline (or pseudocode) you've created and translate each small sub-task into code, but don't do it all at once (unless it's a tiny program). Instead, you should produce a short section of code and then try running it to see if that part does what you expect. If it does, then you can add another short section and run it again, until you've translated your whole outline. If you avoid making lots of changes at once, it's easier to track down any new bugs that pop up.\n" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "## 4b. Run your tests\n", 121 | "\n", 122 | "How do you know if your code does what you expect? By running the tests you designed back in step #2. If you've thought of more tests while coding, add those in. The more testing you do, the more bugs you'll catch.\n" 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "## 4c. Debug your code\n", 130 | "\n", 131 | "What if your code doesn't do what you expect? Well then you need to find the problem and fix it. Fortunately, since you're only making a few changes to your code at a time, that means any new problem is almost certainly among those few changes. Often error messages will also give you information about what the problem is and where it occurred. If you don't see the problem at first, try to methodically narrow down where it could be. After making corrections, re-run your tests to make sure that part works now, and that you haven't accidentally broken anything else.\n" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "## 4d. Let me reiterate to iterate\n", 139 | "\n", 140 | "As you build each piece of your code test along the way and fix the bugs if there are any. Then do it again: build, test, and debug. Essentially, don't just write the whole program in one go, hoping there's not a single typo or error in logic. Ensure each piece you write works as expected and by the time it's complete it will be much more likely to act as you'd expect." 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "## 5. Reflect on your process\n", 148 | "\n", 149 | "Reflecting on your problem solving process can help you fine tune it to work better next time. What did you learn about the problem as you went? What tests didn't work out the way you expected? What alterations did you have to make to your program due to failed tests? How could your planned tests have been more complete? What was missing or needed to be altered from your initial design, and why? What problems did you encounter during implementation? How were you able to solve those problems? What outside sources (sites, books, or other materials) did you find helpful? How can you generalize any parts of your problem solving experience in a way that might help you on future assignments?" 150 | ] 151 | } 152 | ], 153 | "metadata": { 154 | "kernelspec": { 155 | "display_name": "Python 3", 156 | "language": "python", 157 | "name": "python3" 158 | }, 159 | "language_info": { 160 | "codemirror_mode": { 161 | "name": "ipython", 162 | "version": 3 163 | }, 164 | "file_extension": ".py", 165 | "mimetype": "text/x-python", 166 | "name": "python", 167 | "nbconvert_exporter": "python", 168 | "pygments_lexer": "ipython3", 169 | "version": "3.10.8" 170 | }, 171 | "vscode": { 172 | "interpreter": { 173 | "hash": "043be558b016b9409e347fbe78a27f8cd8e6dd0e74b01ce2dd00b7a6b6cbae6b" 174 | } 175 | } 176 | }, 177 | "nbformat": 4, 178 | "nbformat_minor": 4 179 | } 180 | -------------------------------------------------------------------------------- /01-lesson_notebooks/02g-Exercise_Solutions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercises Solutions\n", 8 | "## Print Statements and Types\n", 9 | "1. Write a statement that prints out the float value 188.67." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "print(188.67)" 19 | ] 20 | }, 21 | { 22 | "cell_type": "markdown", 23 | "metadata": {}, 24 | "source": [ 25 | "2. Write a statement that prints out the string value `\"Knock knock, \"Who's There?\", \"Your Mom.\"`" 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "print('''\"Knock knock, \"Who's There?\", \"Your Mom.\"''')" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "3. Write a statement that prints out the bool value True (not the string value \"True\")." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "print(True)" 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "4. Write a statement that prints out the result of calling the type function on the value 77." 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "print(type(77))" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "5. Write a statement that prints out the type of the value `\"You talkin' to me?\"`" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": null, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [ 82 | "print(type(\"You talkin' to me\"))" 83 | ] 84 | }, 85 | { 86 | "cell_type": "markdown", 87 | "metadata": {}, 88 | "source": [ 89 | "## Variables and Assignment\n", 90 | "1. Assign the value 3.14159 to a variable named pi, and then print out the value of that variable." 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": null, 96 | "metadata": {}, 97 | "outputs": [], 98 | "source": [ 99 | "pi: float = 3.14159 \n", 100 | "print(pi)" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "2. Assign the value \"Nguyen\" to a variable named last_name, and then print out the value of that variable." 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": null, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [ 116 | "last_name: str = \"Nguyen\"\n", 117 | "print(last_name)" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": {}, 123 | "source": [ 124 | " 3. Assign the value 16.4 to a variable named length, and then print out the type of the value that variable refers to." 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": null, 130 | "metadata": {}, 131 | "outputs": [], 132 | "source": [ 133 | "length: float = 16.4\n", 134 | "print(type(length))" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "4. Assign the value \"blacksmith\" to a variable named occupation, and the print out the type of the value that variable refers to." 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": null, 147 | "metadata": {}, 148 | "outputs": [], 149 | "source": [ 150 | "occupation: str = \"blacksmith\"\n", 151 | "print(type(occupation))" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "## Comments, Arithmetic, and String Concatenation\n", 159 | "1. Write a statement that prints out the remainder of 17 divided by 3." 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": {}, 166 | "outputs": [], 167 | "source": [ 168 | "print( 17 % 3)" 169 | ] 170 | }, 171 | { 172 | "cell_type": "markdown", 173 | "metadata": {}, 174 | "source": [ 175 | "2. Write a statement that prints out 3 to the 4th power." 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "print(3 ** 4)" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "1. Write a statement that finds the result of 17 divided by 6 and assigns it to a variable named conversion_ratio." 192 | ] 193 | }, 194 | { 195 | "cell_type": "code", 196 | "execution_count": null, 197 | "metadata": {}, 198 | "outputs": [], 199 | "source": [ 200 | "conversion_ratio: float = 17/6" 201 | ] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "metadata": {}, 206 | "source": [ 207 | "4. Write code that first assigns 9 to a variable called num_planets, then subtracts 1 from it, so that num_planets will now equal 8." 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": null, 213 | "metadata": {}, 214 | "outputs": [], 215 | "source": [ 216 | "num_planets: int = 9\n", 217 | "num_planets -= 1" 218 | ] 219 | }, 220 | { 221 | "cell_type": "markdown", 222 | "metadata": {}, 223 | "source": [ 224 | "5. Write code that assigns \"Doctor\" to a variable named title, assigns \"Strange\" to a variable called last_name, and then uses string concatenation to print out \"Doctor Strange\"." 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": {}, 231 | "outputs": [], 232 | "source": [ 233 | "title: str = \"Doctor\"\n", 234 | "last_name: str = \"Strange\"\n", 235 | "print(title + \" \" + last_name)" 236 | ] 237 | }, 238 | { 239 | "cell_type": "markdown", 240 | "metadata": {}, 241 | "source": [ 242 | "## Input and Casting\n", 243 | "1. Write code that asks the user for their name and then prints out \"Hello\" followed by their name." 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": null, 249 | "metadata": {}, 250 | "outputs": [], 251 | "source": [ 252 | "name: str = input(\"name?\")\n", 253 | "print(\"Hello\", name)" 254 | ] 255 | }, 256 | { 257 | "cell_type": "markdown", 258 | "metadata": {}, 259 | "source": [ 260 | "2. Write code that asks the user for two numbers and then prints out \"The result is\" followed by the result of multiplying those numbers." 261 | ] 262 | }, 263 | { 264 | "cell_type": "code", 265 | "execution_count": null, 266 | "metadata": {}, 267 | "outputs": [], 268 | "source": [ 269 | "first_num: float = float(input())\n", 270 | "second_num: float = float(input())\n", 271 | "print(\"The result is\", first_num * second_num)" 272 | ] 273 | }, 274 | { 275 | "attachments": {}, 276 | "cell_type": "markdown", 277 | "metadata": {}, 278 | "source": [ 279 | "3. Take two integers as inputs with variables called `dividend` and `divisor`. Then print out a statement replacing the variables (noted with <> brackets) with your inputs:\n", 280 | "```\n", 281 | "Please enter your dividend:\n", 282 | " \n", 283 | "Please enter your divisor:\n", 284 | "\n", 285 | " goes into times with as the remainder.\n", 286 | "```" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": {}, 293 | "outputs": [], 294 | "source": [ 295 | "dividend: int = int(input(\"Please enter your dividend: \"))\n", 296 | "divisor: int = int(input(\"Please enter your divisor: \"))\n", 297 | "floor_divison: int = dividend // divisor\n", 298 | "remainder: int = dividend % divisor\n", 299 | "print(divisor, \"goes into\", dividend, floor_divison, \"times with\", remainder, \"as the remainder.\")" 300 | ] 301 | } 302 | ], 303 | "metadata": { 304 | "kernelspec": { 305 | "display_name": "Python 3", 306 | "language": "python", 307 | "name": "python3" 308 | }, 309 | "language_info": { 310 | "codemirror_mode": { 311 | "name": "ipython", 312 | "version": 3 313 | }, 314 | "file_extension": ".py", 315 | "mimetype": "text/x-python", 316 | "name": "python", 317 | "nbconvert_exporter": "python", 318 | "pygments_lexer": "ipython3", 319 | "version": "3.7.16 (default, Jan 9 2023, 01:23:12) \n[GCC 11.3.0]" 320 | }, 321 | "vscode": { 322 | "interpreter": { 323 | "hash": "2a806d3aeacb674212bb9595bc81b7e00560d028deaf5d893b1185a2f7bac5ac" 324 | } 325 | } 326 | }, 327 | "nbformat": 4, 328 | "nbformat_minor": 4 329 | } 330 | -------------------------------------------------------------------------------- /01-lesson_notebooks/03a-Comparison_Operators_And_Logical_Operators.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Comparison Operators and Logical Operators" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Comparison Operators" 15 | ] 16 | }, 17 | { 18 | "attachments": {}, 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "We often need to compare two values. Is one value greater? lesser? equal to?\n", 23 | "\n", 24 | "Python has the following comparison operators:\n", 25 | "\n", 26 | "```python\n", 27 | "num_1 == num_2 # num_1 equals num_2\n", 28 | "num_1 != num_2 # num_1 does not equal num_2\n", 29 | "num_1 > num_2 # num_1 is greater than num_2\n", 30 | "num_1 < num_2 # num_1 is less than num_2\n", 31 | "num_1 >= num_2 # num_1 is greater than or equal to num_2\n", 32 | "num_1 <= num_2 # num_1 is less than or equal to num_2\n", 33 | "```" 34 | ] 35 | }, 36 | { 37 | "attachments": {}, 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "Each of the above **conditions** is either `True` or `False`, so if you print out the type of the comparison, you'll see that it's a bool value (`True` or `False`). \n", 42 | "\n", 43 | "For example:" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "17 < 5 # False" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "3 != 12 # True" 62 | ] 63 | }, 64 | { 65 | "attachments": {}, 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "Don't mix up the assignment operator (`=`) and the equality operator (`==`). It's a common mistake that can be hard to see.\n", 70 | "\n", 71 | "**Careful, You shouldn't test two floats for exact equality because of possible lack of precision or round-off errors.** \n", 72 | "\n", 73 | "Instead, if you need to compare float values for equality, you can do something like this:\n", 74 | "\n", 75 | "```python\n", 76 | "abs(num_1 - num_2) < 0.000001\n", 77 | "```" 78 | ] 79 | }, 80 | { 81 | "attachments": {}, 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "This takes the absolute value of the difference between the two numbers and checks whether it's less than a very small value.\n", 86 | "\n", 87 | "Unlike many computer languages, Python allows you to chain comparison operators. In Python you check if x is between 2 and 7 by saying\n", 88 | "\n", 89 | "```python\n", 90 | "2 < x < 7\n", 91 | "```\n", 92 | " \n", 93 | "whereas in most languages you would need to write that as\n", 94 | "```python\n", 95 | "2 < x and x < 7\n", 96 | "```\n", 97 | " \n", 98 | "The logical operator `and` is discussed in the following section." 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "## Logical Operators" 106 | ] 107 | }, 108 | { 109 | "attachments": {}, 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "Sometimes we need to combine comparisons. Python has the following logical operators:\n", 114 | "\n", 115 | "```python\n", 116 | "bool_1 and bool_2 # Both bool_1 and bool_2 equal True\n", 117 | "bool_1 or bool_2 # At least one of bool_1 and bool_2 equals True\n", 118 | "not bool_1 # Flips the value of bool_1. If bool_1 is True not bool_1 is False and vice versa\n", 119 | "```\n", 120 | " \n", 121 | "Each of these conditions is also either True or False." 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": null, 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "17 >= 10 and 5 % 2 == 0 # True and False, which equals False" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": null, 136 | "metadata": {}, 137 | "outputs": [], 138 | "source": [ 139 | "17 >= 10 or 5 % 2 == 0 # True or False, which equals True" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "not 17 >= 10 # not True, which equals False" 149 | ] 150 | }, 151 | { 152 | "attachments": {}, 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "## Some Clarification\n", 157 | "\n", 158 | "Logical conditionals can appear confusing, but they're actually similar to everyday language. \n", 159 | "\n", 160 | "Consider two conditions, represented by `P` and `Q`. When `P` and `Q` are joined with the `and` operator, the statement is true only if both `P` and `Q` are true. For example, if someone asks *\"Do you have a car and a driver's license?\"* The answer would be yes only if you have **BOTH** a car **AND** a driver's license. On the other hand, the `or` operator makes the statement `True` if either `P` or `Q` (or both) are `True`. If someone asks *\"Do you have a car or a bike?\"* The answer would be yes if you have either a car or a bike (or both). \n", 161 | "\n", 162 | "The `not` operator simply reverses the truth value of a statement, so if `P` is `False`, then `not P` is `True` and vice versa." 163 | ] 164 | }, 165 | { 166 | "attachments": {}, 167 | "cell_type": "markdown", 168 | "metadata": {}, 169 | "source": [ 170 | "## A Common Syntax Error\n", 171 | "\n", 172 | "\n", 173 | "To check if num_x and num_y are both equal to 5, it is **not** correct to do the following:\n", 174 | "\n", 175 | "```python\n", 176 | "num_x and num_y == 5 # wrong\n", 177 | "```\n", 178 | " \n", 179 | "since that would check whether `num_x` is `True` and `num_y==5` is `True`. Instead, you would need to do this:\n", 180 | "\n", 181 | "```python\n", 182 | "num_x == 5 and num_y == 5\n", 183 | "```\n", 184 | " \n", 185 | "or since we know we can chain comparisons:\n", 186 | "\n", 187 | "```python\n", 188 | "num_x == num_y == 5\n", 189 | "```" 190 | ] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": {}, 195 | "source": [ 196 | "## Exercises" 197 | ] 198 | }, 199 | { 200 | "attachments": {}, 201 | "cell_type": "markdown", 202 | "metadata": {}, 203 | "source": [ 204 | "1. Print the value of `17 < 5`." 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": null, 210 | "metadata": {}, 211 | "outputs": [], 212 | "source": [ 213 | "# type code here\n" 214 | ] 215 | }, 216 | { 217 | "attachments": {}, 218 | "cell_type": "markdown", 219 | "metadata": {}, 220 | "source": [ 221 | "2. Write code that reads a number from the user, assigns it to a variable, and then prints `True` if that value is greater than 10, but prints `False` otherwise." 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": null, 227 | "metadata": {}, 228 | "outputs": [], 229 | "source": [ 230 | "# type code here\n" 231 | ] 232 | }, 233 | { 234 | "attachments": {}, 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "3. Write code that reads a number from the user, assigns it to a variable, and then prints `True` if that value is between 50 and 100 (inclusive), but prints `False` otherwise." 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": null, 244 | "metadata": {}, 245 | "outputs": [], 246 | "source": [ 247 | "# type code here\n" 248 | ] 249 | } 250 | ], 251 | "metadata": { 252 | "kernelspec": { 253 | "display_name": "Python 3", 254 | "language": "python", 255 | "name": "python3" 256 | }, 257 | "language_info": { 258 | "codemirror_mode": { 259 | "name": "ipython", 260 | "version": 3 261 | }, 262 | "file_extension": ".py", 263 | "mimetype": "text/x-python", 264 | "name": "python", 265 | "nbconvert_exporter": "python", 266 | "pygments_lexer": "ipython3", 267 | "version": "3.10.8" 268 | }, 269 | "vscode": { 270 | "interpreter": { 271 | "hash": "043be558b016b9409e347fbe78a27f8cd8e6dd0e74b01ce2dd00b7a6b6cbae6b" 272 | } 273 | } 274 | }, 275 | "nbformat": 4, 276 | "nbformat_minor": 4 277 | } 278 | -------------------------------------------------------------------------------- /01-lesson_notebooks/03b-Conditional_Execution.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Conditional Execution\n", 9 | "## `if` Statements\n", 10 | "The `if` statement enables us to define branches in our code based on whether a given condition is `True` or `False`. Here's a simple example:" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": null, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "num: int = 14\n", 20 | "if num % 2 == 0: \n", 21 | " print(\"num is even\") # This line executes if and only if the condition is True\n", 22 | "else: \n", 23 | " print(\"num is odd\") # This line executes if and only if the condition is False" 24 | ] 25 | }, 26 | { 27 | "attachments": {}, 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "The else case is optional. Both the `if` and `else` cases can contain as many statements as needed:" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": null, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "even_nums: int = 0\n", 41 | "odd_nums: int = 0\n", 42 | "\n", 43 | "num: int = 47\n", 44 | "if num % 2 == 0:\n", 45 | " print(\"num is even\") \n", 46 | " even_nums += 1\n", 47 | "else: \n", 48 | " print(\"num is odd\") \n", 49 | " odd_nums += 1" 50 | ] 51 | }, 52 | { 53 | "attachments": {}, 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "Indentation is crucial for the proper functioning of a Python program. While indentation is important for readability in many programming languages, in Python it plays a larger role as it determines the grouping of statements. Code blocks related to a specific if statement, for example, are indented underneath, and a new block of related statements begins with a return to the original indentation.\n", 58 | "\n", 59 | "While the Python language does not dictate a specific number of spaces for indentation, it is generally recommended to indent 4 spaces, unless the existing code uses a different amount." 60 | ] 61 | }, 62 | { 63 | "attachments": {}, 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "## Nested `if` statements and `elif`\n", 68 | "You can also have nested `if` statements (`if` statements inside other `if` statements):" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": {}, 75 | "outputs": [], 76 | "source": [ 77 | "score: int = int(input(\"Enter a score: \"))\n", 78 | "grade: str = \"\"\n", 79 | "if score >= 90: \n", 80 | " grade = \"A\"\n", 81 | "else: \n", 82 | " if score >= 80: # If we get here we already know the score is less than 90\n", 83 | " grade = \"B\" \n", 84 | " else: \n", 85 | " if score >= 70: # If we get here we already know the score is less than 80\n", 86 | " grade = \"C\" \n", 87 | " else: \n", 88 | " if score >= 60: # Etc. \n", 89 | " grade = \"D\" \n", 90 | " else: \n", 91 | " grade = \"F\"\n", 92 | "print(\"Letter grade = \", grade)" 93 | ] 94 | }, 95 | { 96 | "attachments": {}, 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "The indentation tells the Python interpreter which ifs and elses go together, however, this level of nesting can get a little hard to read, so the more common way to express this example would be:" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "score: int = int(input(\"Enter a score: \"))\n", 110 | "grade: str = \"\"\n", 111 | "if score >= 90:\n", 112 | " grade = \"A\"\n", 113 | "elif score >= 80:\n", 114 | " grade = \"B\"\n", 115 | "elif score >= 70:\n", 116 | " grade = \"C\"\n", 117 | "elif score >= 60:\n", 118 | " grade = \"D\"\n", 119 | "else:\n", 120 | " grade = \"F\"\n", 121 | "print(\"Letter grade = \", grade)" 122 | ] 123 | }, 124 | { 125 | "attachments": {}, 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "Where `elif` is short for `else if`.\n" 130 | ] 131 | }, 132 | { 133 | "attachments": {}, 134 | "cell_type": "markdown", 135 | "metadata": {}, 136 | "source": [ 137 | "\n", 138 | "## Extra note on indentation\n", 139 | "Additionally, it's worth mentioning that in Python, indentation is **MANDATORY** and must be consistent throughout the code. This means that each code block must be indented to the same level, and every line within a block must have the same indentation. Mixing spaces and tabs for indentation is not recommended, as it can cause issues with code readability and portability.\n", 140 | "\n", 141 | "Furthermore, it's important to note that changing the indentation level of a code block can change its meaning, and can lead to unexpected results. For example, an if statement that is indented correctly to indicate that a block of code should be executed only if a certain condition is met, may not work as expected if the indentation is incorrect.\n", 142 | "\n", 143 | "Proper indentation is essential for writing correct and readable Python code, and should be given careful consideration when writing or modifying code. Consistent indentation and adherence to recommended conventions can greatly improve the readability and maintainability of your code." 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "## Exercises\n", 151 | "1. Write code that reads a number from the user, assigns it to a variable, and then prints \"in range\" if that value is between 50 and 100, but prints \"out of range\" otherwise." 152 | ] 153 | }, 154 | { 155 | "cell_type": "code", 156 | "execution_count": null, 157 | "metadata": {}, 158 | "outputs": [], 159 | "source": [ 160 | "# type code here\n" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "metadata": {}, 166 | "source": [ 167 | "2. Write code that reads a number from the user, assigns it to a variable, and then prints \"small\" if it's less than 10, prints \"medium\" if it's at least 10 but less than 50, and prints \"large\" if it's at least 50." 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": null, 173 | "metadata": {}, 174 | "outputs": [], 175 | "source": [ 176 | "# type code here\n" 177 | ] 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "metadata": {}, 182 | "source": [ 183 | "3. Write code that reads an integer from the user and assigns it to a variable. If that integer is a value from 1-5, your program should print out the English word for that number. Otherwise it should print \"input not recognized\"." 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": null, 189 | "metadata": {}, 190 | "outputs": [], 191 | "source": [ 192 | "# type code here\n" 193 | ] 194 | } 195 | ], 196 | "metadata": { 197 | "kernelspec": { 198 | "display_name": "Python 3", 199 | "language": "python", 200 | "name": "python3" 201 | }, 202 | "language_info": { 203 | "codemirror_mode": { 204 | "name": "ipython", 205 | "version": 3 206 | }, 207 | "file_extension": ".py", 208 | "mimetype": "text/x-python", 209 | "name": "python", 210 | "nbconvert_exporter": "python", 211 | "pygments_lexer": "ipython3", 212 | "version": "3.10.8" 213 | }, 214 | "vscode": { 215 | "interpreter": { 216 | "hash": "043be558b016b9409e347fbe78a27f8cd8e6dd0e74b01ce2dd00b7a6b6cbae6b" 217 | } 218 | } 219 | }, 220 | "nbformat": 4, 221 | "nbformat_minor": 4 222 | } 223 | -------------------------------------------------------------------------------- /01-lesson_notebooks/03d-Code_Tracing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Code Tracing" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Flow of Execution: Code Tracing" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "Being able to trace the flow of execution through a given piece of code and tell how it will behave, is a critical skill for reading and understanding code, as well as for debugging. Here are four common methods people use to help them do this:\n", 22 | "\n", 23 | "1. Hand-tracing is just stepping through the code as if you were the computer, going along line by line, and keeping track of the current values of all the variables as they change. You can write down on paper (or a whiteboard) a row (or column) for each variable, and then each time the value for that variable changes, you can cross off the old value and write down the new value.\n", 24 | "\n", 25 | "2. Temporarily inserting print statements at various places in your code can also be useful for checking what values variables referred to at those points. Make sure to delete such print statements when you're done with them.\n", 26 | "\n", 27 | "3. Many programming environments provide a built-in debugger, which lets you look at the current values of the different variables to see how they change as you step through the code line by line.\n", 28 | "\n", 29 | "4. Explaining how your code works to someone else can often give you an \"Aha!\" moment where it helps you see a disconnect between what your code is supposed to do and what it actually does. This can even work when explaining your code to a cat or dog, or even a rubber duck.\n", 30 | "\n", 31 | "All of these are worth being comfortable with." 32 | ] 33 | } 34 | ], 35 | "metadata": { 36 | "kernelspec": { 37 | "display_name": "Python 3", 38 | "language": "python", 39 | "name": "python3" 40 | }, 41 | "language_info": { 42 | "codemirror_mode": { 43 | "name": "ipython", 44 | "version": 3 45 | }, 46 | "file_extension": ".py", 47 | "mimetype": "text/x-python", 48 | "name": "python", 49 | "nbconvert_exporter": "python", 50 | "pygments_lexer": "ipython3", 51 | "version": "3.7.16 (default, Jan 9 2023, 01:23:12) \n[GCC 11.3.0]" 52 | }, 53 | "vscode": { 54 | "interpreter": { 55 | "hash": "2a806d3aeacb674212bb9595bc81b7e00560d028deaf5d893b1185a2f7bac5ac" 56 | } 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 4 61 | } 62 | -------------------------------------------------------------------------------- /01-lesson_notebooks/03e-Exercise_Solutions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercise Solutions" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Comparison Operators and Logical Operators" 15 | ] 16 | }, 17 | { 18 | "attachments": {}, 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "1. Print the value of `17 < 5`." 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": null, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "print(17 < 5)" 32 | ] 33 | }, 34 | { 35 | "attachments": {}, 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "2. Write code that reads a number from the user, assigns it to a variable, and then prints `True` if that value is greater than 10, but prints `False` otherwise." 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "var:float = float(input())\n", 49 | "print(var > 10)" 50 | ] 51 | }, 52 | { 53 | "attachments": {}, 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "3. Write code that reads a number from the user, assigns it to a variable, and then prints `True` if that value is between 50 and 100, but prints `False` otherwise." 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "var: float = float(input())\n", 67 | "print(var >= 50 and var <= 100)" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "## Conditional Execution" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "1. Write code that reads a number from the user, assigns it to a variable, and then prints \"in range\" if that value is between 50 and 100, but prints \"out of range\" otherwise." 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "var: float = float(input())\n", 91 | "if var >= 50 and var <=100:\n", 92 | " print(\"in range\")\n", 93 | "else:\n", 94 | " print(\"out of range\")" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "2. Write code that reads a number from the user, assigns it to a variable, and then prints \"small\" if it's less than 10, prints \"medium\" if it's at least 10 but less than 50, and prints \"large\" if it's at least 50." 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "var: float = float(input())\n", 111 | "if var < 10:\n", 112 | " print(\"small\")\n", 113 | "elif var < 50:\n", 114 | " print(\"medium\")\n", 115 | "else:\n", 116 | " print(\"large\")" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "3. Write code that reads an integer from the user and assigns it to a variable. If that integer is a value from 1-5, your program should print out the English word for that number. Otherwise it should print \"input not recognized\"." 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "var: int = int(input())\n", 133 | "\n", 134 | "if var == 1:\n", 135 | " print(\"one\")\n", 136 | "elif var == 2:\n", 137 | " print(\"two\")\n", 138 | "elif var == 3:\n", 139 | " print(\"three\")\n", 140 | "elif var == 4:\n", 141 | " print(\"four\")\n", 142 | "elif var == 5:\n", 143 | " print(\"five\")\n", 144 | "else:\n", 145 | " print(\"input not recognized\")" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "## Iteration" 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "1. Write code that reads an integer from the user and prints out the sum of the integers from 1 to that number." 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": {}, 166 | "outputs": [], 167 | "source": [ 168 | "limit: int = int(input())\n", 169 | "sum: int = 0\n", 170 | "i: int\n", 171 | "for i in range(1, limit + 1):\n", 172 | " sum += i\n", 173 | "print(sum)" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "2. Write code that reads a string from the user, counts how many characters are in the string, and prints out \"odd\" if that number is odd, but prints \"even\" if that number is even." 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": null, 186 | "metadata": {}, 187 | "outputs": [], 188 | "source": [ 189 | "my_string: str = input()\n", 190 | "count: int = 0\n", 191 | "character: str\n", 192 | "for character in my_string:\n", 193 | " count += 1\n", 194 | "\n", 195 | "if count % 2 == 1:\n", 196 | " print(\"odd\")\n", 197 | "else:\n", 198 | " print(\"even\")" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "3. Write code that continues reading a string from the user and printing it out until the user enters \"quit\"." 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": null, 211 | "metadata": {}, 212 | "outputs": [], 213 | "source": [ 214 | "user_input: str = input()\n", 215 | "while user_input != \"quit\":\n", 216 | " print(user_input)\n", 217 | " user_input = input()" 218 | ] 219 | } 220 | ], 221 | "metadata": { 222 | "kernelspec": { 223 | "display_name": "Python 3", 224 | "language": "python", 225 | "name": "python3" 226 | }, 227 | "language_info": { 228 | "codemirror_mode": { 229 | "name": "ipython", 230 | "version": 3 231 | }, 232 | "file_extension": ".py", 233 | "mimetype": "text/x-python", 234 | "name": "python", 235 | "nbconvert_exporter": "python", 236 | "pygments_lexer": "ipython3", 237 | "version": "3.7.16 (default, Jan 9 2023, 01:23:12) \n[GCC 11.3.0]" 238 | }, 239 | "vscode": { 240 | "interpreter": { 241 | "hash": "2a806d3aeacb674212bb9595bc81b7e00560d028deaf5d893b1185a2f7bac5ac" 242 | } 243 | } 244 | }, 245 | "nbformat": 4, 246 | "nbformat_minor": 4 247 | } 248 | -------------------------------------------------------------------------------- /01-lesson_notebooks/04b-Exercise_Solutions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercise Solutions" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Functions" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "1. Write a function that takes a numeric parameter and returns twice that number. Write a print statement that calls your function with the number 5 and prints the function's return value" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "def double_num(x: int) -> int:\n", 31 | " return x*2\n", 32 | " \n", 33 | "print(double_num(5))" 34 | ] 35 | }, 36 | { 37 | "attachments": {}, 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "2. Write a function that takes two string parameters and returns the string formed by concatenating those two strings together. Write a print statement that calls your function with the values `\"hello \"` and `\"world\"` and prints the function's return value." 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": {}, 48 | "outputs": [], 49 | "source": [ 50 | "def combine_string(s1: str, s2: str) -> str:\n", 51 | " return s1 + s2\n", 52 | " \n", 53 | "print(combine_string(\"hello \", \"world\"))" 54 | ] 55 | }, 56 | { 57 | "attachments": {}, 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "3. Write a function named `is_even` that takes an integer parameter and returns a `bool` value - `True` if the integer is even, and `False` if the integer is odd." 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "def is_even(n: int) -> bool:\n", 71 | " return n % 2 == 0\n", 72 | "\n", 73 | "print(is_even(3))\n", 74 | "print(is_even(48))" 75 | ] 76 | } 77 | ], 78 | "metadata": { 79 | "kernelspec": { 80 | "display_name": "Python 3", 81 | "language": "python", 82 | "name": "python3" 83 | }, 84 | "language_info": { 85 | "codemirror_mode": { 86 | "name": "ipython", 87 | "version": 3 88 | }, 89 | "file_extension": ".py", 90 | "mimetype": "text/x-python", 91 | "name": "python", 92 | "nbconvert_exporter": "python", 93 | "pygments_lexer": "ipython3", 94 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 95 | }, 96 | "vscode": { 97 | "interpreter": { 98 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 99 | } 100 | } 101 | }, 102 | "nbformat": 4, 103 | "nbformat_minor": 4 104 | } 105 | -------------------------------------------------------------------------------- /01-lesson_notebooks/05a-Recursion.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Recursion" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Introduction" 15 | ] 16 | }, 17 | { 18 | "attachments": {}, 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "A recursive function is a function that calls itself. Each time it calls itself, a separate copy is created that has its own values for its parameters and variables. Of course, if every copy creates another copy, then the recursion will never end, and we'll run out of memory, so it's crucial that every recursive function have one or more base cases. A base case is a case where the function doesn't call itself.\n", 23 | "\n", 24 | "Let's look at a common first example of recursion:" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "def factorial(num: int) -> int:\n", 34 | " \"\"\"\n", 35 | " Returns the factorial of num\n", 36 | " \"\"\"\n", 37 | " if num == 0:\n", 38 | " return 1\n", 39 | " else:\n", 40 | " return num * factorial(num-1)" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "The condition of the if statement checks whether *num* is equal to zero. This is the base case. If it's true, then the function does not call itself. However, if the base case is not true, then it calls itself, performs a multiplication with the return value, and returns the result. We could also write it like this:" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "def factorial(num: int) -> int: \n", 57 | " \"\"\" \n", 58 | " Returns the factorial of num \n", 59 | " \"\"\" \n", 60 | " if num == 0: \n", 61 | " return 1 \n", 62 | " \n", 63 | " return num * factorial(num-1)" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "The else can be omitted here because if the condition is true, then \"return 1\" is executed, and the function ends before it can reach the recursive call. This is the logic I'll use in the other examples in this lesson." 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "## The Call Stack" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "When running a recursive function, multiple copies of the function will be active at once, but only the most recent one will be executing - the others are paused while waiting for a result. When a recursive call is made, the computer needs to save our place in the current copy of the function, so that we can come back to it later. Then we can start executing a new copy of the function. The computer saves our place in the current copy by storing its information on the **call stack**, which keeps track of all active function calls. Watch the video \"Flow of execution example for recursion\" to see how this works." 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "## More examples" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "Here's a recursive function that finds the greatest common divisor of two integers: " 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": null, 104 | "metadata": {}, 105 | "outputs": [], 106 | "source": [ 107 | "def gcd(a: int, b: int) -> int: \n", 108 | " \"\"\" \n", 109 | " Returns the greatest common divisor of a and b \n", 110 | " \"\"\" \n", 111 | " if a % b == 0: \n", 112 | " return b \n", 113 | " \n", 114 | " return gcd(b, a % b)" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "\n", 122 | "\n", 123 | "The base case is when b evenly divides *a*, in which case *b* is the greatest common divisor. Otherwise we make a recursive call with the value of *b* passed for *a*, and the value of *a % b* passed for *b*. Nothing needs to be done with the return values on the way back out of the recursive calls.\n", 124 | "\n", 125 | "Here's a recursive function that computes the hailstone sequence starting from a given number and counts how many steps it takes to reach 1:" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [ 134 | "def hailstone(num: int) -> int: \n", 135 | " \"\"\" \n", 136 | " Returns the number of steps it takes for a hailstone sequence that starts \n", 137 | " at num to reach 1 \n", 138 | " \"\"\" \n", 139 | " if num == 1: \n", 140 | " return 0 \n", 141 | " if num % 2 == 0: # if num is even \n", 142 | " return hailstone(num/2) + 1 \n", 143 | " else: \n", 144 | " return hailstone(num*3+1) + 1" 145 | ] 146 | }, 147 | { 148 | "cell_type": "markdown", 149 | "metadata": {}, 150 | "source": [ 151 | "Here the base case is when the sequence arrives at 1. You can see that there are two different recursive cases - one that happens if *num* is odd, and one that happens if *num* is even. We add 1 to the return value, since the current copy of hailstone takes one more step to reach 1 than the recursive call does. For example, if we start at 3, the sequence goes: 3, 10, 5, 16, 8, 4, 2, 1. If we find the number of steps it takes to go from 10 to 1, then we can just add 1 more step to get the number of steps it takes to go from 3 to 1." 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": {}, 157 | "source": [ 158 | "## Writing a Recursive Function" 159 | ] 160 | }, 161 | { 162 | "attachments": {}, 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "Recursion can feel like it's partly magic, because you're writing a function that is calling the function you're still writing. It feels like an M.C. Escher print. The general strategy for designing a recursive function is to identify how a problem can be broken up into a smaller problem of the same kind, plus a bit of work at the current level.\n", 167 | "\n", 168 | " * In the factorial example, *num*! is equal to (*num*-1)! multiplied by *num*. The smaller problem of the same kind is (*num*-1)! and multiplying by *num* is the bit of work at the current level.\n", 169 | " * In the gcd example, the gcd of *a* and *b* is the same as the gcd of *b* and *a % b*, which is a smaller problem of the same type. In this example no additional work at the current level is needed.\n", 170 | " * In the hailstone sequence example, the smaller problem of the same type is counting how many steps it takes to get from the next number in the sequence to 1. The bit of work at the current level is adding 1 to that result.\n" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "## Exercises" 178 | ] 179 | }, 180 | { 181 | "attachments": {}, 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "1. Write a **recursive** function called `countdown` that takes a positive integer parameter and returns a string that **counts down from that number to 1**. For example, if `5` is passed to the function, it should return the string `\"5 4 3 2 1\"`. You can use string concatenation in your recursive function to build up the return value." 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": null, 191 | "metadata": {}, 192 | "outputs": [], 193 | "source": [ 194 | "# Type code here\n" 195 | ] 196 | }, 197 | { 198 | "attachments": {}, 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "2. Write a **recursive** function called `countup` that takes a positive integer parameter and returns a string that **counts up from 1 to that number**. For example, if `5` is passed to the function, it should return the string `\"1 2 3 4 5\"`. You can use string concatenation in your recursive function to build up the return value." 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [ 211 | "# Type code here\n" 212 | ] 213 | }, 214 | { 215 | "attachments": {}, 216 | "cell_type": "markdown", 217 | "metadata": {}, 218 | "source": [ 219 | "3. Write a **recursive** function called `sum_countup` that takes an integer parameter and returns the sum of all the integers from 1 to that number. For example if the function is passed the value `5`, then it should return `15` because 1 + 2 + 3 + 4 + 5 = 15." 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": null, 225 | "metadata": {}, 226 | "outputs": [], 227 | "source": [ 228 | "# Type code here\n" 229 | ] 230 | } 231 | ], 232 | "metadata": { 233 | "kernelspec": { 234 | "display_name": "Python 3", 235 | "language": "python", 236 | "name": "python3" 237 | }, 238 | "language_info": { 239 | "codemirror_mode": { 240 | "name": "ipython", 241 | "version": 3 242 | }, 243 | "file_extension": ".py", 244 | "mimetype": "text/x-python", 245 | "name": "python", 246 | "nbconvert_exporter": "python", 247 | "pygments_lexer": "ipython3", 248 | "version": "3.7.16 (default, Jan 9 2023, 01:23:12) \n[GCC 11.3.0]" 249 | }, 250 | "vscode": { 251 | "interpreter": { 252 | "hash": "2a806d3aeacb674212bb9595bc81b7e00560d028deaf5d893b1185a2f7bac5ac" 253 | } 254 | } 255 | }, 256 | "nbformat": 4, 257 | "nbformat_minor": 4 258 | } 259 | -------------------------------------------------------------------------------- /01-lesson_notebooks/05c-Exercise_Solutions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercise Solutions" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Recursion" 15 | ] 16 | }, 17 | { 18 | "attachments": {}, 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "1. Write a **recursive** function called `countdown` that takes a positive integer parameter and returns a string that **counts down from that number to 1**. For example, if `5` is passed to the function, it should return the string `\"5 4 3 2 1\"`. You can use string concatenation in your recursive function to build up the return value." 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": null, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "def countdown(n: int) -> str:\n", 32 | " if n < 2:\n", 33 | " return str(n)\n", 34 | " return str(n)+\" \"+countdown(n-1)" 35 | ] 36 | }, 37 | { 38 | "attachments": {}, 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "2. Write a **recursive** function called `countup` that takes a positive integer parameter and returns a string that **counts up from 1 to that number**. For example, if `5` is passed to the function, it should return the string `\"1 2 3 4 5\"`. You can use string concatenation in your recursive function to build up the return value." 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "def countup(n: int) -> str:\n", 52 | " if n < 2:\n", 53 | " return str(n)\n", 54 | " \n", 55 | " return countup(n-1)+\" \"+str(n)" 56 | ] 57 | }, 58 | { 59 | "attachments": {}, 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "3. Write a **recursive** function called `sum_countup` that takes an integer parameter and returns the sum of all the integers from 1 to that number. For example if the function is passed the value `5`, then it should return `15` because 1 + 2 + 3 + 4 + 5 = 15." 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "def sum_countup(n: int) -> str:\n", 73 | " if n == 1:\n", 74 | " return 1\n", 75 | " \n", 76 | " return n + sum_countup(n-1)" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": {}, 82 | "source": [ 83 | "## Classes and Objects" 84 | ] 85 | }, 86 | { 87 | "attachments": {}, 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "1. Define a class named `HourlyWorker` that has three private data members: `_name`, `_ID`, and `_wage`. The class should have a docstring and an `init` method. The parameters to the `init` method should be in the order listed above." 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "class HourlyWorker:\n", 101 | " '''\n", 102 | " Hourly worker with a name, ID and wage.\n", 103 | " '''\n", 104 | " \n", 105 | " def __init__(self, name: str, ID: str, wage: float):\n", 106 | " self._name: str = name\n", 107 | " self._ID: str = ID\n", 108 | " self._wage: float = wage" 109 | ] 110 | }, 111 | { 112 | "attachments": {}, 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "2. Define a class named `Box` that has three private data members:`_length`, `_width`, and `_height`. The class should have a docstring and an `init` method. The parameters to the `init` method should be in the order listed above. The class should also have a method named `volume` that returns the *volume* of the `Box`, and a method named `surface_area` that returns the *surface area* of the `Box`." 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": null, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "class Box:\n", 126 | " '''\n", 127 | " A box with length, width and height\n", 128 | " '''\n", 129 | " \n", 130 | " def __init__(self, length: float, width: float, height: float):\n", 131 | " self._length = length\n", 132 | " self._width = width\n", 133 | " self._height = height\n", 134 | " \n", 135 | " def volume(self) -> float:\n", 136 | " return (self._length*self._width*self._height)\n", 137 | " \n", 138 | " def surface_area(self) -> float:\n", 139 | " l: float = self._length\n", 140 | " w: float = self._width\n", 141 | " h: float = self._height\n", 142 | " return (2 * ((l*w)+(l*h)+(w*h)))" 143 | ] 144 | } 145 | ], 146 | "metadata": { 147 | "kernelspec": { 148 | "display_name": "Python 3", 149 | "language": "python", 150 | "name": "python3" 151 | }, 152 | "language_info": { 153 | "codemirror_mode": { 154 | "name": "ipython", 155 | "version": 3 156 | }, 157 | "file_extension": ".py", 158 | "mimetype": "text/x-python", 159 | "name": "python", 160 | "nbconvert_exporter": "python", 161 | "pygments_lexer": "ipython3", 162 | "version": "3.7.16 (default, Jan 9 2023, 01:23:12) \n[GCC 11.3.0]" 163 | }, 164 | "vscode": { 165 | "interpreter": { 166 | "hash": "2a806d3aeacb674212bb9595bc81b7e00560d028deaf5d893b1185a2f7bac5ac" 167 | } 168 | } 169 | }, 170 | "nbformat": 4, 171 | "nbformat_minor": 4 172 | } 173 | -------------------------------------------------------------------------------- /01-lesson_notebooks/06c-Exercise_Solutions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercise Solutions" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## String Manipulation" 15 | ] 16 | }, 17 | { 18 | "attachments": {}, 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "1. Write a function called `last_char` that takes a string parameter and returns the last letter of that string." 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": null, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "def last_char(s: str) -> str:\n", 32 | " return s[-1]" 33 | ] 34 | }, 35 | { 36 | "attachments": {}, 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "2. Write a function called `midstring` that takes a string parameter and returns a copy of that string minus its first and last letters. If the string passed in has only has 1 or 2 letters, the function should return the empty string `\"\"`." 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "def midstring(s: str) -> str:\n", 50 | " return s[1:-1]" 51 | ] 52 | }, 53 | { 54 | "attachments": {}, 55 | "cell_type": "markdown", 56 | "metadata": {}, 57 | "source": [ 58 | "3. Write a function called `sort_two_strings` that takes two string parameters and returns a single string of both of them in dictionary order, ignoring case. For example, if the strings `\"aardvark\"` and `\"Zebra\"` are passed, it should return `\"aardvark Zebra\"`." 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": null, 64 | "metadata": {}, 65 | "outputs": [], 66 | "source": [ 67 | "def sort_two_strings(s1: str, s2: str) -> str:\n", 68 | " if s1.lower() < s2.lower():\n", 69 | " return s1+\" \"+s2\n", 70 | " else:\n", 71 | " return s2+\" \"+s1" 72 | ] 73 | }, 74 | { 75 | "attachments": {}, 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "4. A palindrome is a string that reads the same forward or backward. Write a function called `is_palindrome` that takes a string parameter and returns `True` if that string is a palindrome, but returns `False` otherwise." 80 | ] 81 | }, 82 | { 83 | "cell_type": "code", 84 | "execution_count": null, 85 | "metadata": {}, 86 | "outputs": [], 87 | "source": [ 88 | "def is_palindrome(s: str) -> str:\n", 89 | " return s[::-1] == s" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "## Lists" 97 | ] 98 | }, 99 | { 100 | "attachments": {}, 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "1. Write a function named `every_other` that takes as a parameter a list and returns a list that only contains every other element starting with the first one. For example, if the original list is `[7, \"joe\", \"apple\", 9.81, False]`, then the new list should be `[7, \"apple\", False]`. Use slicing." 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "def every_other(mixed_list: list[object]):\n", 114 | " return mixed_list[::2]" 115 | ] 116 | }, 117 | { 118 | "attachments": {}, 119 | "cell_type": "markdown", 120 | "metadata": {}, 121 | "source": [ 122 | "2. Write a function named `array_sum` that takes as a parameter a list of strings and returns the total number of characters in all the strings." 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": null, 128 | "metadata": {}, 129 | "outputs": [], 130 | "source": [ 131 | "def array_sum(word_list: list[str]) -> int:\n", 132 | " count: int = 0\n", 133 | " word: str\n", 134 | " ch: str\n", 135 | " for word in word_list:\n", 136 | " for ch in word:\n", 137 | " count += 1\n", 138 | " return count" 139 | ] 140 | }, 141 | { 142 | "attachments": {}, 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "3. Write a function named `rev_string_list` that takes as a parameter a list of strings and returns a list that contains the reverse of each of those strings. **Use a list comprehension**." 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": {}, 153 | "outputs": [ 154 | { 155 | "data": { 156 | "text/plain": [ 157 | "['eno', 'owt', 'eerht']" 158 | ] 159 | }, 160 | "execution_count": 2, 161 | "metadata": {}, 162 | "output_type": "execute_result" 163 | } 164 | ], 165 | "source": [ 166 | "def rev_string_list(string_list: list[str]) -> list[str]:\n", 167 | " return [s[::-1] for s in string_list]" 168 | ] 169 | }, 170 | { 171 | "attachments": {}, 172 | "cell_type": "markdown", 173 | "metadata": {}, 174 | "source": [ 175 | "4. Write a function named `contain_string` that takes as a parameter a list of strings and the target string, and returns a list of the strings from the original list that contain the target string. Use a list comprehension. As an example, if the function call is `contain_string([\"cats\", \"tacks\", \"scat\", \"stack\"], \"cat\")`, then the return value should be `[\"cats\", \"scat\"]`, because `\"cats\"` and `\"scat\"` both contain `\"cat\"`." 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "def contain_string(string_list: list[str], target_string: list[str]) -> list[str]:\n", 185 | " return [s for s in string_list if target_string in s]\n", 186 | "\n", 187 | "contain_string(['cats', 'tacks', 'scat', 'stack'], 'cat')" 188 | ] 189 | }, 190 | { 191 | "cell_type": "code", 192 | "execution_count": null, 193 | "metadata": {}, 194 | "outputs": [], 195 | "source": [] 196 | } 197 | ], 198 | "metadata": { 199 | "kernelspec": { 200 | "display_name": "Python 3", 201 | "language": "python", 202 | "name": "python3" 203 | }, 204 | "language_info": { 205 | "codemirror_mode": { 206 | "name": "ipython", 207 | "version": 3 208 | }, 209 | "file_extension": ".py", 210 | "mimetype": "text/x-python", 211 | "name": "python", 212 | "nbconvert_exporter": "python", 213 | "pygments_lexer": "ipython3", 214 | "version": "3.12.6" 215 | }, 216 | "vscode": { 217 | "interpreter": { 218 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 219 | } 220 | } 221 | }, 222 | "nbformat": 4, 223 | "nbformat_minor": 4 224 | } 225 | -------------------------------------------------------------------------------- /01-lesson_notebooks/07c-Exercise_Solutions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercise Solutions" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Tuples and Mutability" 15 | ] 16 | }, 17 | { 18 | "attachments": {}, 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "1. Does the following program contradict the idea that tuples are immutable? Why or why not?\n", 23 | "\n", 24 | "```python\n", 25 | "def tuple_madness(tup):\n", 26 | " return tup[1:]\n", 27 | "```" 28 | ] 29 | }, 30 | { 31 | "attachments": {}, 32 | "cell_type": "markdown", 33 | "metadata": {}, 34 | "source": [ 35 | "**Ans:** No, `tuple_madness` returns a new tuple that contains the same items in `tup` except the first. `tup` is not modified." 36 | ] 37 | }, 38 | { 39 | "attachments": {}, 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "2. Write a function named `insert_front` that takes as a parameter a list and a value to add at the front of the list. It should not return anything - it should mutate the original list. For example, if the arguments passed to the function are `[9, -55, 37]` and `\"bob\"`, then after calling the function, the list should now be `[\"bob\", 9, -55, 37]`." 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "def insert_front(a_list: list[object], new_element: object) -> None:\n", 53 | " a_list[0:0] = [new_element]" 54 | ] 55 | }, 56 | { 57 | "attachments": {}, 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "3. Write a function named `delete_last` that takes as a parameter a list and removes the last element from that list. It should not return anything - it should mutate the original list. For example, if the list passed to the function is `[7, \"joe\", \"apple\", 9.81, False]`, then after calling the function, the list should be `[7, \"joe\", \"apple\", 9.81]`." 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": null, 67 | "metadata": {}, 68 | "outputs": [], 69 | "source": [ 70 | "def delete_last(some_list: list[object]) -> None:\n", 71 | " del some_list[-1]" 72 | ] 73 | }, 74 | { 75 | "cell_type": "markdown", 76 | "metadata": {}, 77 | "source": [ 78 | "## Object References and Identity" 79 | ] 80 | }, 81 | { 82 | "attachments": {}, 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "1. Is it possible to have variables be equal, but not refer to the same object? Is it possible to have variables refer to the same object, but not be equal? Explain both answers.\n", 87 | "\n", 88 | "_Ans:_ It is possible to have variables be equal, but not refer to the same object. For example, you can have `num_1` referencing an object with the value 7, and `num_2` referencing a different object with the value 7. It's not possible to have variables refer to the same object, but not be equal. For example, if `num_1` and `num_2` both reference the same object that has a value of -3, then `num_1` and `num_2` will be equal." 89 | ] 90 | }, 91 | { 92 | "attachments": {}, 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "2. If `nums_1` and `nums_2` refer to the same list object, and you delete the first element of `nums_1`, then that affects `nums_2`, because they're the same list. Why is this not true if `nums_1` and `nums_2` refer to the same **tuple** object?" 97 | ] 98 | }, 99 | { 100 | "cell_type": "markdown", 101 | "metadata": {}, 102 | "source": [ 103 | "_Ans:_ It's because lists are a mutable type, but tuples are an immutable type." 104 | ] 105 | }, 106 | { 107 | "attachments": {}, 108 | "cell_type": "markdown", 109 | "metadata": {}, 110 | "source": [ 111 | "3. When does rebinding of a variable happen?\n", 112 | "\n", 113 | "*Ans:* It happens when a new value is assigned to it. For example:\n", 114 | "\n", 115 | "```python\n", 116 | "zip_code = \"97331\"\n", 117 | "zip_code = \"98225\"\n", 118 | "```\n", 119 | "\n", 120 | "The first line creates a string object with the value `\"97331\"` and binds `zip_code` to that object. The second line creates a new string object with the value `\"98225\"` and rebinds `zip_code` to that new object.\n" 121 | ] 122 | } 123 | ], 124 | "metadata": { 125 | "kernelspec": { 126 | "display_name": "Python 3", 127 | "language": "python", 128 | "name": "python3" 129 | }, 130 | "language_info": { 131 | "codemirror_mode": { 132 | "name": "ipython", 133 | "version": 3 134 | }, 135 | "file_extension": ".py", 136 | "mimetype": "text/x-python", 137 | "name": "python", 138 | "nbconvert_exporter": "python", 139 | "pygments_lexer": "ipython3", 140 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 141 | }, 142 | "vscode": { 143 | "interpreter": { 144 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 145 | } 146 | } 147 | }, 148 | "nbformat": 4, 149 | "nbformat_minor": 4 150 | } 151 | -------------------------------------------------------------------------------- /01-lesson_notebooks/08a-Dictionaries.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Dictionaries" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Dictionary Data Types" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "Another data type that's built-in to Python is called a dictionary. A dictionary is a way of storing key-value pairs. For example:" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "state_capitals = {\n", 31 | " \"Washington\" : \"Olympia\",\n", 32 | " \"Oregon\" : \"Salem\",\n", 33 | " \"Idaho\" : \"Boise\",\n", 34 | " \"Montana\" : \"Helena\"\n", 35 | "}" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "The first column has the keys and the second column has their associated values (I added extra spaces to align the columns and colons just for ease of reading - it's not required). Each key can only have one value, but the same value can be used for multiple keys. Dictionaries, like lists, are **mutable**. However, unlike lists, you cannot index into a dictionary by the position of an element. You still use the square bracket notation, but instead of a positional index, you give the key that you want the associated value of." 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "state_capitals[\"Idaho\"]" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "state_capitals[\"Washington\"]" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "It's easy to add a new key-value pair:" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "state_capitals[\"Florida\"] = \"Orlando\"\n", 77 | "state_capitals[\"Florida\"]" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "Or to change an existing key-value pair:" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "state_capitals[\"Florida\"] = \"Tallahassee\"\n", 94 | "state_capitals[\"Florida\"]" 95 | ] 96 | }, 97 | { 98 | "attachments": {}, 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "You can delete an entry using `del`:" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "del state_capitals[\"Florida\"]\n", 112 | "state_capitals[\"Florida\"]" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "If you print a dictionary, it will list all of its key-value pairs, in no particular order:" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": null, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "print(state_capitals)" 129 | ] 130 | }, 131 | { 132 | "attachments": {}, 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "## Type hinting with dictionaries as of Python `3.11.1`\n", 137 | "\n", 138 | "Type hinting in Python can be used to specify the expected types of variables, including dictionaries. In the case of the state_capitals dictionary, you can add type hinting as follows:\n", 139 | "\n", 140 | "```python\n", 141 | "state_capitals: dict[str, str] = {\n", 142 | " \"Washington\" : \"Olympia\",\n", 143 | " \"Oregon\" : \"Salem\",\n", 144 | " \"Idaho\" : \"Boise\",\n", 145 | " \"Montana\" : \"Helena\"\n", 146 | "}\n", 147 | "```\n", 148 | "\n", 149 | "The `state_capitals` variable is declared as a `dict[str, str]`, indicating that it is a dictionary with keys of type `str` and values of type `str`." 150 | ] 151 | }, 152 | { 153 | "attachments": {}, 154 | "cell_type": "markdown", 155 | "metadata": {}, 156 | "source": [ 157 | "The keys in a dictionary must be immutable, but the associated values can be of any type. The keys are not required to all be the same type. You can even nest dictionaries. Here's an example of a dictionary with some string values and an integer value. For mixing expected types, we can use the `|` operator." 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "capybara: dict[str, str | int] = {\n", 167 | " \"scientific name\" : \"Hydrochoerus hydrochaeris\", \n", 168 | " \"lifespan in years\" : 10, \n", 169 | " \"classification\" : \"rodent\", \n", 170 | " \"size\" : \"unusual\"\n", 171 | "}" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "You can declare an empty dictionary like so:" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": null, 184 | "metadata": {}, 185 | "outputs": [], 186 | "source": [ 187 | "empty_dict = {}" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "You can use *in* and *not in* to test whether a key is in a dictionary:" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "metadata": {}, 201 | "outputs": [], 202 | "source": [ 203 | "\"classification\" in capybara\n", 204 | "\"genus\" in capybara" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "You can use *len* to get the number of key-value pairs in a dictionary:" 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "len(capybara)" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": {}, 226 | "source": [ 227 | "You can use a for loop to iterate through a dictionary." 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": null, 233 | "metadata": {}, 234 | "outputs": [], 235 | "source": [ 236 | "attribute: str\n", 237 | "for attribute in capybara:\n", 238 | " print(attribute)" 239 | ] 240 | }, 241 | { 242 | "attachments": {}, 243 | "cell_type": "markdown", 244 | "metadata": {}, 245 | "source": [ 246 | "When you iterate through a dictionary, python by default guarantees to return keys in the same order they were created.\n", 247 | "\n", 248 | "The clear method makes a dictionary empty:" 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": null, 254 | "metadata": {}, 255 | "outputs": [], 256 | "source": [ 257 | "capybara.clear()\n", 258 | "len(capybara)" 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "metadata": {}, 264 | "source": [ 265 | "As with lists, there are other operators, functions and methods available for working with dictionaries." 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "## Exercises" 273 | ] 274 | }, 275 | { 276 | "attachments": {}, 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "1. Make a dictionary called `eng_to_span` where the keys are the English words `\"one\"` through `\"ten\"`, and the corresponding values are their Spanish translations." 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": null, 286 | "metadata": {}, 287 | "outputs": [], 288 | "source": [ 289 | "# Type code here\n" 290 | ] 291 | }, 292 | { 293 | "attachments": {}, 294 | "cell_type": "markdown", 295 | "metadata": {}, 296 | "source": [ 297 | "2. Using the dictionary from #1, write a loop that prints out both the key and value of each key-value pair, for example the first iteration of the loop should print `\"one\"` `\"uno\"`." 298 | ] 299 | }, 300 | { 301 | "cell_type": "code", 302 | "execution_count": null, 303 | "metadata": {}, 304 | "outputs": [], 305 | "source": [ 306 | "# Type code here\n" 307 | ] 308 | }, 309 | { 310 | "attachments": {}, 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "3. Write a function named `some_squares` that takes a positive integer parameter and returns a dictionary where the keys are the integers from `1` through the value of the parameter, and the corresponding values are the squares of those integers. For example, if it's passed `3`, then the dictionary should contain the following key-value pairs: `{1: 1, 2: 4, 3: 9}`." 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": null, 320 | "metadata": {}, 321 | "outputs": [], 322 | "source": [ 323 | "# Type code here\n" 324 | ] 325 | } 326 | ], 327 | "metadata": { 328 | "kernelspec": { 329 | "display_name": "Python 3", 330 | "language": "python", 331 | "name": "python3" 332 | }, 333 | "language_info": { 334 | "codemirror_mode": { 335 | "name": "ipython", 336 | "version": 3 337 | }, 338 | "file_extension": ".py", 339 | "mimetype": "text/x-python", 340 | "name": "python", 341 | "nbconvert_exporter": "python", 342 | "pygments_lexer": "ipython3", 343 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 344 | }, 345 | "vscode": { 346 | "interpreter": { 347 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 348 | } 349 | } 350 | }, 351 | "nbformat": 4, 352 | "nbformat_minor": 4 353 | } 354 | -------------------------------------------------------------------------------- /01-lesson_notebooks/08c-Exercise_Solutions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercise Solutions" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Dictionaries" 15 | ] 16 | }, 17 | { 18 | "attachments": {}, 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "1. Make a dictionary called `eng_to_span` where the keys are the English words `\"one\"` through `\"ten\"`, and the corresponding values are their Spanish translations." 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": null, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "eng_to_span: dict[str, str] = {\"one\": \"uno\",\n", 32 | " \"two\": \"dos\",\n", 33 | " \"three\": \"tres\",\n", 34 | " \"four\": \"cuatro\",\n", 35 | " \"five\": \"cinco\",\n", 36 | " \"six\": \"seis\",\n", 37 | " \"seven\": \"siete\",\n", 38 | " \"eight\": \"ocho\",\n", 39 | " \"nine\": \"nueve\",\n", 40 | " \"ten\": \"diez\"}" 41 | ] 42 | }, 43 | { 44 | "attachments": {}, 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "2. Using the dictionary from #1, write a loop that prints out both the key and value of each key-value pair, for example the first iteration of the loop should print `\"one\"` `\"uno\"`." 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": null, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "eng_to_span: dict[str, str] = {\"one\": \"uno\",\n", 58 | " \"two\": \"dos\",\n", 59 | " \"three\": \"tres\",\n", 60 | " \"four\": \"cuatro\",\n", 61 | " \"five\": \"cinco\",\n", 62 | " \"six\": \"seis\",\n", 63 | " \"seven\": \"siete\",\n", 64 | " \"eight\": \"ocho\",\n", 65 | " \"nine\": \"nueve\",\n", 66 | " \"ten\": \"diez\"}\n", 67 | "word: str\n", 68 | "for word in eng_to_span:\n", 69 | " print(word, eng_to_span[word])" 70 | ] 71 | }, 72 | { 73 | "attachments": {}, 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "3. Write a function named `some_squares` that takes a positive integer parameter and returns a dictionary where the keys are the integers from `1` through the value of the parameter, and the corresponding values are the squares of those integers. For example, if it's passed `3`, then the dictionary should contain the following key-value pairs: `{1: 1, 2: 4, 3: 9}`." 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [ 86 | "def some_squares(n: int) -> dict[int, int]:\n", 87 | " d: dict[int, int] = {}\n", 88 | " i: int\n", 89 | " for i in range(1, n+1):\n", 90 | " d[i] = i*i \n", 91 | " \n", 92 | " return d" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": {}, 98 | "source": [ 99 | "## Sets" 100 | ] 101 | }, 102 | { 103 | "attachments": {}, 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "1. Write your own function called \"unionize\" for finding the union of two sets. Your function should take as parameters two sets, and return a new set that is the union of those two sets. Do not use Python's built-in union functionality." 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 1, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [ 116 | "def unionize(s1: set[object], s2: set[object]):\n", 117 | " result: Set = set(object)\n", 118 | " i: object\n", 119 | " for i in s1:\n", 120 | " result.add(i)\n", 121 | " j: object \n", 122 | " for j in s2:\n", 123 | " result.add(j)\n", 124 | " \n", 125 | " return result" 126 | ] 127 | }, 128 | { 129 | "attachments": {}, 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "2. Write your own function called `intersect` for finding the intersection of two sets. Your function should take as parameters two sets, and return a new set that is the intersection of those two sets. Do not use Python's built-in intersection functionality." 134 | ] 135 | }, 136 | { 137 | "cell_type": "code", 138 | "execution_count": 2, 139 | "metadata": {}, 140 | "outputs": [], 141 | "source": [ 142 | "def intersect(s1: set[object], s2: set[object]):\n", 143 | " i: object\n", 144 | " return {i for i in s1 if i in s2}" 145 | ] 146 | }, 147 | { 148 | "attachments": {}, 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "3. Write your own function called `sym_diff` for finding the symmetric difference of two sets. Your function should take as parameters two sets, and return a new set that is the symmetric difference of those two sets. Do not use Python's built-in symmetric difference functionality." 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": null, 158 | "metadata": {}, 159 | "outputs": [], 160 | "source": [ 161 | "def sym_diff(s1: set[object], s2[object]):\n", 162 | " s3: set[object] = s1 | s2\n", 163 | " i: object\n", 164 | " return set(i for i in s3 if ((i not in s1) or (i not in s2)))" 165 | ] 166 | } 167 | ], 168 | "metadata": { 169 | "kernelspec": { 170 | "display_name": "Python 3", 171 | "language": "python", 172 | "name": "python3" 173 | }, 174 | "language_info": { 175 | "codemirror_mode": { 176 | "name": "ipython", 177 | "version": 3 178 | }, 179 | "file_extension": ".py", 180 | "mimetype": "text/x-python", 181 | "name": "python", 182 | "nbconvert_exporter": "python", 183 | "pygments_lexer": "ipython3", 184 | "version": "3.11.1" 185 | }, 186 | "vscode": { 187 | "interpreter": { 188 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 189 | } 190 | } 191 | }, 192 | "nbformat": 4, 193 | "nbformat_minor": 4 194 | } 195 | -------------------------------------------------------------------------------- /02-IDE_exercises/01-project/README.md: -------------------------------------------------------------------------------- 1 | # project-01 2 | 3 | This project will test that you can create and run a python module. 4 | 5 | Create a Python file named my_color.py in the same directory as this `README`. Type the following code into the file, but with **your name** and the **current date**: 6 | ``` 7 | # Author: Brandon Hoffman 8 | # Date: 04/15/1865 9 | # Description: Asks the user for their favorite color and then 10 | # prints out a statement with the variable 11 | 12 | fave_color = input("Please enter your favorite color: ") 13 | print("Your favorite color is " + fave_color + ".") 14 | ``` 15 | Now save the file ("File/Save All") and run it. The program should ask you to enter the name of your favorite color, and after you do, it will print out "Your favorite color is \." 16 | -------------------------------------------------------------------------------- /02-IDE_exercises/02a-project/README.md: -------------------------------------------------------------------------------- 1 | # project-02a 2 | 3 | Write a program in Python to input 5 numbers from keyboard and then calculates the average of those numbers. The program should accept negative as well as negative input and should match the following format when it is executed: 4 | ``` 5 | Please enter five numbers. 6 | -5.4 7 | 2.1 8 | 7.0 9 | 134.8 10 | -20.0 11 | The calculated average of those numbers is: 12 | 23.7 13 | ``` 14 | The file should be named: calculate_average.py 15 | -------------------------------------------------------------------------------- /02-IDE_exercises/02b-project/README.md: -------------------------------------------------------------------------------- 1 | # project-02b 2 | 3 | Write a Python program to convert from Celsius to Fahrenheit using the following fomular: 4 | 5 | F = (9/5)C + 32 6 | 7 | where F is Fahrenheit and C is Celsius. The program should take an input from the user in 8 | Celsius and outputs the corresponding temperature in Fahrenheit. When you run your program, it should match the following format: 9 | 10 | ``` 11 | Please enter the temperature in Celsius. 12 | 34.5 13 | The corresponding temperature in Fahrenheit is: 14 | 94.1 15 | ``` 16 | Your result only needs to match to 7 decimal places and does not to be exact. For example, 13.0999999999 is considered correct. 17 | 18 | The file should be named: temp_conversion.py 19 | -------------------------------------------------------------------------------- /02-IDE_exercises/02c-project/README.md: -------------------------------------------------------------------------------- 1 | # project-02c 2 | 3 | Write a Python program that prompts the user for a (integer) number of cents, from 0 to 99, and calculates the least number of coins required to make change. When your program is executed, it should match the following format: 4 | ``` 5 | Please enter an amount between 0 and 99 cents. 6 | 87 7 | Your change will be: 8 | Q: 3 9 | D: 1 10 | N: 0 11 | P: 2 12 | ``` 13 | Hint: You may find the mod operator (%) useful. 14 | * 1 quarter = 25 cents 15 | * 1 dime = 10 cents 16 | * 1 nickel = 5 cents 17 | * 1 penny = 1 cent 18 | 19 | The file must be named: coin_change.py 20 | -------------------------------------------------------------------------------- /02-IDE_exercises/03a-project/README.md: -------------------------------------------------------------------------------- 1 | # project-03a 2 | 3 | Write a Python program that asks the users how many number they would like to enter, where the users need to enter at least one number, and then prompt the user to enter that many numbers. Once the user has entered all the numbers, the program should output the largest and smallest of those numbers 4 | (You are not permitted to use any data structures or any materials we have not covered). The program should follow this format when it is executed: 5 | ``` 6 | How many numbers would you like to enter? 7 | 3 8 | Please enter 3 numbers. 9 | 3 10 | 5 11 | 7 12 | 13 | min: 3 14 | max: 7 15 | ``` 16 | Hints: How many numbers do you have to keep track at a time? 17 | If someone were reading a list of numbers to you, and you had to tell them the max and min at the end, how would you do it? 18 | How should you initialize your variables? What happens if the user only enters one integer? 19 | 20 | The file must be named: min_max_number.py 21 | -------------------------------------------------------------------------------- /02-IDE_exercises/03b-project/README.md: -------------------------------------------------------------------------------- 1 | # project-03b 2 | 3 | Write a Python program that prompts the user to enter a positive integer, then output all the positive integers that divisible by that number, including itself and 1, in ascending order. 4 | The program should match the following format when it is executed: 5 | ``` 6 | Please enter a positive integer: 12 7 | The factors of 12 are: 8 | 1 9 | 2 10 | 3 11 | 4 12 | 6 13 | 12 14 | ``` 15 | The file should be named: find_factors.py 16 | -------------------------------------------------------------------------------- /02-IDE_exercises/03c-project/README.md: -------------------------------------------------------------------------------- 1 | # project-03c 2 | 3 | Write a Python program that takes in an integer that a player will attempt to guess. The program should display "too high" if the guess is higher and "too lower" if the guess is lower. The program will not stop unless the player guesses the correct integer and print out the number of guesses the player took. The program should executed as follow: 4 | 5 | Enter the number for the player to guess. 6 | -10 7 | Enter your guess. 8 | 10 9 | Too high - try again: 10 | 5 11 | Too high - try again: 12 | -200 13 | Too low - try again: 14 | -10 15 | You guessed it in 4 tries. 16 | ``` 17 | If the user guesses the number in 1 try, then your program should print "You guessed it in 1 try." 18 | 19 | The file should be named: guess_num.py 20 | -------------------------------------------------------------------------------- /02-IDE_exercises/04a-project/README.md: -------------------------------------------------------------------------------- 1 | # project-04a 2 | 3 | **Remember that, as stated in the Code Style Guidelines, all functions in all assignments must have a docstring.** 4 | 5 | Use the following formula to determine the distance an objects falls in an amount of time due to gravity 6 | 7 | d = (1/2)gt2 8 | 9 | where d is the distance in meters, g is 9.8, and t is the time in seconds. 10 | Write a Python function called distance_fallen() that takes time (in second) as an argument then calculates the distance the object has fallen during that time using the formula above. 11 | 12 | Here's a simple example of how your distance_fallen() function could be used: 13 | ``` 14 | dist = distance_fallen(4.5) 15 | print(dist) 16 | ``` 17 | 18 | The file should be named: distance_fallen.py 19 | -------------------------------------------------------------------------------- /02-IDE_exercises/04b-project/README.md: -------------------------------------------------------------------------------- 1 | # project-04b 2 | 3 | The first and second numbers in the Fibonacci sequence are both 1. 4 | After that, each subsequent number is the sum of the two previous numbers. 5 | The first several numbers in the sequence are: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 6 | Write a Python function called fibonacci(number) that takes a positive integer parameter and returns the number at that position of the Fibonacci sequence. 7 | For example fib(1) = 1, fib(3) = 2, fib(5) = 5, etc. 8 | Your function does not need to print anything out - just return a value. 9 | 10 | For example, your function could be use as such: 11 | ``` 12 | term = fibonacci(17) 13 | ``` 14 | 15 | You cannot use recursion, since we haven't covered that technique. That means that for this assignment you cannot have your function call itself. 16 | 17 | The file should be named fibonacci.py 18 | -------------------------------------------------------------------------------- /02-IDE_exercises/04c-project/README.md: -------------------------------------------------------------------------------- 1 | # project-04c 2 | 3 | A hailstone sequence begins with a positive integer. 4 | If the integer is even, divide it by two to get the next integer in the sequence, but if it is odd, multiply it by three and add one to get the next integer in the sequence. 5 | Then you use the value you just generated to find the next value, according to the same rules. 6 | For example, if our initial number is 3, the subsequent numbers will be: 10, 5, 16, 8, 4, 2, 1. 7 | 8 | Write a Python function called hailstone_step(num) that takes a positive number as parameter for the initial number of a hailstone sequence and returns how many steps it takes to reach 1, you must stop once you have reached 1. 9 | If the starting integer is 1, the return value should be 0, since it takes no steps to reach 1. 10 | For example, if the starting number is 3, then the sequence would go: 3, 10, 5, 16, 8, 4, 2, 1, and the result should be 7, since it took 7 steps to reach 1. 11 | Don't print anything out, just return a value 12 | 13 | For example, your function could be used like this: 14 | ``` 15 | answer = hailstone_step(1000) 16 | print(answer) 17 | ``` 18 | 19 | You cannot use recursion, since we haven't covered that technique. 20 | 21 | The file should be named: **hailstone_step.py** 22 | -------------------------------------------------------------------------------- /02-IDE_exercises/05a-project/README.md: -------------------------------------------------------------------------------- 1 | # project-05a 2 | 3 | Write a **recursive** Python function named multiply that takes two positive integers as arguments and returns the product of those two numbers. 4 | Your program can not use multiplication - it has to use addition to find the result. To get your thinking on the right track: 5 | ``` 6 | 7 * 4 = 7 + (7 * 3) 7 | 7 * 3 = 7 + (7 * 2) 8 | 7 * 2 = 7 + (7 * 1) 9 | 7 * 1 = 7 10 | So, 7 * 4 = 7 + (7 + (7 + (7))) 11 | ``` 12 | 13 | Your function cannot use loop 14 | 15 | The file should be named: multiply_recur.py 16 | -------------------------------------------------------------------------------- /02-IDE_exercises/05b-project/README.md: -------------------------------------------------------------------------------- 1 | # project-05b 2 | 3 | 4 | Write a Python class called Taxicab that has three **private** instance variables: 5 | one variable for x-coordinate, y-coordinate, 6 | and odometer reading of the Taxicab. 7 | The class should have an init method that takes two parameters and uses them to initialize the coordinates, and the odometer to zero 8 | The class should have getter methods for each variable for each data member: get_x_coord, get_y_coord, and get_odometer. 9 | The class should have a method called move_x that takes a parameter that tells how far the Taxicab should shift left or right and move_y to tell how far the Taxicab shift up or down 10 | For example, the Taxicab class might be used as follows: 11 | ``` 12 | cab = Taxicab(3, -8) # creates a Taxicab object at coordinates (3, -8) 13 | cab.move_x(4) # moves cab 4 units "right" 14 | cab.move_y(-5) # moves cab 5 units "down" 15 | cab.move_x(-2) # moves cab 2 unit "left" 16 | print(cab.get_odometer()) # prints the current odometer reading 17 | ``` 18 | 19 | The file should be named: Taxicab.py -------------------------------------------------------------------------------- /02-IDE_exercises/06a-project/README.md: -------------------------------------------------------------------------------- 1 | # project-06a 2 | 3 | Write a Python function named find_median that takes a list of number as argument and return the median of those numbers. 4 | You will need to sort the list in order to find the median. Please look up on how to find median if you're not familiar with the logic 5 | 6 | For example, it could be used like this: 7 | ``` 8 | list_of_nums = [13,7,-3,82,4] 9 | result = find_median(list_of_nums) 10 | ``` 11 | 12 | The file should be named: find_median.py 13 | -------------------------------------------------------------------------------- /02-IDE_exercises/06b-project/README.md: -------------------------------------------------------------------------------- 1 | # project-06b 2 | 3 | Write a Python function named add_surname that takes a list of first names as parameter and return a list that contains only those names that start with a "K", but with the surname "Hoffman" added to each one, with a space between the first and last names. 4 | You may assume that all names in the list begin with a capital letter. 5 | For example, if the original list is: 6 | ``` 7 | ["Kiki", "Krystal", "Pavel", "MaryKay", "Annie", "Koala"] 8 | ``` 9 | Then the list that is returned should be: 10 | ``` 11 | ['Kiki Hoffman', 'Krystal Hoffman', 'Koala Hoffman'] 12 | ``` 13 | The file should be named: add_surname.py 14 | -------------------------------------------------------------------------------- /02-IDE_exercises/06c-project/README.md: -------------------------------------------------------------------------------- 1 | # project-06c 2 | 3 | Write a Python class called Person that has two private instance variables - the person's name and age. 4 | 5 | It should have an init method that takes two values and initialize them. It should have a get_age method. 6 | 7 | Write a separate Python function (separated from the Person class) called std_dev that takes as a parameter a list of Person objects and returns the standard deviation of all their ages 8 | 9 | To calculate the standard deviation, you'll need to take a square root or exponent of 0.5. 10 | 11 | For example, the result of 9^(0.5) would be 3.0. Python does have a specific sqrt() function, but that involves importing a module, which we haven't covered yet. 12 | 13 | Here's a simple example of how your class and function could be used: 14 | ``` 15 | person1 = Person("Katie", 73) 16 | person1 = Person("Tran", 24) 17 | person1 = Person("Hanna", 48) 18 | person_list = [person1, person1, person1] 19 | answer = std_dev(person_list) 20 | ``` 21 | 22 | The file should be named: std_dev.py 23 | -------------------------------------------------------------------------------- /02-IDE_exercises/07a-project/README.md: -------------------------------------------------------------------------------- 1 | # project-07a 2 | 3 | Write a Python function called square_list that takes a list of numbers as parameter and replaces each value with the square of that value. 4 | It should not return anything - it should mutate the original list. 5 | 6 | Your function could be used like this: 7 | ``` 8 | nums = [7, -3, 12, 9] 9 | square_list(nums) 10 | print(nums) # This should print [49, 9, 144, 81] 11 | ``` 12 | 13 | The file should be named: square_list.py 14 | -------------------------------------------------------------------------------- /02-IDE_exercises/07b-project/README.md: -------------------------------------------------------------------------------- 1 | # project-07b 2 | 3 | Write a Python function named reverse_list that takes a list of number as parameter and reverses the order of the elements in that list. 4 | It should not return anything - it should mutate the original list and your function must not use any slicing. 5 | 6 | Your function could be used like this: 7 | ``` 8 | vals = [2, -5, 10, 9] 9 | reverse_list(vals) 10 | print(vals) # This should print [9, 10, -5, 2] 11 | ``` 12 | 13 | The file should be named: reverse_list.py 14 | -------------------------------------------------------------------------------- /02-IDE_exercises/08a-project/README.md: -------------------------------------------------------------------------------- 1 | # project-08a 2 | 3 | Write a Python function called count_letters that takes a string as a parameter and returns a dictionary that tabulates how many of each letter is in that string. 4 | The string can contain characters other than letters, empty string, lower and upper-case letter, but the function should only count letter and only count once regardless of upper-case or lower-case. 5 | The keys of the dictionary should be upper-case letters. 6 | For example, if the string is 7 | ``` 8 | "AaBb" 9 | ``` 10 | then the dictionary that is returned should contain these key-value pairs: 11 | ``` 12 | {'A': 2, 'B': 2} 13 | ``` 14 | 15 | we haven't covered the build-in function isalpha() , so don't use it. 16 | 17 | The file should be named: count_letters.py 18 | -------------------------------------------------------------------------------- /02-IDE_exercises/08b-project/README.md: -------------------------------------------------------------------------------- 1 | # project-08b 2 | 3 | Write a Python function called words_in_both that takes two strings as parameters and returns a result set of the words appeared in the two input strings. 4 | You can assume all characters are letters or spaces and capitalization shouldn't matter: "to" or "To" is counted as the same word. 5 | The words in the result set should be all in lowercase. 6 | For example, if one string contains "on", and the other string contains "ON", then the set should contain "on". 7 | 8 | You can use Python's split() funciton. For example: 9 | ``` 10 | sentence = 'Not the comfy chair!' 11 | print(sentence.split()) 12 | ['Not', 'the', 'comfy', 'chair!'] 13 | ``` 14 | 15 | Here's one simple example of how words_in_both() might be used: 16 | ``` 17 | common_words = words_in_both("She's a jack of all trades", 'Jack was tallest of all') 18 | ``` 19 | 20 | The file should be named: words_in_both.py 21 | -------------------------------------------------------------------------------- /02-IDE_exercises/08c-project/README.md: -------------------------------------------------------------------------------- 1 | # project-08c 2 | 3 | Write a Python class called Employee that has **private** variables for an employee's name, ID_number, salary, and email_address. The class should have an init class to initialize the object and getter methods for each data variables. 4 | 5 | Write a separate Python function (separate from the Employee class) called **make_employee_dict** that takes in a list of names, 6 | a list of ID numbers, a list of salaries and a list of email addresses (which are all the same length) as parameters. 7 | The function should iterate through each list to create Employee objects and add these objects to the dictionary where the key is the ID number and the value for that key is the whole Employee object. 8 | The function should return the resulting dictionary. 9 | 10 | For example, it could be used like this: 11 | ``` 12 | emp_names = ["Tuan", "Rachel", "Brandon"] 13 | emp_ids = ["1000", "1001", "1002"] 14 | emp_sals = [30, 35, 28] 15 | emp_emails = ["Tuan@aol.com", "Rachel@aol.com", "Brandon@aol.com"] 16 | result = make_employee_dict(emp_names, emp_ids, emp_sals, emp_emails) 17 | print(result["100"].get_name()) 18 | ``` 19 | 20 | Remember in your testing that printing an object of a user-defined class will just print out the object's type and address in memory. If you want to print the values of its data members, you need to call its get functions, as shown in the print statement above. 21 | 22 | The file should be named: make_employee_dict.py 23 | -------------------------------------------------------------------------------- /02-IDE_exercises/09-project/README.md: -------------------------------------------------------------------------------- 1 | # project-09 2 | 3 | Write a Python class named AddThreeGame that has two players to play a game in which they alternately choose numbers from 1-9. The number cannot be selected if one of the player already selected it and if at any point exactly three of the player's numbers sum to 15, then that player has won. 4 | If all numbers from 1-9 are chosen, but neither player has won, then the game ends in a draw. 5 | 6 | The class will need **private** variables for: 7 | 1. keeping track of chosen number, and by whom 8 | 2. the current state, which holds one of the four following values: "FIRST_WON", "SECOND_WON", "DRAW", or "UNFINISHED" 9 | 3. keeping track of whose turn it is 10 | 11 | Your AddThreeGame class must include the following methods: 12 | * An init method to initialize the players without any parameters. 13 | * A get method named get_current_state to return the current state of the game. 14 | * A method named make_move that takes two parameters - a string designating the player making the move, either "first" or "second", and an integer giving their number choice (in that order). If it is not that player's turn, or if the integer is not in the correct range, or if that integer has already been chosen, or if the game has already been won or drawn, make_move should return False. Otherwise, it should record the move, update the current state if the move caused a win or draw, update which player's turn it is, and return True. 15 | 16 | For example, your class could be used as follows: 17 | ``` 18 | game = AddThreeGame() 19 | game.make_move("first", 2) 20 | game.make_move("second", 5) 21 | result = game.make_move("first", 7) 22 | state = game.get_current_state() 23 | ``` 24 | Your file should be named: AddThreeGame.py 25 | -------------------------------------------------------------------------------- /02-IDE_exercises/09-project/test_AddThreeGame.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from AddThreeGame import AddThreeGame 3 | 4 | class TestAddThreeGame(unittest.TestCase): 5 | 6 | def test_no_errors_first_wins(self): 7 | # No Errors, First Wins 8 | game = AddThreeGame() 9 | self.assertEqual(game.make_move("first", 2), True) 10 | self.assertEqual(game.get_current_state(), "UNFINISHED") 11 | 12 | self.assertEqual(game.make_move("second", 5), True) 13 | self.assertEqual(game.get_current_state(), "UNFINISHED") 14 | 15 | self.assertEqual(game.make_move("first", 7), True) 16 | self.assertEqual(game.get_current_state(), "UNFINISHED") 17 | 18 | self.assertEqual(game.make_move("second", 1), True) 19 | self.assertEqual(game.get_current_state(), "UNFINISHED") 20 | 21 | self.assertEqual(game.make_move("first", 6), True) 22 | self.assertEqual(game.get_current_state(), "FIRST_WON") 23 | 24 | def test_no_errors_second_wins(self): 25 | # No Errors, Second Wins 26 | game = AddThreeGame() 27 | self.assertEqual(game.make_move("first", 2), True) 28 | self.assertEqual(game.get_current_state(), "UNFINISHED") 29 | 30 | self.assertEqual(game.make_move("second", 5), True) 31 | self.assertEqual(game.get_current_state(), "UNFINISHED") 32 | 33 | self.assertEqual(game.make_move("first", 7), True) 34 | self.assertEqual(game.get_current_state(), "UNFINISHED") 35 | 36 | self.assertEqual(game.make_move("second", 1), True) 37 | self.assertEqual(game.get_current_state(), "UNFINISHED") 38 | 39 | self.assertEqual(game.make_move("first", 3), True) 40 | self.assertEqual(game.get_current_state(), "UNFINISHED") 41 | 42 | self.assertEqual(game.make_move("second", 9), True) 43 | self.assertEqual(game.get_current_state(), "SECOND_WON") 44 | 45 | def test_no_errors_draw(self): 46 | # No Errors, Draw 47 | game = AddThreeGame() 48 | self.assertEqual(game.make_move("first", 1), True) 49 | self.assertEqual(game.get_current_state(), "UNFINISHED") 50 | 51 | self.assertEqual(game.make_move("second", 8), True) 52 | self.assertEqual(game.get_current_state(), "UNFINISHED") 53 | 54 | self.assertEqual(game.make_move("first", 2), True) 55 | self.assertEqual(game.get_current_state(), "UNFINISHED") 56 | 57 | self.assertEqual(game.make_move("second", 5), True) 58 | self.assertEqual(game.get_current_state(), "UNFINISHED") 59 | 60 | self.assertEqual(game.make_move("first", 3), True) 61 | self.assertEqual(game.get_current_state(), "UNFINISHED") 62 | 63 | self.assertEqual(game.make_move("second", 6), True) 64 | self.assertEqual(game.get_current_state(), "UNFINISHED") 65 | 66 | self.assertEqual(game.make_move("first", 4), True) 67 | self.assertEqual(game.get_current_state(), "UNFINISHED") 68 | 69 | self.assertEqual(game.make_move("second", 9), True) 70 | self.assertEqual(game.get_current_state(), "UNFINISHED") 71 | 72 | self.assertEqual(game.make_move("first", 7), True) 73 | self.assertEqual(game.get_current_state(), "DRAW") 74 | 75 | def test_out_of_order(self): 76 | # Out of Order 77 | game = AddThreeGame() 78 | self.assertEqual(game.make_move("second", 2), False) 79 | self.assertEqual(game.get_current_state(), "UNFINISHED") 80 | 81 | self.assertEqual(game.make_move("first", 2), True) 82 | self.assertEqual(game.get_current_state(), "UNFINISHED") 83 | 84 | self.assertEqual(game.make_move("first", 5), False) 85 | self.assertEqual(game.get_current_state(), "UNFINISHED") 86 | 87 | self.assertEqual(game.make_move("second", 5), True) 88 | self.assertEqual(game.get_current_state(), "UNFINISHED") 89 | 90 | self.assertEqual(game.make_move("first", 7), True) 91 | self.assertEqual(game.get_current_state(), "UNFINISHED") 92 | 93 | self.assertEqual(game.make_move("second", 1), True) 94 | self.assertEqual(game.get_current_state(), "UNFINISHED") 95 | 96 | self.assertEqual(game.make_move("first", 6), True) 97 | self.assertEqual(game.get_current_state(), "FIRST_WON") 98 | 99 | 100 | def test_repeat_values(self): 101 | # Repeat Values 102 | game = AddThreeGame() 103 | self.assertEqual(game.make_move("first", 2), True) 104 | self.assertEqual(game.get_current_state(), "UNFINISHED") 105 | 106 | self.assertEqual(game.make_move("second", 2), False) 107 | self.assertEqual(game.get_current_state(), "UNFINISHED") 108 | 109 | self.assertEqual(game.make_move("second", 5), True) 110 | self.assertEqual(game.get_current_state(), "UNFINISHED") 111 | 112 | self.assertEqual(game.make_move("first", 7), True) 113 | self.assertEqual(game.get_current_state(), "UNFINISHED") 114 | 115 | self.assertEqual(game.make_move("second", 1), True) 116 | self.assertEqual(game.get_current_state(), "UNFINISHED") 117 | 118 | self.assertEqual(game.make_move("first", 5), False) 119 | self.assertEqual(game.get_current_state(), "UNFINISHED") 120 | 121 | self.assertEqual(game.make_move("first", 3), True) 122 | self.assertEqual(game.get_current_state(), "UNFINISHED") 123 | 124 | self.assertEqual(game.make_move("second", 9), True) 125 | self.assertEqual(game.get_current_state(), "SECOND_WON") 126 | 127 | def test_values_out_of_range(self): 128 | # Values out of range 129 | game = AddThreeGame() 130 | self.assertEqual(game.make_move("first", 1), True) 131 | self.assertEqual(game.get_current_state(), "UNFINISHED") 132 | 133 | self.assertEqual(game.make_move("second", 0), False) 134 | self.assertEqual(game.get_current_state(), "UNFINISHED") 135 | 136 | self.assertEqual(game.make_move("first", 3), False) 137 | self.assertEqual(game.get_current_state(), "UNFINISHED") 138 | 139 | self.assertEqual(game.make_move("second", 2), True) 140 | self.assertEqual(game.get_current_state(), "UNFINISHED") 141 | 142 | self.assertEqual(game.make_move("first", -1), False) 143 | self.assertEqual(game.get_current_state(), "UNFINISHED") 144 | 145 | self.assertEqual(game.make_move("first", 3), True) 146 | self.assertEqual(game.get_current_state(), "UNFINISHED") 147 | 148 | self.assertEqual(game.make_move("second", 4), True) 149 | self.assertEqual(game.get_current_state(), "UNFINISHED") 150 | 151 | self.assertEqual(game.make_move("first", 100), False) 152 | self.assertEqual(game.get_current_state(), "UNFINISHED") 153 | 154 | def test_play_after_game_finishes(self): 155 | # Plays after game is finished 156 | game = AddThreeGame() 157 | self.assertEqual(game.make_move("first", 2), True) 158 | self.assertEqual(game.get_current_state(), "UNFINISHED") 159 | 160 | self.assertEqual(game.make_move("second", 5), True) 161 | self.assertEqual(game.get_current_state(), "UNFINISHED") 162 | 163 | self.assertEqual(game.make_move("first", 7), True) 164 | self.assertEqual(game.get_current_state(), "UNFINISHED") 165 | 166 | self.assertEqual(game.make_move("second", 1), True) 167 | self.assertEqual(game.get_current_state(), "UNFINISHED") 168 | 169 | self.assertEqual(game.make_move("first", 6), True) 170 | self.assertEqual(game.get_current_state(), "FIRST_WON") 171 | 172 | self.assertEqual(game.make_move("second", 9), False) 173 | self.assertEqual(game.get_current_state(), "FIRST_WON") 174 | 175 | def test_player_1_wins_4_choices(self): 176 | # Player 1 wins after 4 choices 177 | game = AddThreeGame() 178 | self.assertEqual(game.make_move("first", 1), True) 179 | self.assertEqual(game.get_current_state(), "UNFINISHED") 180 | 181 | self.assertEqual(game.make_move("second", 2), True) 182 | self.assertEqual(game.get_current_state(), "UNFINISHED") 183 | 184 | self.assertEqual(game.make_move("first", 3), True) 185 | self.assertEqual(game.get_current_state(), "UNFINISHED") 186 | 187 | self.assertEqual(game.make_move("second", 4), True) 188 | self.assertEqual(game.get_current_state(), "UNFINISHED") 189 | 190 | self.assertEqual(game.make_move("first", 5), True) 191 | self.assertEqual(game.get_current_state(), "UNFINISHED") 192 | 193 | self.assertEqual(game.make_move("second", 6), True) 194 | self.assertEqual(game.get_current_state(), "UNFINISHED") 195 | 196 | self.assertEqual(game.make_move("first", 9), True) 197 | self.assertEqual(game.get_current_state(), "FIRST_WON") 198 | 199 | def test_player_2_wins_4_choices(self): 200 | # Player 2 wins after 4 choices 201 | game = AddThreeGame() 202 | self.assertEqual(game.make_move("first", 1), True) 203 | self.assertEqual(game.get_current_state(), "UNFINISHED") 204 | 205 | self.assertEqual(game.make_move("second", 2), True) 206 | self.assertEqual(game.get_current_state(), "UNFINISHED") 207 | 208 | self.assertEqual(game.make_move("first", 3), True) 209 | self.assertEqual(game.get_current_state(), "UNFINISHED") 210 | 211 | self.assertEqual(game.make_move("second", 4), True) 212 | self.assertEqual(game.get_current_state(), "UNFINISHED") 213 | 214 | self.assertEqual(game.make_move("first", 5), True) 215 | self.assertEqual(game.get_current_state(), "UNFINISHED") 216 | 217 | self.assertEqual(game.make_move("second", 7), True) 218 | self.assertEqual(game.get_current_state(), "UNFINISHED") 219 | 220 | self.assertEqual(game.make_move("first", 8), True) 221 | self.assertEqual(game.get_current_state(), "UNFINISHED") 222 | 223 | self.assertEqual(game.make_move("second", 6), True) 224 | self.assertEqual(game.get_current_state(), "SECOND_WON") 225 | 226 | 227 | if __name__ == '__main__': 228 | unittest.main() -------------------------------------------------------------------------------- /02-IDE_exercises/10-project/README.md: -------------------------------------------------------------------------------- 1 | # project-10 2 | 3 | **Remember that this project cannot be submitted late.** 4 | 5 | Write a Python class called BuildersGame that creates the board for a two-player game that is played on a 5x5 grid. 6 | The rules of the games are each players' builders will move around the board and add levels to towers and the winner is the first one to move a builder on top of a 3-story tower. 7 | 8 | For example, playerA places her two builders on the board, then PlayerB places her two builders on the board. Throughout the game, no two builders can ever occupy the same square. After the initial placement, playerA can move either one of her builders to an adjacent square (one square orthogonally or diagonally). Builders can move any number of levels down, but can move at most 1 level up (they can also stay at the same level). Builders always move to the top of the tower on their destination square. After a builder moves, it **must** add a level to an adjacent square (it must be adjacent to the builder that moved). A level cannot be added to a square that is occupied by any builder. Once a tower has a 4th level, no further levels can be added. After playerA has moved and built, the players alternate moving and building in this way until the game ends. If a player moves one of her builders on top of a 3-story tower **or** if her opponent will not have a legal move available, then she has won. 9 | 10 | The class should have the following **private** data members - a representation of the board; the current state, which holds one of the four following values: "playerA_WON", "playerB_WON", or "UNFINISHED"; and something to keep track of whose turn it is. 11 | 12 | It should have an init method that initializes the board to being empty, initializes the current_state to "UNFINISHED", and appropriately initializes any other data members. 13 | 14 | Tip: Probably the easiest way of representing the board is to use a list of lists. The init method could then initialize the board to a list of 5 lists, each of which contains 5 empty strings (or whatever character you want to use to represent an empty space). 15 | 16 | It should have a get method named get_current_state, which returns the current state. 17 | 18 | It should have a method named initial_placement that takes five parameters: the row and column of each of the player's two builders, and either 'x' or 'o' to indicate the player who is placing builders. Rows and columns will be integers in the range 0-4. For example, initial_placement(0,1,4,2,'o') would place o's builders at row 0, column 1 and row 4, column 2. If one of the chosen squares is already occupied, initial_placement should return False. Also, if the player placing builders doesn't match the player whose turn it is, or if this method is called for a player that has already made a valid initial placement, then it should return False. Otherwise, it should update the board, update whose turn it is, and return True. 19 | 20 | It should have a method named make_move that takes six parameters: the row and column of the piece to move, the row and column of the square it's moving to, and the row and column of where to build. For example, make_move(2,0,3,1,3,0) would move the builder at row 2, column 0 to row 3, column 1 and then build a level at row 3, column 0. If the game has already been won or drawn, or if the move is invalid, make_move should return False. Also, if the builder being moved doesn't belong to the player whose turn it is, or if this method is called before both players have made their initial placements, then it should return False. Otherwise, it should record the move, update the current state, update whose turn it is, and return True. To update the current state, you need to detect if this move put a builder on top of a 3-story tower, or if the opponent will not have a legal move available. 21 | 22 | It's not required, but you'll probably find it useful for testing and debugging to have a method that prints out the board. 23 | 24 | Whether you think of the list indices as being [row][column] or [column][row] doesn't matter as long as you're consistent. 25 | 26 | As a very simple example, your class could be used as follows: 27 | ``` 28 | board = BuildersGame() 29 | board.initial_placement(2,2,1,2,'x') 30 | board.initial_placement(0,1,4,2,'o') 31 | board.make_move(2,2,1,1,1,0) 32 | board.make_move(0,1,1,0,2,0) 33 | board.get_current_state() 34 | ``` 35 | Your file should be named: BuildersGame.py 36 | -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/01-project/my_color.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 04/15/1865 3 | # Description: Asks the user for their favorite color and then 4 | # prints out a statement with the variable 5 | 6 | fave_color = input("Please enter your favorite color: ") 7 | print("Your favorite color is " + fave_color + ".") -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/02a-project/calculate_average.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 09/24/2020 3 | # Description: Takes in 5 float or int values and calculates the average for the inputs 4 | 5 | print("Please enter five numbers") 6 | input_1 = float(input()) 7 | input_2 = float(input()) 8 | input_3 = float(input()) 9 | input_4 = float(input()) 10 | input_5 = float(input()) 11 | 12 | avg = (input_1 + input_2 + input_3 + input_4 + input_5) / 5 13 | print("The calculated average of those numbers is:" + str(avg)) 14 | 15 | 16 | -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/02b-project/temp_conversion.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 09/24/2020 3 | # Description: Takes in a float temperature in Celsius and converts to its corresponding temperature 4 | # in Fahrenheit 5 | 6 | print("Please enter the temperature in Celsius.") 7 | 8 | temp_c = float(input()) 9 | temp_f = (9/5) * temp_c + 32 10 | 11 | print("The corresponding temperature in Fahrenheit is:") 12 | print(temp_f) 13 | 14 | -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/02c-project/coin_change.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 09/24/2020 3 | # Description: Asks the user for int of cents less than $1 and returns 4 | # breakout of coin denominations with fewest number of coins 5 | 6 | print("Please enter an amount between 0 and 99 cents.") 7 | 8 | coins = int(input()) 9 | 10 | print("Your change will be:") 11 | 12 | quarters = coins // 25 13 | coins -= quarters * 25 14 | dimes = coins // 10 15 | coins -= dimes * 10 16 | nickels = coins // 5 17 | coins -= nickels * 5 18 | pennies = coins 19 | 20 | print("Q:", quarters) 21 | print("D:", dimes) 22 | print("N:", nickels) 23 | print("P:", pennies) -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/03a-project/min_max_number.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/04/2020 3 | # Description: Take in number of integers to record from user. Return min and max 4 | # integers from user 5 | 6 | print("How many numbers would you like to enter?") 7 | num_int = int(input()) 8 | # The first while loop ensures that the user enters at least one number 9 | # if, the user enters anything less than 1, it will prompt the user to enter something greater than one 10 | 11 | while num_int < 1: 12 | print("Please enter at least one number") 13 | num_int = int(input()) 14 | else: 15 | print("Please enter", num_int, "numbers.") 16 | 17 | first_int = int(input()) 18 | # the first number is the largest as well as the smallest number 19 | min = first_int 20 | max = first_int 21 | 22 | # if the number of ints requested by user is greater than one, we'll initialize 23 | # a while loop 24 | 25 | while num_int > 1: 26 | n = int(input()) 27 | if n < min: 28 | min = n 29 | if n > max: 30 | max = n 31 | 32 | num_int -= 1 33 | 34 | print("min:", min) 35 | print("max:", max) 36 | -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/03b-project/find_factors.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/05/2020 3 | # Description: Take in positive integer and print list of factors 4 | 5 | integer = int(input("Please enter a positive integer:")) 6 | print("The factors of", integer, "are:") 7 | 8 | for i in range(1, integer+1): 9 | if integer % i == 0: 10 | print(i) -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/03c-project/guess_num.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/05/2020 3 | # Description: Guessing game that takes a number to guess and has user contiously 4 | # make guesses till they get the answer correct 5 | 6 | print("Enter the number for the player to guess.") 7 | solution = int(input()) 8 | 9 | print("Enter your guess.") 10 | guess = int(input()) 11 | 12 | number_of_guesses = 1 13 | 14 | while guess != solution: 15 | if guess > solution: 16 | print("Too high - try again:") 17 | guess = int(input()) 18 | if guess < solution: 19 | print("Too low - try again:") 20 | guess = int(input()) 21 | 22 | number_of_guesses += 1 23 | 24 | number_of_guesses +=1 25 | 26 | print("You guessed it in", number_of_guesses, "tries.") -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/04a-project/distance_fallen.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/17/2020 3 | # Description: created a function called "fall_distance() that takes an input of seconds and returns 4 | # the distance an object has fallen." 5 | 6 | 7 | def fall_distance(t): 8 | '''takes input in seconds and returns distance object has fallen''' 9 | g = 9.8 # velocity 10 | 11 | return 0.5 * g * t*t 12 | 13 | -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/04b-project/fibonacci.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/17/2020 3 | # Description: created a function called fib() that calculate a fibonnaci number for a given 'n' without recursion or the golden ratio. 4 | 5 | def fib(n): 6 | '''calculate a fibonnaci number given the input 'n' without recursion using the golden ratio''' 7 | 8 | prev_num = 0 9 | curr_num = 1 10 | sol = 1 11 | for i in range(n-1): 12 | sol = curr_num + prev_num 13 | prev_num = curr_num 14 | curr_num = sol 15 | 16 | 17 | return sol 18 | 19 | -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/04c-project/hailstone_step.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/17/2020 3 | # Description: Wrote a function for a hailstone sequence where a given number, if even is divided by two and if odd is multiplied by 3 and added by 1. The result will go through the 4 | # same process until the result terminates at a value of 1. 5 | 6 | 7 | def hailstone(n): 8 | '''takes an integer, 'n' and if even divides by 2 and if odd multiples by 3 and adds 1 9 | the result continues until the value reaches 1 and the function terminates and returns the count the number of steps''' 10 | count = 0 11 | while n != 1: 12 | print(count, n) 13 | if n % 2 == 0: 14 | n //= 2 15 | else: 16 | n = (n * 3) + 1 17 | 18 | count += 1 19 | 20 | return count -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/05a-project/multiply_recur.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/24/2020 3 | # Description: write a function that uses recursive iteration to multiply two positive integers 4 | # with addition 5 | 6 | def multiply(multiplier, multiplicand): 7 | """ 8 | Takes in two positive integers and multiplies them by recursively adding the int multiplicand int multiplier times. 9 | """ 10 | if multiplier == 1: 11 | return multiplicand 12 | else: 13 | return multiply(multiplier-1, multiplicand) + multiplicand -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/05b-project/Taxicab.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/24/2020 3 | # Description: Create a taxicab class that tracks changes to x and y coordinates and total odometer changes 4 | 5 | 6 | class Taxicab: 7 | """ 8 | Represents a taxicab that tracks the distance traveled when given x and y coordinates 9 | """ 10 | def __init__(self, x, y): 11 | """ 12 | Creates a taxicab object with x and y coordiantes and intializes an odometer to 0 13 | """ 14 | self._x = x 15 | self._y = y 16 | 17 | self._odometer = 0 18 | 19 | def get_x_coord(self): 20 | """ 21 | returns the current x coordinate 22 | """ 23 | return self._x 24 | 25 | def get_y_coord(self): 26 | """ 27 | returns the current y coordinate 28 | """ 29 | return self._y 30 | 31 | def get_odometer(self): 32 | """ 33 | sums the abs value of the change in x and y coordinates 34 | """ 35 | return self._odometer 36 | 37 | def move_x(self, x_vector): 38 | """ 39 | takes in a one-dimensional vector and adds it to the x coordiante as its original value and the odometer as an absolute value 40 | """ 41 | self._x += x_vector 42 | self._odometer += abs(x_vector) 43 | 44 | def move_y(self, y_vector): 45 | """ 46 | takes in a one-dimensional vector and adds it to the x coordiante as its original value and the odometer as an absolute value 47 | """ 48 | self._y += y_vector 49 | self._odometer += abs(y_vector) 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/06a-project/find_median.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/25/2020 3 | # Description: Sorts a list of numbers and returns the median number in the list 4 | 5 | def find_median(some_nums): 6 | """ 7 | Sorts a list of numbers and returns the median value 8 | """ 9 | some_nums.sort() 10 | array_length = len(some_nums) 11 | 12 | mid_index = int(array_length/2) 13 | 14 | if array_length % 2 == 0: 15 | mid_index_alt = int((array_length/2)-1) 16 | return (some_nums[mid_index] + some_nums[mid_index_alt]) / 2 17 | else: 18 | return some_nums[mid_index] 19 | -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/06b-project/add_surname.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/25/2020 3 | # Description: create a function that takes a list of names and stores any value that starts with the letter 'K' in a new list concatenated also with the string ' Hoffman' 4 | 5 | def add_surname(name_list): 6 | """ 7 | takes a list of names and stores any value that starts with the letter 'K' in a new list concatenated also with the string ' Hoffman' 8 | """ 9 | return [name + " Hoffman" for name in name_list if name[0] == "K"] -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/06c-project/std_dev.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/25/2020 3 | # Description: Creates a Person class to intialize a name and age. 4 | # Then creates a std_dev function that can take a list of person 5 | # objects and calculate a standard deviation on the age 6 | 7 | class Person: 8 | """ 9 | Represents a person 10 | """ 11 | 12 | def __init__(self, name, age): 13 | """ 14 | Intializes a person's name and age 15 | """ 16 | self._name = name 17 | self._age = age 18 | 19 | def get_age(self): 20 | """ 21 | returns the age of a person object 22 | """ 23 | return self._age 24 | 25 | 26 | def std_dev(person_list): 27 | """ 28 | Takes in a list of 'Person' objects and returns the standard deviation of their ages 29 | """ 30 | age_sum = 0 31 | for person in person_list: 32 | age_sum += person.get_age() 33 | 34 | avg = age_sum / len(person_list) 35 | 36 | variance = 0 37 | for person in person_list: 38 | variance += (person.get_age() - avg)**2 39 | 40 | stdv = (variance / len(person_list))**0.5 41 | 42 | return stdv -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/07a-project/square_list.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 10/29/2020 3 | # Description: Mutates a given list and squares the items in the list 4 | 5 | def square_list(lst): 6 | """ 7 | Input: a list of numbers 8 | Doesn't return anything, mutates given list 9 | """ 10 | 11 | for i in range(len(lst)-1): 12 | lst[i] **= 2 13 | -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/07b-project/reverse_list.py: -------------------------------------------------------------------------------- 1 | # Author: Luis Mercado 2 | # Date: 10/24/2024 3 | # Description: Function that mutates a list of numbers by reversing its order without slicing 4 | 5 | 6 | def reverse_list(num_list: list[int | float]) -> None: 7 | """ 8 | Mutates list of numbers (float or int) into reverse order 9 | without using any slicing (no return value) 10 | """ 11 | 12 | # Define lower limit of desired index range which is the same as upper limit of starting list argument 13 | low_lim: int = len(num_list)-1 14 | 15 | # For range must use negative stride and go to -1 so that 0 index is included 16 | for num in range(low_lim, -1, -1): 17 | num_list.append(num_list[num]) # Adds currently indexed list value to end of list 18 | del num_list[num] # Deletes original iteration of currently indexed value from list 19 | 20 | # No return value, but by using .append and del[], the original num_list argument has iteratively had its last 21 | # value duplicated to the end and then had the original occurrence of it deleted so that the list is now 22 | # effectively in the opposite order -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/08a-project/count_letters.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 11/14/2020 3 | # Description: creates a function called count_letters that takes as a parameter a string 4 | # and returns a dictionary that tabulates how many of each letter is in that string. 5 | 6 | def count_letters(string): 7 | """ 8 | Input: a string 9 | Output: a dictionary with the key as a capital letter and the value as the count 10 | of occurrences of the upper and lower case occurences of that letter 11 | """ 12 | 13 | letter_counts = {} 14 | 15 | for c in string: 16 | 17 | if 'A' <= c.upper() <= 'Z': 18 | 19 | if c.upper() not in letter_counts: 20 | letter_counts[c.upper()] = 1 21 | 22 | else: 23 | letter_counts[c.upper()] += 1 24 | 25 | return letter_counts -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/08b-project/words_in_both.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 11/14/2020 3 | # Description: Takes in two strings and returns a set of common words 4 | 5 | def words_in_both(string_1, string_2): 6 | """ 7 | Input: two strings 8 | Output: a set of common words between the two strings 9 | """ 10 | set_1 = set(string_1.lower().split()) 11 | set_2 = set(string_2.lower().split()) 12 | 13 | return set_1 & set_2 -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/08c-project/make_employee_dict.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 11/14/2020 3 | # Description: Creates an Employee object to store common charactersitcs of an employee 4 | # Creates a function, make_employees_dict that takes a list of these characteristics and 5 | # returns a dictionary where the key is the id numbers and the value is the Employee object 6 | 7 | class Employee: 8 | """ 9 | Represents fundamental characteristics of an employee of a company 10 | """ 11 | 12 | def __init__(self, name, ID_number, salary, email_address): 13 | """ 14 | Creates an Employeee object with name, ID_number, salary, and email_address values 15 | """ 16 | self._name = name 17 | self._ID_number = ID_number 18 | self._salary = salary 19 | self._email_address = email_address 20 | 21 | def get_name(self): 22 | """ 23 | returns employee name 24 | """ 25 | return self._name 26 | 27 | def get_ID_number(self): 28 | """ 29 | returns employee ID number 30 | """ 31 | return self._ID_number 32 | 33 | def get_salary(self): 34 | """ 35 | returns employee salary 36 | """ 37 | return self._salary 38 | 39 | def get_email_address(self): 40 | """ 41 | returns employee email_address 42 | """ 43 | return self._email_address 44 | 45 | def make_employee_dict(names, id_nums, salaries, email_addresses): 46 | """ 47 | Input: 4 lists of names, id numbers, salaries, and email_addresses of equal length 48 | Output: a dictionary where the id num is the key and the Employee object the value 49 | """ 50 | 51 | employee_dict = {} 52 | 53 | i = 0 54 | for id_ in id_nums: 55 | employee_dict[id_] = Employee(names[i], id_nums[i], salaries[i], email_addresses[i]) 56 | i += 1 57 | 58 | return employee_dict -------------------------------------------------------------------------------- /02-IDE_exercises/solutions/09-project/AddThreeGame.py: -------------------------------------------------------------------------------- 1 | # Author: Brandon Hoffman 2 | # Date: 11/15/2020 3 | # Description: The class AddThreeGame that allows two players to play a game 4 | # in which they alternately choose numbers from 1-9. They may not choose a number 5 | # that has already been selected by either player. If at any point exactly three 6 | # of the player's numbers sum to 15, then that player has won. 7 | # If all numbers from 1-9 are chosen, but neither player has won, 8 | # then the game ends in a draw. 9 | 10 | 11 | class AddThreeGame: 12 | """ 13 | The class AddThreeGame that allows two players to play a game 14 | in which they alternately choose numbers from 1-9. They may not choose a number 15 | that has already been selected by either player. If at any point exactly three 16 | of the player's numbers sum to 15, then that player has won. 17 | If all numbers from 1-9 are chosen, but neither player has won, 18 | then the game ends in a draw. 19 | """ 20 | 21 | def __init__(self): 22 | """ 23 | intializes 4 private variables to be used throughout the Class 24 | """ 25 | self._nums_chosen = [] 26 | self._current_state = "UNFINISHED" 27 | self._player_turn = "first" 28 | self._player_score = 0 29 | 30 | 31 | def get_current_state(self): 32 | """ 33 | get method to allow user to see the state of the game. 34 | Input: VOID 35 | Output: Should return string either: "UNFINISHED", "FIRST_WON", "SECOND_WON", or "DRAW" 36 | """ 37 | return self._current_state 38 | 39 | def get_player_turn(self): 40 | """ 41 | returns player turn private variable 42 | """ 43 | return self._player_turn 44 | 45 | def get_player_choices(self): 46 | """ 47 | returns array of player choices for first or second player, depending on instance of player turn 48 | """ 49 | if self._player_turn == "first": 50 | n = 0 51 | elif self._player_turn == "second": 52 | n = 1 53 | 54 | return self._nums_chosen[n::2] 55 | 56 | def _set_current_state(self): 57 | """ 58 | private method that will update the current state depending on the state of the 59 | most current score and which player's turn it is 60 | """ 61 | if self._check_score(self.get_player_choices()): 62 | self._current_state = self.get_player_turn().upper() + '_' + 'WON' 63 | 64 | elif len(self._nums_chosen) == 9: 65 | self._current_state = 'DRAW' 66 | 67 | def _set_player_turn(self): 68 | """ 69 | private method to change the _player_turn variable to the next player 70 | """ 71 | if self._player_turn == "first": 72 | self._player_turn = "second" 73 | 74 | else: 75 | self._player_turn = "first" 76 | 77 | def _check_score(self, arr): 78 | if len(arr) < 3: 79 | return False 80 | 81 | choices = set(arr) 82 | for i in range(len(arr) -1): 83 | for j in range(i + 1, len(arr)): 84 | solution = 15 - (arr[i] + arr[j]) 85 | 86 | if solution in choices and solution not in [arr[i], arr[j]]: 87 | return True 88 | else: 89 | return False 90 | 91 | def make_move(self, player, num_choice): 92 | """ 93 | public method that allows players to interact with the game 94 | Input: takes a player variable either "first" or "second" and an integer from 1-9 95 | Output: Returns True if rules of game are met. 96 | """ 97 | if self._current_state != "UNFINISHED": 98 | return False 99 | 100 | if player != self._player_turn: 101 | return False 102 | 103 | if 9 < num_choice or num_choice < 1: 104 | return False 105 | 106 | if num_choice in self._nums_chosen: 107 | return False 108 | 109 | else: 110 | self._nums_chosen.append(num_choice) 111 | self._set_current_state() 112 | self._set_player_turn() 113 | 114 | return True -------------------------------------------------------------------------------- /03-additional_material/01b-Git_Terminology_Commands_And_Workflow.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Git Terms\n", 9 | "Rebasing and merging are two different ways to integrate changes from one branch to another in version control systems like Git.\n", 10 | "\n", 11 | "1. **Git**: A distributed version control system for tracking changes in source code during software development.\n", 12 | "\n", 13 | "2. **Repository**: A collection of files and directories that make up a project, along with the version history and metadata associated with the project.\n", 14 | "\n", 15 | "3. **Commit**: A snapshot of changes to a set of files at a particular point in time. Each commit has a unique identifier and metadata such as author, date, and commit message.\n", 16 | "\n", 17 | "4. **Branch**: A separate line of development within a repository, used to isolate changes and collaborate on new features or bug fixes.\n", 18 | "\n", 19 | "5. **Merge**: Combining changes from one branch into another, resulting in a new commit that incorporates the changes from both branches.\n", 20 | "\n", 21 | "6. **Rebase**: A way of integrating changes from one branch to another by moving the entire branch to the tip of the target branch, creating a linear history. This can be useful for maintaining a clean and organized history, but can also be complex and require resolving conflicts.\n", 22 | "\n", 23 | "7. **Merge conflict**: A situation that occurs when Git is unable to automatically merge changes from one branch into another, typically because there are conflicting changes to the same file or lines of code. Resolving merge conflicts requires manual intervention to decide which changes should be kept and which should be discarded.\n", 24 | "\n", 25 | "8. **Pull request**: A proposed set of changes to a repository, typically used for collaboration and review.\n", 26 | "\n", 27 | "9. **Fork**: A copy of a repository that allows you to make changes to the codebase without affecting the original project.\n", 28 | "\n", 29 | "10. **Clone**: A local copy of a repository that allows you to make changes and push them back to the remote repository.\n", 30 | "\n", 31 | "11. **Remote**: A version of a repository hosted on a server, such as GitHub, that can be accessed by multiple users.\n", 32 | "\n", 33 | "12. **Issue**: A problem or task related to a project that is tracked in the repository, typically used for bug tracking and project management.\n", 34 | "\n", 35 | "## Some common Git commands\n", 36 | "Sure, here are some commonly used Git commands along with brief explanations of what they do:\n", 37 | "\n", 38 | "`git init`: Creates a new Git repository in the current directory.\n", 39 | "\n", 40 | "`git clone`: Creates a copy of a remote repository on your local machine.\n", 41 | "\n", 42 | "`git add`: Adds changes to the staging area, preparing them to be committed.\n", 43 | "\n", 44 | "`git commit`: Records changes to the repository, creating a new commit with a message describing the changes.\n", 45 | "\n", 46 | "`git status`: Shows the current status of the repository, including any changes that have been made since the last commit.\n", 47 | "\n", 48 | "`git branch`: Lists all branches in the repository or creates a new branch.\n", 49 | "\n", 50 | "`git checkout`: Switches between different branches or commits in the repository.\n", 51 | "\n", 52 | "`git merge`: Combines changes from one branch into another.\n", 53 | "\n", 54 | "`git push`: Sends commits from your local repository to a remote repository.\n", 55 | "\n", 56 | "`git pull`: Fetches and merges changes from a remote repository into your local repository.\n", 57 | "\n", 58 | "`git fetch`: Retrieves changes from a remote repository, but does not merge them.\n", 59 | "\n", 60 | "`git log`: Displays a list of all commits in the repository, along with their metadata.\n", 61 | "\n", 62 | "`git diff`: Shows the differences between files or commits.\n", 63 | "\n", 64 | "`git stash`: Temporarily saves changes that are not ready to be committed.\n", 65 | "\n", 66 | "`git remote`: Manages connections to remote repositories.\n", 67 | "\n", 68 | "## Git workflow example\n", 69 | "Sure, here's an example Git workflow that you might use when working on a software development project with a team:\n", 70 | "\n", 71 | "Create a new branch: Before making any changes, create a new branch for the feature or bug fix you will be working on. This isolates your changes from the main branch, allowing you to work on the feature without disrupting other work being done on the project. You can create a new branch using the command `git checkout -b `.\n", 72 | "\n", 73 | "Make changes: Once you have created a new branch, make changes to the code to implement the feature or fix the bug. Use `git add` to stage changes, and `git commit` to create a new commit with a descriptive commit message.\n", 74 | "\n", 75 | "Pull changes: Before pushing your changes to the remote repository, pull any changes that have been made to the main branch since you created your new branch. This ensures that your changes are based on the latest version of the code. You can do this using `git pull origin main`.\n", 76 | "\n", 77 | "Push changes: Once you have made and committed your changes, push them to the remote repository using `git push origin `.\n", 78 | "\n", 79 | "Create a pull request: Once your changes have been pushed to the remote repository, create a pull request to merge your changes into the main branch. This allows other team members to review and comment on your changes before they are merged. You can create a pull request on GitHub or using the `git request-pull` command.\n", 80 | "\n", 81 | "Resolve merge conflicts: If there are any merge conflicts between your branch and the main branch, you will need to resolve them before your changes can be merged. Use `git merge` to merge changes from the main branch into your feature branch, and then resolve any conflicts that arise.\n", 82 | "\n", 83 | "Merge changes: Once any conflicts have been resolved and your changes have been reviewed and approved, merge your changes into the main branch using the `git merge` command or by clicking the \"merge\" button on the pull request page in GitHub.\n", 84 | "\n", 85 | "Delete branch: After your changes have been merged, delete your feature branch using the `git branch -d ` command." 86 | ] 87 | } 88 | ], 89 | "metadata": { 90 | "kernelspec": { 91 | "display_name": ".venv", 92 | "language": "python", 93 | "name": "python3" 94 | }, 95 | "language_info": { 96 | "name": "python", 97 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 98 | }, 99 | "orig_nbformat": 4, 100 | "vscode": { 101 | "interpreter": { 102 | "hash": "70079cbbe2cc42f2592d5a55443ae9a6fc8ec5f7d810c21163e2b036cc83b19b" 103 | } 104 | } 105 | }, 106 | "nbformat": 4, 107 | "nbformat_minor": 2 108 | } 109 | -------------------------------------------------------------------------------- /03-additional_material/01b-The_Terminal.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Terminals/Command Line Interface (CLI)\n", 9 | "\n", 10 | "## What is the terminal\n", 11 | "A terminal is a command-line interface that allows you to interact with your computer using text commands. It provides a way to navigate your computer's file system, run programs, and perform various tasks without the need for a graphical user interface. While it may seem intimidating at first, learning to use the terminal can be very empowering and efficient once you become familiar with its basic commands and structure.\n", 12 | "\n", 13 | "## Why learning the terminal is important for developers\n", 14 | "Learning to use the terminal is important for aspiring developers for several reasons:\n", 15 | "\n", 16 | "1. Efficiency: Using the terminal can be much faster and more efficient than using a graphical user interface for many tasks, especially when working with code or performing system-level tasks.\n", 17 | "\n", 18 | "2. Automation: The terminal can be used to automate repetitive tasks and create scripts to perform complex tasks, which can save time and reduce errors.\n", 19 | "\n", 20 | "3. Debugging: Many programming languages and development tools use the terminal for debugging and troubleshooting purposes.\n", 21 | "\n", 22 | "4. Collaboration: Many software development workflows involve using the terminal to interact with version control systems, build tools, and deployment pipelines, so it's essential to be comfortable using the terminal when working with other developers.\n", 23 | "\n", 24 | "5. Flexibility: The terminal provides a way to interact with a wide variety of tools and systems, making it an essential tool for developers working with a range of technologies and platforms.\n", 25 | "\n", 26 | "## What's the difference between the terminal and the shell\n", 27 | "A shell is a program that provides a command-line interface for interacting with an operating system. It takes commands from the user and executes them by interacting with the operating system's kernel. The shell provides various features such as command history, auto-completion, and scripting capabilities.\n", 28 | "\n", 29 | "On the other hand, a terminal is a hardware device or software application that provides a user interface for accessing the shell. It provides a way to interact with the shell by displaying the output of shell commands and allowing the user to input new commands. In other words, a terminal is a window that displays the output of the shell and allows the user to interact with it.\n", 30 | "\n", 31 | "In modern computing, the terms \"shell\" and \"terminal\" are often used interchangeably, and many people refer to the terminal as the \"command-line interface.\" However, technically speaking, a shell is a program that runs within the terminal, and the terminal is the application that provides the interface for the shell.\n", 32 | "\n", 33 | "## Here's an example of a shell script you might find useful\n", 34 | "To the point of automating your terminal commands and making them collaborative, you may find it tedious to install python libraries over and over again on new systems. You may also worry that other developers or users will have trouble managing these resources as well.\n", 35 | "\n", 36 | "Here's an example of a shell script we could write that would check for the user that the appropriate version of Python is installed, update necessary resources like pip, setup and activate a virtual environment, then install the required packages from a provided `requirements.txt` file.\n", 37 | "### `install_dependencies.sh`\n", 38 | "```bash\n", 39 | "#!/bin/bash\n", 40 | "\n", 41 | "if python -c 'import sys; assert sys.version_info >= (3,11)' > /dev/null; then\n", 42 | "\n", 43 | " # update necessary python resources at global level\n", 44 | " python -m pip install --upgrade setuptools wheel pip\n", 45 | "\n", 46 | " # setup and activate virtual environment\n", 47 | " python -m venv .venv\n", 48 | " source \"./.venv/bin/activate\" && python -m pip install --upgrade setuptools wheel pip\n", 49 | "\n", 50 | " if [ -f requirements.txt ]; then\n", 51 | " # install from requirements\n", 52 | " python -m pip install -r requirements.txt\n", 53 | " \n", 54 | " fi\n", 55 | "\n", 56 | "else\n", 57 | "\n", 58 | " echo \"python version should be >= 3.11\"\n", 59 | "\n", 60 | "fi\n", 61 | "```\n", 62 | "\n", 63 | "## Useful commands to know:\n", 64 | "Here are some of the most common and important shell commands to know:\n", 65 | "\n", 66 | "`ls`: Lists the files and directories in the current directory.\n", 67 | "\n", 68 | "`cd`: Changes the current directory.\n", 69 | "\n", 70 | "`mkdir`: Creates a new directory.\n", 71 | "\n", 72 | "`rm`: Deletes files and directories.\n", 73 | "\n", 74 | "`cp`: Copies files and directories.\n", 75 | "\n", 76 | "`mv`: Moves or renames files and directories.\n", 77 | "\n", 78 | "`cat`: Displays the contents of a file.\n", 79 | "\n", 80 | "`grep`: Searches for a pattern in a file or input.\n", 81 | "\n", 82 | "`ps`: Lists the currently running processes.\n", 83 | "\n", 84 | "`kill`: Terminates a process.\n", 85 | "\n", 86 | "`chmod`: Changes the permissions of a file or directory.\n", 87 | "\n", 88 | "`ssh`: Connects to a remote computer using Secure Shell (SSH).\n", 89 | "\n", 90 | "`tar`: Archives files into a compressed file.\n", 91 | "\n", 92 | "`curl`: Downloads files from the internet.\n", 93 | "\n", 94 | "`echo`: Prints a message to the console.\n", 95 | "\n", 96 | "These are just a few of the most commonly used shell commands. There are many other commands available, and their usage can vary depending on the operating system and the specific shell being used. Learning to use these commands efficiently can help improve productivity and simplify common tasks in the terminal." 97 | ] 98 | } 99 | ], 100 | "metadata": { 101 | "kernelspec": { 102 | "display_name": "Python 3", 103 | "language": "python", 104 | "name": "python3" 105 | }, 106 | "language_info": { 107 | "name": "python", 108 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 109 | }, 110 | "orig_nbformat": 4, 111 | "vscode": { 112 | "interpreter": { 113 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 114 | } 115 | } 116 | }, 117 | "nbformat": 4, 118 | "nbformat_minor": 2 119 | } 120 | -------------------------------------------------------------------------------- /03-additional_material/01b-Updating_Forked_Projects.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "\n", 9 | "\n", 10 | "# How to update or sync a forked repository from GitHub\n", 11 | "\n", 12 | "If you're unfamiliar with Git terms, commands, or the general workflow, you can review [01b-Git_Terminology_Commands_And_Workflow.ipynb](../03-additional_material/01b-Git_Terminology_Commands_And_Workflow.ipynb)\n", 13 | "\n", 14 | "## The Problem\n", 15 | "\n", 16 | "Let's say you have forked a repository on GitHub called `my-repo` and made some changes to your local copy of the repository. Meanwhile, the original repository you forked from has had some changes made to it by other contributors.\n", 17 | "\n", 18 | "Now you want to update your local copy of `my-repo` with the changes from the original \"upstream\" repository. Here's where the problem comes in - if you simply try to pull the changes from `upstream` into your local copy of `my-repo`, you may run into conflicts that need to be resolved manually.\n", 19 | "\n", 20 | "The solution is to add the `upstream` repository as a \"remote\"\\* to your local copy of `my-repo`, fetch all branches from that remote, and then rebase your local copy of the `main` branch onto the `main` branch of the `upstream` repository. Let's see the solution below to understand better.\n", 21 | "\n", 22 | "\n", 23 | "\\**\"Remotes\" are like nicknames for the URLs of repositories. For instance, `origin` is probably the remote for your forked project.*\n", 24 | "\n", 25 | "## The Solution\n", 26 | "\n", 27 | "Here's a good [summary](https://stackoverflow.com/a/7244456/10380766) provided by \"Mark Longair\" on Stack Overflow. We've updated the provided commands with our related project:\n", 28 | "\n", 29 | "In your local clone of your forked repository, you can add the original GitHub repository as a \"remote\". Then you can fetch all the branches from that \"upstream\" repository, and rebase your work to continue working on the upstream version. In terms of commands, this might look like the following:\n", 30 | "\n", 31 | "```bash\n", 32 | "# Add the remote, call it \"upstream\":\n", 33 | " \n", 34 | "git remote add upstream git@github.com:branhoff/python_class_101.git\n", 35 | " \n", 36 | "# Fetch all the branches of that remote into remote-tracking branches\n", 37 | "\n", 38 | "git fetch upstream\n", 39 | "\n", 40 | "# Make sure that you're on your master branch:\n", 41 | " \n", 42 | "git checkout main\n", 43 | " \n", 44 | "# Rewrite your master branch so that any commits of yours that\n", 45 | "# aren't already in upstream/master are replayed on top of that\n", 46 | "# other branch:\n", 47 | "\n", 48 | "git rebase upstream/main\n", 49 | "```\n", 50 | "\n", 51 | "For some additional details, you can see the linked StackOverflow post above." 52 | ] 53 | } 54 | ], 55 | "metadata": { 56 | "kernelspec": { 57 | "display_name": ".venv", 58 | "language": "python", 59 | "name": "python3" 60 | }, 61 | "language_info": { 62 | "name": "python", 63 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 64 | }, 65 | "orig_nbformat": 4, 66 | "vscode": { 67 | "interpreter": { 68 | "hash": "70079cbbe2cc42f2592d5a55443ae9a6fc8ec5f7d810c21163e2b036cc83b19b" 69 | } 70 | } 71 | }, 72 | "nbformat": 4, 73 | "nbformat_minor": 2 74 | } 75 | -------------------------------------------------------------------------------- /03-additional_material/06b-Lists.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# List syntax prior to `3.9`\n", 9 | "Type hinting can be used to specify the expected data type of elements in a list. In Python, you can use the List type from the typing module to specify the type of elements in a list. For example:\n", 10 | "\n", 11 | "```python\n", 12 | "from typing import List\n", 13 | "\n", 14 | "def get_average(numbers: List[float]) -> float:\n", 15 | " return sum(numbers) / len(numbers)\n", 16 | "```\n", 17 | "In the example above, the get_average function takes a single argument, numbers, which is expected to be a list of float values. The List[float] syntax specifies that the numbers argument is a list whose elements are of type float. The function's return value is indicated to be of type float.\n", 18 | "\n", 19 | "One extra bit you probably noticed is the phraise `from typing import List`. We'll cover `import` statements, in the future, but for now just know that for type hinting with `Lists` (and other collection objects we'll talk about soon), we need to \"`import`\" the class \"`List`\" which comes from the \"`typing`\" module where a module is a file containing Python definitions and statements that can be used in other Python programs.\n", 20 | "\n", 21 | "So just remember to include `from typing import List` at the top of your project files when using lists in your module." 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "# let's see how to run our examples from the beginning again execep this time with type hinting\n", 31 | "from typing import List\n", 32 | "\n", 33 | "some_primes: List[int] = [2,3,5,7,11,13,17,19,23,29,31] # list with integers\n", 34 | "some_names: List[str] = [\"Groucho\",\"Harpo\",\"Chico\",\"Zeppo\",\"Karl\"] # list with strings\n", 35 | "# Let's skip this one and talk about how to do type hinting with mixed data types\n", 36 | "# some_stuff: List[] = [98, \"Fido\", -34.925, [\"Phantom\", \"Tollbooth\"]] # list with a mix of integer, string, float, and nested list objects\n", 37 | "one = [\"just me\"] # a single" 38 | ] 39 | }, 40 | { 41 | "attachments": {}, 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "## Type hinting with **mixed** data types in collection object\n", 46 | "\n", 47 | "To type hint a list with a mix of items, you can use the `Union` type from the typing module. The `Union` type allows you to specify that a variable can be of one of several types. Let's take a look at how we'd type hint of the `some_stuff` variable." 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "from typing import List, Union\n", 57 | "\n", 58 | "some_stuff: List[Union[int, str, float, List[str]]] = [98, \"Fido\", -34.925, [\"Phantom\", \"Tollbooth\"]]" 59 | ] 60 | }, 61 | { 62 | "attachments": {}, 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "In this code, the some_stuff variable is declared as a list of items that can be either an `int`, a `str`, a `float`, or a nested `list` of `str` values, using the `Union` type and the `List` type. The `List[Union[int, str, float, List[str]]]` syntax specifies that the `some_stuff` argument is a list whose elements can be one of `int`, `str`, `float`, or `List[str]` types." 67 | ] 68 | }, 69 | { 70 | "attachments": {}, 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "## Type hinting with **any** data type in collection object\n", 75 | "\n", 76 | "If your list can contain any type of object, you can use the `Any` type from the `typing` module to denote that in your type hint. The `Any` type indicates that the type of an object can be anything.\n", 77 | "\n", 78 | "If we used our `some_stuff` example from before, we could write it with the `Any` type like so:\n", 79 | "\n", 80 | "```python\n", 81 | "from typing import List, Any\n", 82 | "\n", 83 | "some_stuff: List[Any] = [98, \"Fido\", -34.925, [\"Phantom\", \"Tollbooth\"]]\n", 84 | "```\n", 85 | "It's important to note that using the Any type can make it harder to catch type errors at runtime and can also make the code less readable, as the type of the objects in the list is not specified. In general, it's recommended to use more specific types where possible." 86 | ] 87 | } 88 | ], 89 | "metadata": { 90 | "kernelspec": { 91 | "display_name": "Python 3", 92 | "language": "python", 93 | "name": "python3" 94 | }, 95 | "language_info": { 96 | "codemirror_mode": { 97 | "name": "ipython", 98 | "version": 3 99 | }, 100 | "file_extension": ".py", 101 | "mimetype": "text/x-python", 102 | "name": "python", 103 | "nbconvert_exporter": "python", 104 | "pygments_lexer": "ipython3", 105 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 106 | }, 107 | "vscode": { 108 | "interpreter": { 109 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 110 | } 111 | } 112 | }, 113 | "nbformat": 4, 114 | "nbformat_minor": 4 115 | } 116 | -------------------------------------------------------------------------------- /03-additional_material/07a-Tuples_and_Mutability_vs_Immutability.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Type hinting with Tuples in Python prior to `3.9`\n", 9 | "To type hint tuples in Python, you can use the `Tuple` type from the `typing` module and specify the types of the individual elements in the tuple." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 3, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "some_primes: tuple[int, int, int, int, int, int, int, int, int, int, int] = (2, 3, 5, 7, 11, 13, 17, 19, 23, 27, 31)\n", 19 | "some_names: tuple[str, str, str, str, str] = (\"Groucho\", \"Harpo\", \"Chico\", \"Zeppo\", \"Karl\")\n", 20 | "some_stuff: tuple[int, str, float, tuple[str, str]] = (98, \"Fido\", -4.925, (\"phantom\", \"tollbooth\"))\n", 21 | "zero: tuple[()] = () # the empty tuple\n", 22 | "\n", 23 | "one: tuple[str] = (\"just me\",)\n", 24 | "\n", 25 | "numbers: tuple[int, int, int] = (3, 2, 1)" 26 | ] 27 | }, 28 | { 29 | "attachments": {}, 30 | "cell_type": "markdown", 31 | "metadata": {}, 32 | "source": [ 33 | "In this code, each of the tuples is declared with a type hint using the `Tuple` type, indicating the types of the individual elements in the tuple. The type hint syntax uses a comma-separated list of types within square brackets to specify the types of the elements. For example, `Tuple[int, int, int]` specifies a tuple with three `int` elements. The `Tuple[()]` syntax is used to specify an empty tuple.\n", 34 | "\n", 35 | "\n", 36 | "Naturally, the syntax can be a little tedious if you have a large number items to declare in your Tuple.\n", 37 | "\n", 38 | "You can use the `Tuple` type from the typing module with the `...` syntax to specify that the tuple can contain any number of elements of any type.\n", 39 | "\n", 40 | "Here's an example of using the `Tuple` type to type hint a tuple without declaring individual elements:" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "from typing import Tuple\n", 50 | "\n", 51 | "some_primes: Tuple[int, ...] = (2, 3, 5, 7, 11, 13, 17, 19, 23, 27, 31)\n", 52 | "some_names: Tuple[str, ...] = (\"Groucho\", \"Harpo\", \"Chico\", \"Zeppo\", \"Karl\")\n", 53 | "some_stuff: Tuple[int, str, float, Tuple[str, ...]] = (98, \"Fido\", -4.925, (\"phantom\", \"tollbooth\"))\n", 54 | "zero: Tuple[()] = ()\n", 55 | "\n", 56 | "one: Tuple[str] = (\"just me\",)\n", 57 | "\n", 58 | "numbers: Tuple[int, ...] = (3, 2, 1)" 59 | ] 60 | }, 61 | { 62 | "attachments": {}, 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "In this code, the `Tuple` type is used with the `...` syntax to specify that each tuple can contain any number of elements of the specified type. For example, `Tuple[int, ...]` specifies a tuple that can contain any number of `int` elements.\n", 67 | "\n", 68 | "Using the `Tuple` type with the `...` syntax can make your code more concise and easier to read, as well as make it more flexible if you need to change the number of elements in your tuples in the future." 69 | ] 70 | } 71 | ], 72 | "metadata": { 73 | "kernelspec": { 74 | "display_name": "Python 3", 75 | "language": "python", 76 | "name": "python3" 77 | }, 78 | "language_info": { 79 | "codemirror_mode": { 80 | "name": "ipython", 81 | "version": 3 82 | }, 83 | "file_extension": ".py", 84 | "mimetype": "text/x-python", 85 | "name": "python", 86 | "nbconvert_exporter": "python", 87 | "pygments_lexer": "ipython3", 88 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 89 | }, 90 | "vscode": { 91 | "interpreter": { 92 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 93 | } 94 | } 95 | }, 96 | "nbformat": 4, 97 | "nbformat_minor": 4 98 | } 99 | -------------------------------------------------------------------------------- /03-additional_material/08a-Dictionaries.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Type hinting with Dictionaries in Python prior to `3.9`\n", 9 | "Type hinting in Python can be used to specify the expected types of variables, including dictionaries. In the case of the state_capitals dictionary, you can add type hinting as follows:\n", 10 | "\n", 11 | "```python\n", 12 | "from typing import Dict\n", 13 | "\n", 14 | "state_capitals: Dict[str, str] = {\n", 15 | " \"Washington\" : \"Olympia\",\n", 16 | " \"Oregon\" : \"Salem\",\n", 17 | " \"Idaho\" : \"Boise\",\n", 18 | " \"Montana\" : \"Helena\"\n", 19 | "}\n", 20 | "```\n", 21 | "\n", 22 | "In this code, we'e using our old friend, the `typing` module and importing the `Dict` type. The `state_capitals` variable is declared as a `Dict[str, str]`, indicating that it is a dictionary with keys of type `str` and values of type `str`." 23 | ] 24 | }, 25 | { 26 | "attachments": {}, 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "The keys in a dictionary must be immutable, but the associated values can be of any type. The keys are not required to all be the same type. You can even nest dictionaries. Here's an example of a dictionary with some string values and an integer value. For mixing expected types, we can use the `Union` method." 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "from typing import Dict, Union\n", 40 | "\n", 41 | "capybara: Dict[str, Union[str, int]] = {\n", 42 | " \"scientific name\" : \"Hydrochoerus hydrochaeris\", \n", 43 | " \"lifespan in years\" : 10, \n", 44 | " \"classification\" : \"rodent\", \n", 45 | " \"size\" : \"unusual\"\n", 46 | "}" 47 | ] 48 | } 49 | ], 50 | "metadata": { 51 | "kernelspec": { 52 | "display_name": "Python 3", 53 | "language": "python", 54 | "name": "python3" 55 | }, 56 | "language_info": { 57 | "codemirror_mode": { 58 | "name": "ipython", 59 | "version": 3 60 | }, 61 | "file_extension": ".py", 62 | "mimetype": "text/x-python", 63 | "name": "python", 64 | "nbconvert_exporter": "python", 65 | "pygments_lexer": "ipython3", 66 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 67 | }, 68 | "vscode": { 69 | "interpreter": { 70 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 71 | } 72 | } 73 | }, 74 | "nbformat": 4, 75 | "nbformat_minor": 4 76 | } 77 | -------------------------------------------------------------------------------- /03-additional_material/08b-Sets.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# Type hinting with sets prior to Python `3.9`\n" 9 | ] 10 | }, 11 | { 12 | "cell_type": "code", 13 | "execution_count": null, 14 | "metadata": {}, 15 | "outputs": [], 16 | "source": [ 17 | "from typing import Set, Union\n", 18 | "\n", 19 | "some_ints: Set[int] = {1, -7, -3, 524, 0}\n", 20 | "some_elements: Set[Union[int, str, float, bool, tuple]] = {19, \"watermelon\", 12.6, False, (1,2,3)}\n", 21 | "empty: Set = set() # The empty set\n", 22 | "# Remember that {} would be an empty dictionary" 23 | ] 24 | }, 25 | { 26 | "attachments": {}, 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "In this code, the `typing` module is imported to provide access to the `Set` and `Union` types. The `some_ints` variable is declared as a `Set[int]`, indicating that it is a set of integers. The `some_elements` variable is declared as a `Set[Union[int, str, float, bool, tuple]]`, indicating that it is a set of elements that can be either integers, strings, floats, booleans, or tuples. The empty variable is declared as a `Set`, indicating that it is an empty set without any type restrictions." 31 | ] 32 | } 33 | ], 34 | "metadata": { 35 | "kernelspec": { 36 | "display_name": "Python 3", 37 | "language": "python", 38 | "name": "python3" 39 | }, 40 | "language_info": { 41 | "codemirror_mode": { 42 | "name": "ipython", 43 | "version": 3 44 | }, 45 | "file_extension": ".py", 46 | "mimetype": "text/x-python", 47 | "name": "python", 48 | "nbconvert_exporter": "python", 49 | "pygments_lexer": "ipython3", 50 | "version": "3.11.1 (main, Feb 12 2023, 14:34:36) [GCC 11.3.0]" 51 | }, 52 | "vscode": { 53 | "interpreter": { 54 | "hash": "e9e699164e4a322cc4d7e5a175ae888281c7a6a570ea3d8a2c02e29901df6b06" 55 | } 56 | } 57 | }, 58 | "nbformat": 4, 59 | "nbformat_minor": 4 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python_class_101 2 | 3 | Welcome to this programming course! In this course, we will be introducing the basics of programming using the Python language. Python is a powerful and versatile programming language that is widely used in a variety of fields, such as web development, scientific computing, data analysis, and artificial intelligence. One of the reasons why Python is so popular is because it is easy to read and write, and its syntax is simple and consistent. 4 | 5 | Throughout this course, we will be focusing on the fundamental concepts of programming rather than the specific syntax of the Python language. This means that we will **NOT** be teaching you the most optimal or efficient way to write Python code, but rather the basic concepts that you need to know in order to understand and write your own programs. 6 | 7 | You will learn how to use variables, control flow structures, loops, functions, Object Oriented programming, and how to work with data structures like lists and dictionaries. By the end of this course, you will have a solid understanding of the basic concepts of programming and will be able to write your own simple programs using Python and be able to take these general concepts to learn other programming languages as well. 8 | 9 | So, let's get started! 10 | 11 | This project/course consists primarily of two components: 12 | * Jupyter Notebooks outlining essential concepts in programming. These are stored in the `01-lesson_notebooks` directory. 13 | * A corresponding larger project exercise, intended to be built in an IDE (program assumes VS Code), is also included in the `02-IDE_excecises folder`. 14 | 15 | ## How to use the materials 16 | Lesson notebooks are arranged by topic denoted with a lesson number like `01a-...`, `03b-...`, or `09c-...` . Each notebook contains explanations and examples of the programming principle/concept for that section. Lesson notebooks have simple exercises that you can work out directly in the notebook itself. 17 | 18 | Each lesson set has a corresponding "IDE Exercise" with the same lesson number that relates to the set of notebooks i.e. `01-...`, `02a-...`, `10-...`, etc. These are projects with a larger scope that you should practice building within in your IDE. I'm generally assuming you're using VS Code as your IDE in the included notes. Each project folder has a `README`, included with the project exercise description. 19 | 20 | ## How to get started 21 | Navigate to the setup workbooks [00a-Mac_Setup.ipynb](01-lesson_notebooks/00a-Mac_Setup.ipynb) and/or the [00b-Windows_Setup.ipynb](01-lesson_notebooks/00b-Windows_Setup.ipynb) and follow the instructions to begin downloading the various tools we recommend. You can then checkout [01a-Some_Context.ipynb](01-lesson_notebooks/01a-Some_Context.ipynb) to get an understanding of the basics and WHY we downloaded the tools we that did. 22 | 23 | ## How you can contribute to the project 24 | There are many ways that people can help contribute to your project. One of the most important ways is by expanding on the explanations and descriptions provided in the project. This can include adding more detailed information and examples, creating diagrams and images to help illustrate key concepts, and providing additional resources and materials for users to reference. 25 | 26 | Another way that people can help contribute to your project is by adding project exercises and challenges. These can include coding challenges, quizzes, and other interactive activities that help users test their understanding of the concepts covered in the project. 27 | 28 | Another way to help is to proofreading and spell checking the project for any errors or typos. This will ensure that the project is easy to read and understand for users of all levels. 29 | 30 | Finally, adding unit tests for users to test their program is a great way to ensure that the program is working correctly and that users are able to understand the concepts covered in the project. 31 | 32 | Overall, there are many ways that people can help contribute to your project and make it a valuable resource for users. By working together and leveraging the skills and expertise of a diverse group of contributors, you can create a high-quality and effective project that helps users learn and grow. 33 | 34 | ## TODO: 35 | * [ ] Add exercise to count occurence of vowels in string 36 | * [ ] Add exercise to count occurence of set of strings in total strings 37 | * [ ] Add exercise that prints the longest substring of string s in which letters occur in alphabetical order 38 | * [ ] Finish 7b presentation... 39 | * [ ] Finish 7b Notes by adding the pictures 40 | * [ ] Add tests for IDE project solutions 41 | * [ ] Update embedded images in Jupyter notebooks. [Reference](https://stackoverflow.com/questions/32370281/how-to-embed-image-or-picture-in-jupyter-notebook-either-from-a-local-machine-o) 42 | 43 | -------------------------------------------------------------------------------- /install_dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if python -c 'import sys; assert sys.version_info >= (3,11)' > /dev/null; then 4 | 5 | # update necessary python resources at global level 6 | python -m pip install --upgrade setuptools wheel pip 7 | 8 | # setup and activate virtual environment 9 | python -m venv .venv 10 | source "./.venv/bin/activate" && python -m pip install --upgrade setuptools wheel pip 11 | 12 | if [ -f requirements.txt ]; then 13 | # install from requirements 14 | python -m pip install -r requirements.txt 15 | 16 | fi 17 | 18 | else 19 | 20 | echo "python version should be >= 3.11" 21 | 22 | fi 23 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | notebook==6.5.2 --------------------------------------------------------------------------------