From 2998a257576d008888ea35aa482a776b5210810e Mon Sep 17 00:00:00 2001 From: Edoardo Baldi Date: Fri, 14 Nov 2025 10:48:55 +0100 Subject: [PATCH] Add extra notebook from 2025-11-14 Add the "Python Insights" notebook that we discussed on the Intro Tutorial in November 2025 --- extra/07_some_python_insights.ipynb | 408 ++++++++++++++++++++++++++++ 1 file changed, 408 insertions(+) create mode 100644 extra/07_some_python_insights.ipynb diff --git a/extra/07_some_python_insights.ipynb b/extra/07_some_python_insights.ipynb new file mode 100644 index 00000000..96a93229 --- /dev/null +++ b/extra/07_some_python_insights.ipynb @@ -0,0 +1,408 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "0", + "metadata": {}, + "source": [ + "# Python Insights 🤓" + ] + }, + { + "cell_type": "markdown", + "id": "1", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "## Why intervals are open-ended in Python?" + ] + }, + { + "cell_type": "markdown", + "id": "2", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "Half-open intervals `[start:end)` with 0-based indexing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3", + "metadata": {}, + "outputs": [], + "source": [ + "lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']\n", + "lst" + ] + }, + { + "cell_type": "markdown", + "id": "4", + "metadata": {}, + "source": [ + "### 1. Length is just end - start" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5", + "metadata": {}, + "outputs": [], + "source": [ + "lst[1:4] # ['b', 'c', 'd'] — length is 4-1 = 3" + ] + }, + { + "cell_type": "markdown", + "id": "6", + "metadata": {}, + "source": [ + "### 2. Consecutive slices don't overlap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7", + "metadata": {}, + "outputs": [], + "source": [ + "lst[0:3] # ['a', 'b', 'c']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8", + "metadata": {}, + "outputs": [], + "source": [ + "lst[3:6] # ['d', 'e', 'f']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9", + "metadata": {}, + "outputs": [], + "source": [ + "lst[6:9] # ['g', 'h', 'i']" + ] + }, + { + "cell_type": "markdown", + "id": "10", + "metadata": {}, + "source": [ + "### 3. First n elements is clean" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11", + "metadata": {}, + "outputs": [], + "source": [ + "n = 5\n", + "lst[:n] # ['a', 'b', 'c', 'd', 'e'] — exactly n elements" + ] + }, + { + "cell_type": "markdown", + "id": "12", + "metadata": {}, + "source": [ + "### 4. Empty slices make sense" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13", + "metadata": {}, + "outputs": [], + "source": [ + "lst[3:3] # [] — naturally empty" + ] + }, + { + "cell_type": "markdown", + "id": "14", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "## What happens inside a `for` and `while` loops?" + ] + }, + { + "cell_type": "markdown", + "id": "15", + "metadata": {}, + "source": [ + "**Remember:** in Python, `for item in container` allows you to assign the `item` variable to **every single element** that `container` holds.\n", + "One at a time.\n", + "\n", + "We call these container objects **iterables**." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "16", + "metadata": {}, + "outputs": [], + "source": [ + "fruits = [\"apple\", \"banana\", \"cherry\"] # a list, a tuple, a string, a dictionary, a set... are all iterables\n", + "count = 0\n", + "\n", + "for fruit in fruits:\n", + " count += 1\n", + " print(f\"Item {count}: {fruit}\")\n", + "\n", + "print(f\"Total fruits: {count}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17", + "metadata": {}, + "outputs": [], + "source": [ + "for index, fruit = enumerate(fruits):\n", + " print(index, fruit)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18", + "metadata": {}, + "outputs": [], + "source": [ + "a, b, c = 1, 2, 3" + ] + }, + { + "cell_type": "markdown", + "id": "19", + "metadata": {}, + "source": [ + "Let's try to \"visualize\" what happens with the [Python Tutor](https://pythontutor.com/render.html#code=fruits%20%3D%20%5B%22apple%22,%20%22banana%22,%20%22cherry%22%5D%0Acount%20%3D%200%0A%0Afor%20fruit%20in%20fruits%3A%0A%20%20%20%20count%20%2B%3D%201%0A%20%20%20%20print%28f%22Item%20%7Bcount%7D%3A%20%7Bfruit%7D%22%29%0A%0Aprint%28f%22Total%20fruits%3A%20%7Bcount%7D%22%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false)" + ] + }, + { + "cell_type": "markdown", + "id": "20", + "metadata": {}, + "source": [ + "The same idea with a `while` loop" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21", + "metadata": {}, + "outputs": [], + "source": [ + "fruits = [\"apple\", \"banana\", \"cherry\"]\n", + "i = 0\n", + "\n", + "while i < len(fruits):\n", + " fruit = fruits[i]\n", + " print(f\"Item {i+1}: {fruit}\")\n", + " i += 1\n", + "\n", + "print(\"Done!\")" + ] + }, + { + "cell_type": "markdown", + "id": "22", + "metadata": {}, + "source": [ + "With the [Python Tutor](https://pythontutor.com/render.html#code=fruits%20%3D%20%5B%22apple%22,%20%22banana%22,%20%22cherry%22%5D%0Ai%20%3D%200%0A%0Awhile%20i%20%3C%20len%28fruits%29%3A%0A%20%20%20%20fruit%20%3D%20fruits%5Bi%5D%0A%20%20%20%20print%28f%22Item%20%7Bi%2B1%7D%3A%20%7Bfruit%7D%22%29%0A%20%20%20%20i%20%2B%3D%201%0A%0Aprint%28%22Done!%22%29&cumulative=false&curInstr=0&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false)" + ] + }, + { + "cell_type": "markdown", + "id": "23", + "metadata": {}, + "source": [ + "### One example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24", + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [1, 2, 3]\n", + "result = []\n", + "\n", + "for num in numbers:\n", + " result.append(num * 2)\n", + " print(f\"Num is: {num}\")\n", + "\n", + "print(f\"Numbers (list): {numbers}\") # What do you think are the values of numbers?\n", + "print(result)" + ] + }, + { + "cell_type": "markdown", + "id": "25", + "metadata": {}, + "source": [ + "## Some live coding together" + ] + }, + { + "cell_type": "markdown", + "id": "26", + "metadata": {}, + "source": [ + "### Remove vowels" + ] + }, + { + "cell_type": "markdown", + "id": "27", + "metadata": {}, + "source": [ + "From Leetle, 2 July 2025\n", + "\n", + "Write a function that takes a string and returns a new string with all vowels (a, e, i, o, u) removed.\n", + "Both uppercase and lowercase vowels should be removed.\n", + "\n", + "Examples:\n", + "- Input: `\"hello, world!\"`\n", + "- Output: `\"hll, wrld!\"`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28", + "metadata": {}, + "outputs": [], + "source": [ + "def solve(message: str) -> str:\n", + " vowels = \"aeiouAEIOU\"\n", + " result = \"\"\n", + " for char in message:\n", + " if char not in vowels:\n", + " result += char\n", + " return result" + ] + }, + { + "cell_type": "markdown", + "id": "29", + "metadata": {}, + "source": [ + "### Old phones keyboards" + ] + }, + { + "cell_type": "markdown", + "id": "30", + "metadata": {}, + "source": [ + "From Leetle, 8 August 2025\n", + "\n", + "Write a function that decodes old phone keypad text input.\n", + "Each number represents letters: `2=ABC`, `3=DEF`, `4=GHI`, `5=JKL`, `6=MNO`, `7=PQRS`, `8=TUV`, `9=WXYZ`.\n", + "Multiple presses select the letter (`22=B`, `777=R`).\n", + "Space separates different letters on same key." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31", + "metadata": {}, + "outputs": [], + "source": [ + "def solve(string: str) -> str:\n", + " keypad = {\n", + " \"2\": \"ABC\", \"3\": \"DEF\", \"4\": \"GHI\", \"5\": \"JKL\",\n", + " \"6\": \"MNO\", \"7\": \"PQRS\", \"8\": \"TUV\", \"9\": \"WXYZ\",\n", + " }\n", + " result = \"\"\n", + " for word in string.split():\n", + " press = len(word) - 1\n", + " number = keypad[word[0]]\n", + " result += keypad[number][press]\n", + " return result" + ] + }, + { + "cell_type": "markdown", + "id": "32", + "metadata": {}, + "source": [ + "### Sum until a single digit" + ] + }, + { + "cell_type": "markdown", + "id": "33", + "metadata": {}, + "source": [ + "From Leetle, 3 May 2025\n", + "\n", + "Write a function that repeatedly sums the digits of a number until a single digit is obtained.\n", + "\n", + "Examples:\n", + "\n", + "| Input | Output | Steps |\n", + "| --- | --- | --- |\n", + "| 16 | 7 | 6+1 = 7 |\n", + "| 546 | 6 | 5+4+6 = 15 then 1+5 = 6 |" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34", + "metadata": {}, + "outputs": [], + "source": [ + "def solve(number: int) -> int:\n", + " ..." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}