{ "cells": [ { "cell_type": "markdown", "id": "468e25aa-24a4-4eaf-b4e0-c47792f38b1c", "metadata": { "tags": [] }, "source": [ "##### Python for High School (Summer 2022)\n", "\n", "* [Table of Contents](PY4HS.ipynb)\n", "* \"Open\n", "* [![nbviewer](https://raw.githubusercontent.com/jupyter/design/master/logos/Badges/nbviewer_badge.svg)](https://nbviewer.org/github/4dsolutions/elite_school/blob/master/Py4HS_July_12_2022.ipynb)" ] }, { "cell_type": "markdown", "id": "8d898b43-f9b3-4232-bf9c-bb9da6e8f9db", "metadata": {}, "source": [ "### Recap\n", "\n", "What have we been learning so far?\n", "\n", "Our focus has been the Python computer language and how to [make types](Py4HS_MakingTypes.ipynb) or classes. \n", "\n", "Once we have a couple Animal classes, we discover the power of [inheritance](https://www.w3schools.com/python/python_inheritance.asp): let your classes \"pass the buck\" sometimes, to a superclass that's already debugged and trusted. Why reinvent the wheel (or \"stomach\" or \"eat method\" as the case may be)?\n", "\n", "Let's take another look at the [Animals](https://replit.com/@kurner/Animals#main.py) on Replit." ] }, { "cell_type": "markdown", "id": "6389011b-2f13-4632-8dd8-fe67a9c55a55", "metadata": {}, "source": [ "Five Dimensions of Python:\n", "\n", "1. syntax and punctuation, keywords\n", "2. the builtins (like print, int, str... Exceptions)\n", "3. ```__ribs__``` i.e. special names (magic methods)\n", "4. Standard Library\n", "5. Ecosystem (3rd party packages such as numpy, pandas, django)" ] }, { "cell_type": "markdown", "id": "e7387c75-f8dd-4920-8693-61cd71a01868", "metadata": {}, "source": [ "These Jupyter Notebook and JupyterLab based ways of using Python, gaining in popularity, belong to level five.\n", "\n", "When we made a Dog type with a way to represent itself, the ways accessing level three features." ] }, { "cell_type": "markdown", "id": "1a66de9e-a93b-49f6-b805-af9ec1a67062", "metadata": {}, "source": [ "Cut and paste the code below to any Python source code editor, either on your local device or in the cloud. Play around with it. Add a new animal type." ] }, { "cell_type": "code", "execution_count": 1, "id": "ffc9310b-eac3-4c69-bda0-b2e9084d8304", "metadata": {}, "outputs": [], "source": [ "\"\"\"\n", "Used for Py4HS: Python for High School\n", "https://github.com/4dsolutions/elite_school/blob/master/PY4HS.ipynb\n", "\"\"\"\n", "\n", "from random import choice # used by Dog type\n", "\n", "class Animal:\n", " \"\"\"\n", " The parent class. The child classes will get\n", " their instructions from here if they do not \n", " find it in themselves (example: eat method).\n", " \"\"\"\n", " \n", " def __init__(self, nm): # Python provides a self\n", " \"\"\"\n", " the constructor method, a special name\n", " >>> new_python = Python(\"Shiela\")\n", " \"\"\"\n", " self.name = nm\n", " self.stomach = [ ]\n", " \n", " def eat(self, food):\n", " \"\"\"\n", " append to the stomach associated \n", " with this particular instance (self)\n", " \"\"\"\n", " self.stomach.append(food)\n", "\n", "class Dog(Animal):\n", " \"\"\"\n", " Another type\n", " \"\"\"\n", " tricks = ['Play dead', 'Fetch', 'Roll over']\n", " \n", " def do_trick(self):\n", " return choice(self.tricks)\n", " \n", " def __repr__(self):\n", " return f\"Dog named {self.name}\"\n", "\n", "class Python(Animal):\n", " \n", " def __repr__(self):\n", " # known as the repper\n", " return \"I'm a Python named \" + self.name\n", "\n", "class Pig(Animal):\n", " \"\"\"\n", " A type\n", " \"\"\"\n", " def __repr__(self):\n", " return f\"Pig named {self.name}\"" ] }, { "cell_type": "code", "execution_count": 2, "id": "fae87c4a-f180-421d-bc2d-1a6862686a59", "metadata": {}, "outputs": [], "source": [ "cyber_dog = Dog(\"Rover\")\n", "robo_dog = Dog(\"Fido\")" ] }, { "cell_type": "code", "execution_count": 3, "id": "faaf0a11-8f44-44ba-a8e9-8fb4508ebe10", "metadata": {}, "outputs": [], "source": [ "cyber_dog.eat(\"steak\")\n", "robo_dog.eat(\"crackers\")" ] }, { "cell_type": "code", "execution_count": 4, "id": "44e88b80-f07b-4272-bdc4-c25912df85b1", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['steak']" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cyber_dog.stomach" ] }, { "cell_type": "code", "execution_count": 5, "id": "1be52903-2edc-4d41-bf14-10b7e05e9863", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['steak', '🍩']" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cyber_dog.eat('🍩') # emoji are strings\n", "cyber_dog.stomach" ] }, { "cell_type": "markdown", "id": "5873222d-0e9e-47c1-bf4d-d5ef59a74d94", "metadata": {}, "source": [ "A complete understanding of our syntax so far also requires understanding string formatting, which includes the act of string substitution.\n", "\n", "Lets take some time to review some of those details." ] }, { "cell_type": "markdown", "id": "464d04ed-25f4-447e-94eb-6b930f26c5fa", "metadata": { "tags": [] }, "source": [ "### Rational Numbers\n", "\n", "Our next task is to develop a Rational Number type or class. We'll call it Rat, for Rational, but Rat also reminds us of the animal, which is intentional, because of our coding theme so far.\n", "\n", "Lets remember where the rationals fit into our hierarchy of numeric sets:\n", "* Counting Numbers, or set $\\mathbb{N}$ \n", "* Whole Numbers $\\mathbb{W}$ (add 0 to $\\mathbb{N}$)\n", "* Integers $\\mathbb{Z}$ (add negatives of positives)\n", "* Rationals $\\mathbb{Q}$ (integer:integer ratios)\n", "* Reals $\\mathbb{R}$ (no holes)\n", "* Complex numbers (add root of -1 to $\\mathbb{R}$)\n", "\n", "each a superset of the next previous.\n", "\n", "$$\n", "\\mathbb{N} \\subset \n", "\\mathbb{W} \\subset \n", "\\mathbb{Z} \\subset \n", "\\mathbb{Q} \\subset \n", "\\mathbb{R} \\subset \n", "\\mathbb{C}\n", "$$" ] }, { "cell_type": "markdown", "id": "94d83a2d-6a96-4e49-adb2-d70307ac7f43", "metadata": {}, "source": [ "Lets check a Rat class implementation on Replit.\n", "\n", "[Rat class on Replit](https://replit.com/@kurner/rationals#main.py)" ] }, { "cell_type": "code", "execution_count": 6, "id": "8c43f2a6-572e-4fcc-a449-4799c6d2f7b6", "metadata": {}, "outputs": [], "source": [ "from math import gcd\n", "\n", "class Rat:\n", "\n", " def __init__(self, n, d=None):\n", " \"\"\"\n", " Allow ints and other Rats to create new Rats\n", " not just the two ints, numerator and denominator\n", " \"\"\"\n", " if ( (type(n) == int and not d)\n", " or (type(n) == Rat and not d)):\n", " d = n.denominator\n", " n = n.numerator\n", " \n", " GCD = gcd(n, d)\n", " self.numerator = n // GCD \n", " self.denominator = d // GCD\n", "\n", " def __mul__(self, other):\n", " new_n = self.numerator * other.numerator\n", " new_d = self.denominator * other.denominator\n", " return Rat(new_n, new_d)\n", "\n", " def __add__(self, other):\n", " new_n = self.numerator * other.denominator + other.numerator * self.denominator\n", " new_d = self.denominator * other.denominator\n", " return Rat(new_n, new_d)\n", "\n", " def __neg__(self):\n", " return Rat(-self.numerator, self.denominator)\n", "\n", " def __sub__(self, other):\n", " return self + (- other)\n", "\n", " def __invert__(self):\n", " return Rat(self.denominator, self.numerator)\n", "\n", " def __truediv__(self, other):\n", " return self * ~other\n", "\n", " def __eq__(self, other):\n", " return ((self.numerator == other.numerator)\n", " and (self.denominator == other.denominator))\n", "\n", " def __repr__(self):\n", " return \"({} / {})\".format(self.numerator, self.denominator)\n", "\n", " def __float__(self):\n", " return self.numerator / self.denominator" ] }, { "cell_type": "code", "execution_count": 7, "id": "19b7e0b9-ca91-4eb8-ba96-f2f5837ba78e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1 / 2)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "q = Rat(1, 2)\n", "Rat(q)" ] }, { "cell_type": "code", "execution_count": 8, "id": "aa0d9625-7556-49b3-b00e-6b0c4cfce340", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "3 .denominator # the int type has these properties built in" ] }, { "cell_type": "markdown", "id": "81965834-b890-42c8-860b-914de42b4f66", "metadata": {}, "source": [ "Still missing from the above implementation: the ability to put the Rat to the right of the operator in question. We also don't yet have powering i.e. ```__pow__```. Even without these features, our Rat is fairly functional." ] }, { "cell_type": "markdown", "id": "2511a107-75ea-43e2-baf1-e24336f51150", "metadata": {}, "source": [ "### Fibonacci Numbers\n", "\n", "Number sequences figure centrally in this high school curriculum, as they do in so many. Figurate and polyhedral numbers, their gnomons and running totals, primes, Carmichael Numbers... all of these may be researched in [the Online Dictionary of Integer Sequences](https://oeis.org/)." ] }, { "cell_type": "markdown", "id": "9ec0faaa-c4de-449f-8cfc-bc84b286534c", "metadata": {}, "source": [ "What we will discover in this section is that $F[n+1]/F[n]$ where $F[n]$ and $F[n+1]$ are consecutive Fibonacci numbers, approaches ever closer to Phi as n increases.\n", "\n", "But first, we need a way to generate those Fibonacci numbers:" ] }, { "cell_type": "code", "execution_count": 9, "id": "36cef86a-773b-4889-a832-0f23836353de", "metadata": {}, "outputs": [], "source": [ "def fibo(a=0, b=1):\n", " while True:\n", " yield a\n", " a, b = b, a + b" ] }, { "cell_type": "markdown", "id": "3e2a9f98-74f9-4b16-95b7-bb91111a13b5", "metadata": {}, "source": [ "That's using the keyword `yeild`; have you seen that before? \n", "\n", "`yield` behaves a lot like return, in handing back an object and halting execution. \n", "\n", "However, unlike `return`, a generator function may resume right after the `yield` statement, when nudged by `next`. \n", "\n", "Let's take a look:" ] }, { "cell_type": "code", "execution_count": 10, "id": "b1578c65-1bec-4e41-8306-6ecbdce35554", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gen_fib = fibo() # create a generator object\n", "next(gen_fib) # run to the next yield" ] }, { "cell_type": "code", "execution_count": 11, "id": "fcefe659-87f7-44de-9f3e-212708d1371d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(gen_fib) # run to the next yield (same one)" ] }, { "cell_type": "code", "execution_count": 12, "id": "a8dde62d-5ab9-4153-b35b-57e12fafbce0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(gen_fib) # run to the next yield (looping)" ] }, { "cell_type": "code", "execution_count": 13, "id": "49d6f827-2687-4e56-a12c-ca8de77bcf0a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(gen_fib) # no limit on how many times we nudge" ] }, { "cell_type": "code", "execution_count": 14, "id": "716acb42-2a64-4c5f-a3b0-8373a287e849", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "next(gen_fib) # the Fibonacci series is coming out" ] }, { "cell_type": "code", "execution_count": 15, "id": "abcc954e-d1c1-4405-a932-fcd4d870bce1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n", "8\n", "13\n", "21\n", "34\n", "55\n", "89\n", "144\n", "233\n", "377\n" ] } ], "source": [ "for _ in range(10): # let speed up nudging with for\n", " print(next(gen_fib))" ] }, { "cell_type": "code", "execution_count": 16, "id": "cf5abab5-5fdb-4aac-ac5c-2f4133b1d92a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(987 / 610)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "denom, numer = next(gen_fib), next(gen_fib)\n", "ratio = Rat(numer, denom) # now build a fraction\n", "ratio" ] }, { "cell_type": "code", "execution_count": 17, "id": "69d75891-b91f-4269-a87a-ea8e5991c417", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.618032786885246" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "float(ratio)" ] }, { "cell_type": "markdown", "id": "ac7dcb94-ec3f-44b2-a186-88c866d02fed", "metadata": {}, "source": [ "The famous number we approach, as we keep getting bigger consecutive Fibonacci numbers, is named φ and pronounce \"fie\" (rhyming with \"fly\") by most people (a few say \"fee\", and no one says \"fum\" (joke)).\n", "\n", "\"pentatrig\"" ] }, { "cell_type": "markdown", "id": "b88d973f-4893-4666-a7c4-97bddc4444a6", "metadata": {}, "source": [ "The whole (1 + the part) is to 1, as 1 is to the part, what is that part? We can start with it being an unkown and write this equation, equating two ratios:" ] }, { "cell_type": "code", "execution_count": 18, "id": "a6366207-bf22-44b0-9ead-29ff706a0000", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle φ = \\frac{φ + 1}{φ}$" ], "text/plain": [ "Eq(φ, (φ + 1)/φ)" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import sympy as sp\n", "φ = sp.Symbol('φ')\n", "equation = sp.Eq(φ/1, (φ+1)/φ) # 1 is to φ as φ is to x + 1\n", "equation" ] }, { "cell_type": "markdown", "id": "a7760c4c-6ed6-4204-b973-574c12155ec9", "metadata": {}, "source": [ "In class I talked about cross multiplying and how the above would be the same as:" ] }, { "cell_type": "code", "execution_count": 19, "id": "190157ba-6c76-4894-83f4-e98b72804906", "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle 0 = φ^{2} - φ - 1$" ], "text/plain": [ "Eq(0, φ**2 - φ - 1)" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "same_equation = sp.Eq(0, φ**2 - φ - 1)\n", "same_equation" ] }, { "cell_type": "markdown", "id": "d094c410-3cfb-4816-b887-96fa14701413", "metadata": {}, "source": [ "This is what we call a polynomial of the 2nd degree, meaning the highest power monomial is 2. \n", "\n", "The goal is to find what values of $\\phi$ make it a true statement.\n", "\n", "sympy will help you with this." ] }, { "cell_type": "code", "execution_count": 20, "id": "d5b2a450-9698-4c5e-b46d-26da316ad98c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1/2 - sqrt(5)/2, 1/2 + sqrt(5)/2]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ans = sp.solve(equation)\n", "ans" ] }, { "cell_type": "code", "execution_count": 21, "id": "99470cdd-541d-43f7-9e98-d11ae9c11654", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1/2 - sqrt(5)/2, 1/2 + sqrt(5)/2]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "same_ans = sp.solve(same_equation)\n", "same_ans" ] }, { "cell_type": "markdown", "id": "1847b1cf-80c2-4518-ba86-143bd3b52231", "metadata": {}, "source": [ "How shall we visualize Phi?\n", "\n", "This arrangement of 3 segments scales up and down, meaning it's a ratio we are looking for -- but there's an additive aspect to this particular ratio.\n", "\n", "\"Flipped\n", "\n", "\"Phi\"" ] }, { "cell_type": "code", "execution_count": 22, "id": "9dfcc8a9-a949-4800-bce8-2ca78874319a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137484754088075386891752126633862223536931793180060766726354433389086595939582905638322661319928290267880675208766892501711696207032221043216269548626296313614438149758701220340805887954454749246185695364864449241044320771344947049565846788509874339442212544877066478091588460749988712400765217057517978834166256249407589069704000281210427621771117778053153171410117046665991466979873176135600670874807101317952368942752194843530567830022878569978297783478458782289110976250030269615617002504643382437764861028383126833037242926752631165339247316711121158818638513316203840052221657912866752946549068113171599343235973494985090409476213222981017261070596116456299098162905552085247903524060201727997471753427775927786256194320827505131218156285512224809394712341451702237358057727861600868838295230459264787801788992199027077690389532196819861514378031499741106926088674296226757560523172777520353613936\n" ] } ], "source": [ "print(ans[1].evalf(1000))" ] }, { "cell_type": "code", "execution_count": 23, "id": "3aa89ca6-edf8-4065-b139-0a3f5d22034a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.618033988749894848204586834365638117720309179805762862135448622705260462818902449707207204189391137484754088075386891752126633862223536931793180060766726354433389086595939582905638322661319928290267880675208766892501711696207032221043216269548626296313614438149758701220340805887954454749246185695364864449241044320771344947049565846788509874339442212544877066478091588460749988712400765217057517978834166256249407589069704000281210427621771117778053153171410117046665991466979873176135600670874807101317952368942752194843530567830022878569978297783478458782289110976250030269615617002504643382437764861028383126833037242926752631165339247316711121158818638513316203840052221657912866752946549068113171599343235973494985090409476213222981017261070596116456299098162905552085247903524060201727997471753427775927786256194320827505131218156285512224809394712341451702237358057727861600868838295230459264787801788992199027077690389532196819861514378031499741106926088674296226757560523172777520353613936\n" ] } ], "source": [ "print(sp.S.GoldenRatio.n(1000))" ] }, { "cell_type": "markdown", "id": "b07e2c14-dba5-4c52-b44f-2a0a3beebd64", "metadata": {}, "source": [ "### Continued Fractions and $\\phi$" ] }, { "cell_type": "code", "execution_count": 12, "id": "415e89eb-20b5-4c79-9cf1-535ba99b6ba7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.6180327868852458" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1+ 1/\n", " (1)))))))))))))))" ] }, { "cell_type": "code", "execution_count": 13, "id": "651d24c1-1268-4991-a614-bd201a868f10", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Fraction(1, 1)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from fractions import Fraction\n", "one = Fraction(1,1)\n", "one" ] }, { "cell_type": "code", "execution_count": 15, "id": "0d598c54-1fca-45dd-931b-35586792e3ce", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Fraction(987, 610)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one+ 1/\n", " (one)))))))))))))))" ] }, { "cell_type": "markdown", "id": "6fc5cf7c-082e-47cc-a06a-4035a287e74a", "metadata": {}, "source": [ "[Continued](GenPhi.ipynb)" ] } ], "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.9.12" } }, "nbformat": 4, "nbformat_minor": 5 }