{ "cells": [ { "cell_type": "markdown", "id": "fbb4d5a2", "metadata": { "id": "fbb4d5a2" }, "source": [ "# Code from Downey's _Think Python_\n", "\n", "This notebook contains code for examples and exercises from chapter 4,\n", "_Functions and Interfaces_ of Allen Downey's\n", "_Think Python Third Edition_ (O'Reilly, 2024) using turtle graphics.\n", "\n", "I removed the main text, keeping only the section titles to make it easier to locate the code in the book.\n", "I also added some very brief comments for context." ] }, { "cell_type": "markdown", "id": "0b0efa00", "metadata": { "id": "0b0efa00" }, "source": [ "## The Turtle module\n", "\n", "Import the `Turtle` class:" ] }, { "cell_type": "code", "execution_count": 1, "id": "8f5a8a45", "metadata": { "id": "8f5a8a45" }, "outputs": [], "source": [ "from jupyturtle import Turtle" ] }, { "cell_type": "markdown", "id": "8c801121", "metadata": { "id": "8c801121" }, "source": [ "Create `Turtle` object, use a method:" ] }, { "cell_type": "code", "execution_count": 2, "id": "b3f255cd", "metadata": { "id": "b3f255cd", "outputId": "deb4d489-1a62-47ef-d6bf-39617641f591" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "9c8af26412904a2cbe520966b6dde35a", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "t = Turtle()\n", "t.forward(100)" ] }, { "cell_type": "markdown", "id": "77a61cbb", "metadata": { "id": "77a61cbb" }, "source": [ "Shortcuts for exploratory programming with an imperative API:" ] }, { "cell_type": "code", "execution_count": 3, "id": "234fde81", "metadata": { "id": "234fde81" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "2d39de4651ac4bce9c06e748a11d4706", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyturtle import fd\n", "fd(100)" ] }, { "cell_type": "markdown", "id": "c1322d31", "metadata": { "id": "c1322d31" }, "source": [ "The `fd()` call created a new turtle and drawing.\n", "Further commands will update that same drawing." ] }, { "cell_type": "markdown", "id": "bd319754", "metadata": { "id": "bd319754" }, "source": [ "Import more functions:" ] }, { "cell_type": "code", "execution_count": 4, "id": "6d874b03", "metadata": { "id": "6d874b03" }, "outputs": [], "source": [ "from jupyturtle import lt, rt, fd" ] }, { "cell_type": "markdown", "id": "0da2a311", "metadata": { "id": "0da2a311" }, "source": [ "Experiment with `left`, aliased to `lt`." ] }, { "cell_type": "code", "execution_count": 5, "id": "1bb57a0c", "metadata": { "id": "1bb57a0c", "outputId": "7c5c99bb-d1c1-4e70-8eeb-60dd7e4d9976" }, "outputs": [], "source": [ "fd(50)\n", "lt(90)\n", "fd(50)" ] }, { "cell_type": "markdown", "id": "e20ea96c", "metadata": { "id": "e20ea96c" }, "source": [ "## Making a square" ] }, { "cell_type": "code", "execution_count": 6, "id": "9a9e455f", "metadata": { "id": "9a9e455f", "outputId": "b2f6fc88-1ae0-4058-94ab-b11fb7278169" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "46803f8f54714197a811cf39fb339a6f", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyturtle import make_turtle, forward, left\n", "\n", "make_turtle()\n", "\n", "forward(50)\n", "left(90)\n", "\n", "forward(50)\n", "left(90)\n", "\n", "forward(50)\n", "left(90)\n", "\n", "forward(50)\n", "left(90)" ] }, { "cell_type": "markdown", "id": "a7500957", "metadata": { "id": "a7500957" }, "source": [ "Using a `for` loop." ] }, { "cell_type": "code", "execution_count": 7, "id": "cc27ad66", "metadata": { "id": "cc27ad66", "outputId": "d13253a3-9547-49a5-8181-38994a7d9bcf" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "de397c03eafb4d15a944c4c0d22492af", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle()\n", "for i in range(4):\n", " forward(50)\n", " left(90)" ] }, { "cell_type": "markdown", "id": "c072ea41", "metadata": { "id": "c072ea41" }, "source": [ "## Encapsulation and generalization\n", "\n", "Write function" ] }, { "cell_type": "code", "execution_count": 8, "id": "ad5f1128", "metadata": { "id": "ad5f1128" }, "outputs": [], "source": [ "def square():\n", " for i in range(4):\n", " forward(50)\n", " left(90)" ] }, { "cell_type": "markdown", "id": "0789b5d9", "metadata": { "id": "0789b5d9" }, "source": [ "Call it." ] }, { "cell_type": "code", "execution_count": 9, "id": "193bbe5e", "metadata": { "id": "193bbe5e", "outputId": "685b50ca-1d40-43e6-c9d0-c04eb3384e9c" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "953998c6361740c5bc21c39cacb98772", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle()\n", "square()" ] }, { "cell_type": "markdown", "id": "da905fc6", "metadata": { "id": "da905fc6" }, "source": [ "Function with parameter" ] }, { "cell_type": "code", "execution_count": 10, "id": "def8a5f1", "metadata": { "id": "def8a5f1" }, "outputs": [], "source": [ "def square(length):\n", " for i in range(4):\n", " forward(length)\n", " left(90)" ] }, { "cell_type": "markdown", "id": "397fda4b", "metadata": { "id": "397fda4b" }, "source": [ "Now we can draw squares with different sizes." ] }, { "cell_type": "code", "execution_count": 11, "id": "b283e795", "metadata": { "id": "b283e795", "outputId": "f1681b48-b958-430c-fa9d-2290dcb64e85" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d6188170474246e4bdad15799cdd9484", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle()\n", "square(30)\n", "square(60)" ] }, { "cell_type": "markdown", "id": "5a46bf64", "metadata": { "id": "5a46bf64" }, "source": [ "Generalization:" ] }, { "cell_type": "code", "execution_count": 12, "id": "171974ed", "metadata": { "id": "171974ed" }, "outputs": [], "source": [ "def polygon(n, length):\n", " angle = 360 / n\n", " for i in range(n):\n", " forward(length)\n", " left(angle)" ] }, { "cell_type": "markdown", "id": "286d3c77", "metadata": { "id": "286d3c77" }, "source": [ "Example:" ] }, { "cell_type": "code", "execution_count": 13, "id": "71f7d9d2", "metadata": { "id": "71f7d9d2", "outputId": "b9160d99-658e-4933-f17e-1ecf02c9a6fa" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "32cd065a3e404b66b82c3a8481d5282a", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle()\n", "polygon(7, 30)" ] }, { "cell_type": "markdown", "id": "dc0226db", "metadata": { "id": "dc0226db" }, "source": [ "Named arguments:" ] }, { "cell_type": "code", "execution_count": 14, "id": "8ff2a5f4", "metadata": { "id": "8ff2a5f4", "outputId": "4b4a744d-bf00-4d1e-feba-9f4174506318", "tags": [ "remove-output" ] }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "851053a66a5a44699694d37936427bac", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle()\n", "polygon(n=7, length=30)" ] }, { "cell_type": "markdown", "id": "b10184b4", "metadata": { "id": "b10184b4" }, "source": [ "## Approximating a circle\n", "\n", "To draw a circle:" ] }, { "cell_type": "code", "execution_count": 15, "id": "7f2a5f28", "metadata": { "id": "7f2a5f28" }, "outputs": [], "source": [ "import math\n", "\n", "def circle(radius):\n", " circumference = 2 * math.pi * radius\n", " n = 30\n", " length = circumference / n\n", " polygon(n, length)" ] }, { "cell_type": "markdown", "id": "39023314", "metadata": { "id": "39023314" }, "source": [ "The `delay` argument (named `speed` in ColabTurtle):" ] }, { "cell_type": "code", "execution_count": 16, "id": "75258056", "metadata": { "id": "75258056", "outputId": "9cbf7b6a-c5e7-433e-a14f-2b275e9e9f05" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "7ac0533e488d45e5bb01ff39fea1f9f3", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle(delay=0.05)\n", "circle(30)" ] }, { "cell_type": "markdown", "id": "c48f262c", "metadata": { "id": "c48f262c" }, "source": [ "## Refactoring\n", "\n", "`polyline`, a more general version of `polygon`:" ] }, { "cell_type": "code", "execution_count": 17, "id": "381edd23", "metadata": { "id": "381edd23" }, "outputs": [], "source": [ "def polyline(n, length, angle):\n", " for i in range(n):\n", " forward(length)\n", " left(angle)" ] }, { "cell_type": "markdown", "id": "c2b2503e", "metadata": { "id": "c2b2503e" }, "source": [ "Parameters:\n", "\n", "`n`: number of segments to draw\n", "\n", "`length`: length each segment\n", "\n", "`angle`: angle between them\n", "\n", "New `polygon` using `polyline`:" ] }, { "cell_type": "code", "execution_count": 18, "id": "2f4eecc0", "metadata": { "id": "2f4eecc0" }, "outputs": [], "source": [ "def polygon(n, length):\n", " angle = 360.0 / n\n", " polyline(n, length, angle)" ] }, { "cell_type": "markdown", "id": "2714a59e", "metadata": { "id": "2714a59e" }, "source": [ "Use `polyline` to write `arc`:" ] }, { "cell_type": "code", "execution_count": 19, "id": "539466f6", "metadata": { "id": "539466f6" }, "outputs": [], "source": [ "def arc(radius, angle):\n", " arc_length = 2 * math.pi * radius * angle / 360\n", " n = 30\n", " length = arc_length / n\n", " step_angle = float(angle) / n\n", " polyline(n, length, step_angle)" ] }, { "cell_type": "markdown", "id": "3c18773c", "metadata": { "id": "3c18773c" }, "source": [ "Rewrite `circle` to use `arc`:" ] }, { "cell_type": "code", "execution_count": 20, "id": "8e09f456", "metadata": { "id": "8e09f456" }, "outputs": [], "source": [ "def circle(radius):\n", " arc(radius, 360)" ] }, { "cell_type": "markdown", "id": "313a357c", "metadata": { "id": "313a357c" }, "source": [ "To check that these functions work as expected, we'll use them to draw something like a snail." ] }, { "cell_type": "code", "execution_count": 21, "id": "80d6eadd", "metadata": { "id": "80d6eadd", "outputId": "7568b421-69a5-4e3d-c369-e706f92b2e7e" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "3b745f4e02de4446ac5cdf282e84cda7", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle(delay=0.01)\n", "polygon(n=20, length=9)\n", "arc(radius=70, angle=70)\n", "circle(radius=10)" ] }, { "cell_type": "markdown", "id": "d18c9d16", "metadata": { "id": "d18c9d16" }, "source": [ "## Stack diagram\n", "\n", "(no turtle examples in this section)" ] }, { "cell_type": "markdown", "id": "3e3bae20", "metadata": { "id": "3e3bae20" }, "source": [ "## Docstrings\n", "\n", "`polyline` with docstring:" ] }, { "cell_type": "code", "execution_count": 22, "id": "b68f3682", "metadata": { "id": "b68f3682" }, "outputs": [], "source": [ "def polyline(n, length, angle):\n", " \"\"\"Draws line segments with the given length and angle between them.\n", "\n", " n: integer number of line segments\n", " length: length of the line segments\n", " angle: angle between segments (in degrees)\n", " \"\"\"\n", " for i in range(n):\n", " forward(length)\n", " left(angle)" ] }, { "cell_type": "code", "execution_count": 23, "id": "1182531b-8252-4389-a6b4-58adec2fc19b", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "0a9c81ff7deb4040bc38e2a7de05f67a", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle()\n", "polyline(9, 30, 36)" ] }, { "cell_type": "markdown", "id": "f1115940", "metadata": { "id": "f1115940" }, "source": [ "## Debugging\n", "\n", "(no turtle examples in this section)" ] }, { "cell_type": "markdown", "id": "a4d33a70", "metadata": { "id": "a4d33a70" }, "source": [ "## Glossary\n", "\n", "(no turtle examples in this section)" ] }, { "cell_type": "markdown", "id": "50ed5c38", "metadata": { "id": "50ed5c38" }, "source": [ "## Exercises\n", "\n", "`penup` and `pendown`" ] }, { "cell_type": "code", "execution_count": 24, "id": "6f9a0106", "metadata": { "id": "6f9a0106" }, "outputs": [], "source": [ "from jupyturtle import forward, penup, pendown\n", "\n", "def jump(length):\n", " \"\"\"Move forward length units without leaving a trail.\n", "\n", " Postcondition: Leaves the pen down.\n", " \"\"\"\n", " penup()\n", " forward(length)\n", " pendown()" ] }, { "cell_type": "markdown", "id": "c78c1e17", "metadata": { "id": "c78c1e17" }, "source": [ "### Exercise\n", "\n", "Draw a rectangle:" ] }, { "cell_type": "code", "execution_count": 25, "id": "c54ba660", "metadata": { "id": "c54ba660" }, "outputs": [], "source": [ "# Solution\n", "\n", "def rectangle(length1, length2):\n", " \"\"\"Draw a rectangle with the given lengths.\n", "\n", " length1: length of the first side\n", " length2: length of the second size\n", " \"\"\"\n", " for i in range(2):\n", " forward(length1)\n", " left(90)\n", " forward(length2)\n", " left(90)" ] }, { "cell_type": "code", "execution_count": 26, "id": "1311ee08", "metadata": { "id": "1311ee08", "outputId": "f73e1eaf-e057-4099-8d25-45fc326b491a" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "7bb72c2d989341ebb656b8fcc7143640", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle()\n", "rectangle(80, 40)" ] }, { "cell_type": "markdown", "id": "8b8faaf6", "metadata": { "id": "8b8faaf6" }, "source": [ "### Exercise\n", "\n", "Draw a rhombus:" ] }, { "cell_type": "code", "execution_count": 27, "id": "3db6f106", "metadata": { "id": "3db6f106" }, "outputs": [], "source": [ "def rhombus(length, angle):\n", " for i in range(2):\n", " forward(length)\n", " left(angle)\n", " forward(length)\n", " left(180-angle)" ] }, { "cell_type": "code", "execution_count": 28, "id": "1d845de9", "metadata": { "id": "1d845de9", "outputId": "66e0bd71-a207-482a-c855-184f9603b6b5" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "308730ffc65240fc8b51d01fd3db3c85", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle()\n", "rhombus(50, 60)" ] }, { "cell_type": "markdown", "id": "a9175a90", "metadata": { "id": "a9175a90" }, "source": [ "### Exercise\n", "\n", "Write `parallelogram`, then rewrite `rectangle` and `rhombus` to use it:" ] }, { "cell_type": "code", "execution_count": 29, "id": "895005cb", "metadata": { "id": "895005cb" }, "outputs": [], "source": [ "# Solution\n", "\n", "def parallelogram(length1, length2, angle):\n", " for i in range(2):\n", " forward(length1)\n", " left(angle)\n", " forward(length2)\n", " left(180-angle)" ] }, { "cell_type": "code", "execution_count": 30, "id": "7e7d34b0", "metadata": { "id": "7e7d34b0" }, "outputs": [], "source": [ "# Solution\n", "\n", "def rectangle(length1, length2):\n", " \"\"\"Draw a rectangle with the given lengths.\n", "\n", " length1: length of the first side\n", " length2: length of the second size\n", " \"\"\"\n", " parallelogram(length1, length2, 90)" ] }, { "cell_type": "code", "execution_count": 31, "id": "481396f9", "metadata": { "id": "481396f9" }, "outputs": [], "source": [ "# Solution\n", "\n", "def rhombus(length, angle):\n", " parallelogram(length, length, angle)" ] }, { "cell_type": "code", "execution_count": 32, "id": "c8dfebc9", "metadata": { "id": "c8dfebc9", "outputId": "a6b35bd8-69c7-44ed-cb5f-c540b8abacd8" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d7c73a390c704391a6a83e0dda2cf49b", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle(delay=0.05)\n", "jump(-120)\n", "\n", "rectangle(80, 40)\n", "jump(100)\n", "rhombus(50, 60)\n", "jump(80)\n", "parallelogram(80, 50, 60)" ] }, { "cell_type": "markdown", "id": "b9bd3ad7-f086-4470-82a5-8a3a82593719", "metadata": {}, "source": [ "### Exercise\n", "\n", "A `triangle` function:\n" ] }, { "cell_type": "code", "execution_count": 33, "id": "8be6442e", "metadata": { "id": "8be6442e" }, "outputs": [], "source": [ "# Solution\n", "import math\n", "\n", "from jupyturtle import forward, left, right\n", "\n", "def triangle(radius, angle):\n", " \"\"\"Draws an icosceles triangle.\n", "\n", " The turtle starts and ends at the peak, facing the middle of the base.\n", "\n", " radius: length of the equal legs\n", " angle: half peak angle in degrees\n", " \"\"\"\n", " y = radius * math.sin(angle * math.pi / 180)\n", "\n", " right(angle)\n", " forward(radius)\n", " left(90+angle)\n", " forward(2*y)\n", " left(90+angle)\n", " forward(radius)\n", " left(180-angle)" ] }, { "cell_type": "markdown", "id": "b8aeab81-bc97-400c-917f-bc962d834cb5", "metadata": {}, "source": [ "(a little demonstration)" ] }, { "cell_type": "code", "execution_count": 34, "id": "2666dcde", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "c41f7318131242e09e89f5f081f96761", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from jupyturtle import make_turtle, hide\n", "make_turtle()\n", "hide()\n", "\n", "for i in range(12):\n", " triangle(50, 10)\n", " left(30)" ] }, { "cell_type": "code", "execution_count": 35, "id": "be1b7ed8", "metadata": { "id": "be1b7ed8" }, "outputs": [], "source": [ "# Solution\n", "\n", "def draw_pie(n, radius):\n", " \"\"\"Draws a pie divided into radial segments.\n", "\n", " n: number of segments\n", " radius: length of the radial spokes\n", " \"\"\"\n", " angle = 360.0 / n\n", " for i in range(n):\n", " triangle(radius, angle/2)\n", " left(angle)" ] }, { "cell_type": "code", "execution_count": 36, "id": "9b1f5a1e", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "fc2e3a030d3a4538811b569afe4ea8b6", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle(delay=0.01)\n", "draw_pie(5, 40)" ] }, { "cell_type": "code", "execution_count": 37, "id": "89ce198a", "metadata": { "id": "89ce198a", "outputId": "252a28de-d853-4851-abb0-525ea33c0998" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "0e4e9feb8c584b97869330c3bf7b9e79", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle(delay=0.01)\n", "jump(-120)\n", "\n", "size = 40\n", "draw_pie(5, size)\n", "jump(2*size)\n", "draw_pie(6, size)\n", "jump(2*size)\n", "draw_pie(7, size)\n", "jump(2*size)\n", "draw_pie(8, size)" ] }, { "cell_type": "markdown", "id": "7c665dd1", "metadata": { "id": "7c665dd1" }, "source": [ "### Exercise\n", "\n", "Draw flowers with `petal`:" ] }, { "cell_type": "code", "execution_count": 38, "id": "0f0e7498", "metadata": { "id": "0f0e7498" }, "outputs": [], "source": [ "# Solution\n", "\n", "def petal(radius, angle):\n", " \"\"\"Draws a petal using two arcs.\n", "\n", " t: Turtle\n", " radius: radius of the arcs\n", " angle: angle (degrees) that subtends the arcs\n", " \"\"\"\n", " for i in range(2):\n", " arc(radius, angle)\n", " left(180-angle)" ] }, { "cell_type": "code", "execution_count": 39, "id": "6c0d0bff", "metadata": { "id": "6c0d0bff" }, "outputs": [], "source": [ "# Solution\n", "\n", "def flower(n, radius, angle):\n", " \"\"\"Draws a flower with n petals.\n", "\n", " n: number of petals\n", " radius: radius of the arcs\n", " angle: angle (degrees) that subtends the arcs\n", " \"\"\"\n", " for i in range(n):\n", " petal(radius, angle)\n", " left(360/n)" ] }, { "cell_type": "code", "execution_count": 40, "id": "2f4b4c22-198d-4e30-8d38-68d04023309a", "metadata": { "id": "4cfea3b0", "outputId": "cb03438b-e82a-4c35-97dc-884bfde25056" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e0952c7e48e64744a79bd68ded3ad53a", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle(delay=0.01)\n", "\n", "jump(-100)\n", "flower(7, 60.0, 60.0)\n", "\n", "jump(100)\n", "flower(10, 40.0, 80.0)" ] }, { "cell_type": "markdown", "id": "e546cb2d-7968-42e7-a81b-ba22635d799f", "metadata": {}, "source": [ "Hiding the turtle reduces the number of elements in the drawing, so it renders faster with each step." ] }, { "cell_type": "code", "execution_count": 41, "id": "1e1c01b1-c4a4-4f6a-9bd8-05da8dd8f027", "metadata": { "id": "4cfea3b0", "outputId": "cb03438b-e82a-4c35-97dc-884bfde25056" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "23d7e226a5844a6eae4161d4196f954d", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "make_turtle(delay=0.01) # start a new drawing\n", "hide() # don't draw the turtle\n", "jump(100)\n", "flower(14, 140.0, 20.0)" ] }, { "cell_type": "markdown", "id": "9d9f35d1", "metadata": { "id": "9d9f35d1" }, "source": [ "### Ask an assistant\n", "\n", "Draw a spiral:" ] }, { "cell_type": "code", "execution_count": 42, "id": "46d3151c", "metadata": { "id": "46d3151c", "outputId": "47731432-91f7-4efc-d6da-077dd95234f8" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "56a822fb301240af9e3bd868bf446cf9", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Solution\n", "\n", "from jupyturtle import make_turtle, forward, right\n", "\n", "make_turtle()\n", "\n", "def spiral(length, angle):\n", " for _ in range(100):\n", " forward(length)\n", " right(angle)\n", " length += 2 # Increase the length for each segment\n", "\n", "spiral(5, 90)" ] }, { "cell_type": "code", "execution_count": 43, "id": "186c7fbc", "metadata": { "id": "186c7fbc", "outputId": "45628c53-a3b4-482e-dbf0-32a4ac0edaf9" }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d7fd41d1288c423489353a4797c92888", "version_major": 2, "version_minor": 0 }, "text/plain": [ "MultiCanvas(height=200, sync_image_data=True, width=400)" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "done\n" ] } ], "source": [ "# Solution\n", "\n", "# prompt: make that a circular spiral, and don't change the name of the module\n", "\n", "from jupyturtle import make_turtle, forward, left\n", "import math\n", "\n", "make_turtle(delay=0.01)\n", "\n", "def circular_spiral(radius, angle):\n", " rotations = 5\n", " distance = 2 * math.pi * radius / 360 # Calculate the distance for each degree of rotation\n", " for _ in range(rotations * 360):\n", " forward(distance)\n", " left(angle)\n", " radius += 0.1 # Increase the radius for each segment\n", " distance = 2 * math.pi * radius / 360 # Recalculate the distance for the updated radius\n", "\n", "# sometimes crashes chromium\n", "circular_spiral(50, 1)\n", "print('done')" ] }, { "cell_type": "code", "execution_count": null, "id": "0cd5b7e3-ccaf-4954-bca0-ccebd10bfbc7", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Tags", "colab": { "provenance": [] }, "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.12.2" } }, "nbformat": 4, "nbformat_minor": 5 }