{ "cells": [ { "cell_type": "raw", "metadata": {}, "source": [ "---\n", "title: \"Notebook 3: Python Basics via Pseudocode & Flowcharts\"\n", "subtitle: \"COMP 1150 โ€” Computer Science Concepts\"\n", "author: \"Brendan Shea, PhD\"\n", "date: last-modified\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/brendanpshea/computing_concepts_python/blob/main/v2/notebooks/COMP1150_NB03_PseudocodeFlowcharts.ipynb)\n", "[Download .ipynb](https://raw.githubusercontent.com/brendanpshea/computing_concepts_python/main/v2/notebooks/COMP1150_NB03_PseudocodeFlowcharts.ipynb) ยท [View on GitHub](https://github.com/brendanpshea/computing_concepts_python/blob/main/v2/notebooks/COMP1150_NB03_PseudocodeFlowcharts.ipynb)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "๐Ÿ“บ **Lecture video:** *(link coming soon)*\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Learning Outcomes\n", "\n", "By the end of this notebook, you will be able to:\n", "\n", "- **Create** variables and recognize the four core data types (`int`, `float`, `str`, `bool`)\n", "- **Build** expressions with arithmetic, comparison, and boolean operators\n", "- **Format** output with f-strings, escape characters, and string methods\n", "- **Convert** between types correctly and read input from a person\n", "- **Write** clear pseudocode and read a flowchart\n", "- **Follow** the workflow *problem โ†’ pseudocode โ†’ flowchart โ†’ Python* on a real problem\n", "- **Trace** a short program by hand, and use AI to pressure-test a plan you wrote yourself\n", "\n", "*Maps to course Learning Outcomes 5 (pseudocode & flowcharts) and 6 (writing Python to implement algorithms).*\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Welcome to the Emporium\n", "\n", "Tucked down a foggy lane, behind a window full of dusty curiosities, stands **Mirabel's Emporium of Practical Enchantments**. Inside you will find bottled luck, phoenix feathers sold by the quill, jars of moonpetal, and a cat who may or may not be furniture. The shop runs on two things: **stock** on the shelves and **coin** in the till โ€” silver **crowns** and copper **bits**, where 100 bits make 1 crown.\n", "\n", "**Mirabel Quill**, the proprietor, has a problem. Her apprentice, **Fen**, keeps the books by hand, by candlelight, late into the night โ€” and Fen, being human, makes mistakes. A miscounted shelf here, a fumbled bit of change there. Mirabel doesn't want the sums done *cleverly*. She wants them done **exactly, repeatably, the same way every time**.\n", "\n", "That is what this notebook is about. In Notebooks 1 and 2 you mostly *read* code. Here you start *writing* it โ€” and not by guessing. You'll learn the method this whole course runs on: **problem โ†’ pseudocode โ†’ flowchart โ†’ Python**. By the end you'll take a plain-English task from Mirabel and turn it into working code, step by deliberate step โ€” the way the shop's careful ledger-keeper, **Wren Hollow**, does it. Wren never touches the ledger until she has written down exactly what she means to do.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A Word You'll Use All Year: *Algorithm*\n", "\n", "When Mirabel asks for arithmetic done \"exactly, repeatably, the same way every time,\" she is โ€” without using the word โ€” asking for an **algorithm**. It is the single most important word in computer science, so let's make it precise.\n", "\n", "An **algorithm** is a finite list of clear, unambiguous steps that takes some **input**, does a definite amount of work, and produces an **output**. You already know dozens of them. A recipe is an algorithm. The long-division procedure you learned as a child is an algorithm. The steps Fen follows to count out change for a customer is an algorithm. A computer is simply a very fast, very literal machine for *carrying algorithms out* โ€” it never improvises, and it never gets bored.\n", "\n", "Computer scientists ask four things of a genuine algorithm:\n", "\n", "- **Definite** โ€” every step is precise. No \"season to taste,\" no \"do whatever seems best.\"\n", "- **Finite** โ€” it is a fixed list of steps, not an endless one.\n", "- **Terminating** โ€” it eventually *stops* and hands you an answer.\n", "- **Input and output** โ€” it takes something in and gives something back.\n", "\n", "Keep these four in your pocket. When something you write loops forever or gives a different answer each run, one of these four has slipped.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Two more ideas are worth holding onto. First, **one problem can have many algorithms.** There are dozens of ways to sort a shelf of labelled jars โ€” some quick, some slow โ€” and choosing well is much of what computer science is about (you'll meet this head-on in Notebook 7). Second, an algorithm is an *idea*, separate from any one programming language. Wren's method for splitting a cache of crystals among apprentices could be carried out in Python, in some other language, or by Fen with a pencil and a patient evening.\n", "\n", "That separation is the whole reason this notebook teaches a **workflow** instead of just Python syntax. You'll pin down the algorithm *first* โ€” in plain words and a picture โ€” and only then translate it into code.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ๐Ÿ’ญ Think About It โ€” Algorithms You Already Follow\n", "\n", "You just met the word *algorithm*: a precise sequence of steps that anyone โ€” or any machine โ€” can follow to get a result.\n", "\n", "- Describe an everyday routine (a recipe, getting ready in the morning, giving someone directions) as an algorithm. Where is it precise, and where does it secretly rely on human judgment?\n", "- A good algorithm leaves no step to guesswork. Why is \"leave nothing to interpretation\" so much harder than it sounds when the follower is a machine instead of a person?\n", "- \"Social media algorithms\" are in the news constantly. Based on what the word actually means, what do you think people are really worried about when they complain about them?\n", "\n", "There are no single right answers here โ€” share a sentence or two on each." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Roadmap\n", "\n", "| Part | What you'll pick up |\n", "|---|---|\n", "| Variables & types | How a program stores a value, and what *kind* of value it is |\n", "| Operators & expressions | Arithmetic, comparison, and combining true/false conditions |\n", "| Input & output | How a program talks to a person โ€” and the #1 beginner bug |\n", "| Printing well | Escape characters, f-string formatting, string methods |\n", "| The workflow | Problem โ†’ pseudocode โ†’ flowchart โ†’ Python, start to finish |\n", "| Building with AI | Plan by hand, let the AI critique your plan, then build |\n", "\n", "**One scope note.** Every program in this notebook runs **straight down, top to bottom** โ€” no choices, no repetition. *Decisions* (`if`) and *repetition* (loops) are Notebook 4. We'll point at that door near the end, but we won't walk through it yet.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### How to Use This Notebook\n", "\n", "This is a **tinkering** notebook, not a reading one. Most code cells open with a block like this:\n", "\n", "```python\n", "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "crowns = 50\n", "```\n", "\n", "Change the numbers, press **Shift + Enter**, and watch what happens. Poking at a working example is how the ideas actually stick โ€” far more than reading about them. Each new section also ends with a small **โœ๏ธ Your Turn** cell where you write a little code of your own. Don't skip those; they're the point.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Variables: Named Boxes\n", "\n", "Before a program can *do* anything with a value, it needs somewhere to keep it. That somewhere is a **variable** โ€” a labelled box that holds one value at a time. You put a value into the box with the **assignment operator**, the single `=`.\n", "\n", "Here is the shape of every assignment you'll ever write:\n", "\n", "```python\n", "box_name = value\n", "```\n", "\n", "The trick is how to *read* that `=`. Read it as **\"gets,\"** not \"equals.\" So `crowns = 50` means *\"the box named `crowns` gets the value 50.\"* It's an **instruction to store something**, not a claim that two things are equal. Mirabel likes this arrangement: a named box can be checked, reused, and corrected in exactly one place โ€” unlike Fen's totals, scattered in the margins of three different pages.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "crowns = 50 # coins in the till\n", "spent = 12 # a customer's purchase\n", "# ----------------------------------\n", "\n", "crowns = crowns - spent # the right side runs first, then it's stored back\n", "\n", "print(crowns)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is one line above that trips up almost every beginner: `crowns = crowns - spent`. How can a box equal itself minus something? It can't โ€” and that's the clue that `=` is not \"equals.\" **The right side always runs first.** Python computes `50 - 12 = 38`, and *then* drops that result into `crowns`, replacing whatever was there before. A variable always holds whatever was assigned **most recently**; the old value is simply gone.\n", "\n", "Try it: set `spent = 70` and re-run. The till goes negative, and Python doesn't bat an eye โ€” to it, numbers are just numbers. (Mirabel would bat an eye.)\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| echo: false\n", "#@title ๐Ÿ“Š Diagram code (click to show)\n", "from graphviz import Digraph\n", "\n", "d = Digraph(graph_attr={\"rankdir\": \"LR\"})\n", "d.node(\"E\", \"crowns - spent\\n(50 - 12)\", shape=\"box\",\n", " style=\"rounded,filled\", fillcolor=\"lightyellow\")\n", "d.node(\"B\", \"crowns\\nโ€•โ€•โ€•\\n38\", shape=\"box\",\n", " style=\"filled\", fillcolor=\"lightgreen\")\n", "d.edge(\"E\", \"B\", label=\" result stored into the box \")\n", "d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Reading the picture:** the yellow box is the expression Python works out first; the arrow is the act of storing; the green box is `crowns` after the update. Assignment always flows **right โ†’ left**.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### โœ๏ธ Your Turn โ€” Update the Till\n", "\n", "A customer buys a phoenix feather. Start with the till and the price already in boxes, then update the till to reflect the sale, and print the new total.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "till = 200 # crowns currently in the till\n", "price = 35 # price of one phoenix feather\n", "# ----------------------------------\n", "\n", "# TODO: subtract the price from the till, store it back into `till`,\n", "# then print the new total." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data Types: What Kind of Value?\n", "\n", "Every value a program holds has a **type** โ€” a category that decides what you're allowed to do with it. You can add two numbers, but \"adding\" two names means something different, and dividing a word by three means nothing at all. The type is what tells Python which rules apply.\n", "\n", "**Auditor Crane**, who visits from the Guild of Weights and Measures with a magnifying glass and no sense of humour, insists that you *always know which type you are holding*. The four you need right now:\n", "\n", "| Type | Full name | Example | Used for |\n", "|---|---|---|---|\n", "| `int` | integer | `42`, `-7` | whole numbers โ€” counts, crowns, bits |\n", "| `float` | floating-point | `3.14`, `2.0` | numbers with a decimal point |\n", "| `str` | string | `\"Mirabel\"` | text, always in quotes |\n", "| `bool` | boolean | `True`, `False` | yes/no answers |\n", "\n", "When you want to know what you're holding, ask Python directly with the `type()` function:\n", "\n", "```python\n", "type(some_value)\n", "```\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "print(type(42)) # a whole number\n", "print(type(3.14)) # has a decimal point\n", "print(type(\"Mirabel\")) # in quotes -> text\n", "print(type(7 > 3)) # a comparison -> True / False\n", "print(type(\"42\")) # quotes! looks like a number, but it's text\n", "\n", "# โฌ‡๏ธ CHANGE THIS and re-run to test your own guess:\n", "mystery = 9.0\n", "print(\"mystery is:\", type(mystery))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice the last two lines especially. `42` is an `int`, but `\"42\"` โ€” with quotes โ€” is a `str`. They look almost identical on the page and behave completely differently, and confusing them is the most common beginner bug there is. The rule to carry all year: **quotes win.** If it's in quotes, it's text, no matter how numeric it looks. And one small surprise worth memorizing now: `2` is an `int`, but `2.0` is a `float`. The lone decimal point is the whole difference.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### โœ๏ธ Your Turn โ€” Name That Type\n", "\n", "Store one value of **each** of the four types in the boxes below โ€” your own choices โ€” then print the type of each. Before you run it, predict each answer out loud; then check yourself against Python.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# โฌ‡๏ธ FILL IN a value of each type, then run.\n", "whole_number = # an int\n", "decimal_number = # a float\n", "some_text = # a str (remember the quotes!)\n", "yes_or_no = # a bool: True or False\n", "# ----------------------------------\n", "\n", "# TODO: print the type() of each of the four boxes above." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Operators & Expressions\n", "\n", "An **expression** is any piece of code that computes a value. `crowns - spent` is an expression; so is `7 > 3`. The values an expression works on are its **operands**, and the symbols that act on them โ€” `+`, `-`, and friends โ€” are its **operators**. A whole line of code like `total = crowns - spent` is a **statement**: a complete instruction. (Tuck those four words away โ€” *expression, operand, operator, statement* โ€” they come back all year.)\n", "\n", "The everyday arithmetic operators are the ones you'd expect: `+ - * /`. But three more deserve special attention, because they show up constantly and surprise people:\n", "\n", "| Operator | Meaning | Example | Result |\n", "|---|---|---|---|\n", "| `/` | true division โ€” **always** gives a `float` | `7 / 2` | `3.5` |\n", "| `//` | floor division โ€” the whole part only | `7 // 2` | `3` |\n", "| `%` | modulo โ€” the remainder left over | `7 % 2` | `1` |\n", "| `**` | exponent โ€” raise to a power | `2 ** 3` | `8` |\n", "\n", "The pair `//` and `%` are a team. Together they answer one very practical question: *\"how many whole groups fit, and how much is left over?\"* That question is everywhere โ€” and in our shop, it's exactly how you turn a heap of copper bits into crowns-and-bits.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# โฌ‡๏ธ CHANGE THIS, THEN RE-RUN\n", "bits = 347 # a pile of loose copper bits (100 bits = 1 crown)\n", "# ----------------------------------\n", "\n", "print(bits / 100) # true division -> 3.47 (a float)\n", "print(bits // 100) # floor division -> 3 (whole crowns)\n", "print(bits % 100) # modulo -> 47 (leftover bits)\n", "print(bits ** 2) # exponent -> 120409" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Look at the middle two lines together: `347 // 100` is `3` and `347 % 100` is `47`. So 347 loose bits is **3 crowns and 47 bits**. That's the entire idea behind `//` and `%`, and it returns as the worked example later in this notebook โ€” so make sure it clicks now. (Note too that `/` gave `3.47`, a `float`, even though we wanted whole crowns. `/` *always* hands back a float, even when the division comes out even: `10 / 5` is `5.0`, not `5`.)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A Few Built-in Math Tools\n", "\n", "Operators aren't the only way to compute. Python ships with small **functions** that do common jobs โ€” you call one by writing its name and putting its inputs in parentheses, like `abs(-5)`. A clerk's-toolkit worth knowing:\n", "\n", "| Function | What it does | Example | Result |\n", "|---|---|---|---|\n", "| `abs(x)` | distance from zero (drops the minus sign) | `abs(-38)` | `38` |\n", "| `round(x, n)` | round to `n` decimal places | `round(19.547, 2)` | `19.55` |\n", "| `min(...)` | the smallest value | `min(8, 40, 12)` | `8` |\n", "| `max(...)` | the largest value | `max(8, 40, 12)` | `40` |\n", "| `divmod(a, b)` | the `//` and `%` answers together, as a pair | `divmod(347, 100)` | `(3, 47)` |\n", "\n", "That last one, `divmod`, is just the crowns-and-bits split in a single call โ€” handy once you trust what `//` and `%` do.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### โœ๏ธ Your Turn โ€” Crowns and Bits\n", "\n", "A customer pays for a jar of moonpetal with a fistful of loose bits. Given the number of bits, work out how many whole **crowns** that is and how many **bits** are left over, and print both.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# โฌ‡๏ธ CHANGE THIS, THEN RE-RUN\n", "paid_bits = 525\n", "# ----------------------------------\n", "\n", "# TODO: use // and % to split paid_bits into whole crowns and leftover bits,\n", "# then print a line like: 525 bits = 5 crowns and 25 bits" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Comparisons & Booleans: Asking Yes/No Questions\n", "\n", "So far our expressions have produced numbers. But programs also need to ask **questions** โ€” *is the till empty? can the customer afford this?* โ€” and the answer to a yes/no question is a **bool**: either `True` or `False`.\n", "\n", "You ask numeric questions with the **comparison operators**:\n", "\n", "| Operator | Means | Example | Result |\n", "|---|---|---|---|\n", "| `==` | equal to | `7 == 7` | `True` |\n", "| `!=` | not equal to | `7 != 5` | `True` |\n", "| `<` | less than | `3 < 2` | `False` |\n", "| `>` | greater than | `10 > 4` | `True` |\n", "| `<=` | less than or equal to | `5 <= 5` | `True` |\n", "| `>=` | greater than or equal to | `9 >= 12` | `False` |\n", "\n", "One of these causes more grief than all the others combined: **`==` is a question, `=` is a command.** `crowns == 50` *asks* \"is the till 50?\" and answers True or False. `crowns = 50` *orders* \"put 50 in the till.\" Mixing them up is a rite of passage; knowing the difference now will save you a real headache later.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Often one question isn't enough โ€” *can the customer afford it **and** is it in stock?* You combine yes/no answers with the **boolean operators** `and`, `or`, and `not`. These are exactly the AND / OR / NOT logic gates from Notebook 2, now spelled as English words:\n", "\n", "| `A` | `B` | `A and B` | `A or B` | `not A` |\n", "|---|---|---|---|---|\n", "| F | F | F | F | T |\n", "| F | T | F | T | T |\n", "| T | F | F | T | F |\n", "| T | T | **T** | **T** | F |\n", "\n", "- **`and`** โ€” True only when **both** sides are True.\n", "- **`or`** โ€” True when **either** side is True.\n", "- **`not`** โ€” flips it: `not True` is `False`.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "purse = 72 # crowns the customer is carrying\n", "price = 50 # price of the item\n", "in_stock = True\n", "# ----------------------------------\n", "\n", "print(purse >= price) # can they afford it?\n", "print(purse >= price and in_stock) # affordable AND on the shelf?\n", "print(purse < price or in_stock) # either one is enough here\n", "print(not in_stock) # is it sold out?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Tracing it by hand.** \"Tracing\" means running code in your head, line by line, predicting each result before Python tells you โ€” and it is the single most useful habit for the rest of this course. Python untangles a compound condition from the **inside out, simplest part first**. Walk through `purse >= price and in_stock` with `purse = 72`, `price = 50`, `in_stock = True`:\n", "\n", "1. `72 >= 50` โ†’ `True`\n", "2. `in_stock` is `True`\n", "3. `True and True` โ†’ **`True`**\n", "\n", "When several operators meet in one line, they resolve in a set order โ€” **arithmetic โ†’ comparisons โ†’ `not` โ†’ `and` โ†’ `or`** โ€” but you never have to memorize that under pressure. When in doubt, add parentheses and Python (and your reader) will evaluate the innermost ones first.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### โœ๏ธ Your Turn โ€” The Shopkeeper's Test\n", "\n", "Mirabel will sell an item only if the customer can afford it **and** it's in stock. Set up the boxes below, then write and print **one** boolean expression that is `True` exactly when the sale should go through. Test it by changing the values so it comes out both `True` and `False`.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "purse = 40\n", "price = 35\n", "in_stock = True\n", "# ----------------------------------\n", "\n", "# TODO: print a single True/False value: can this sale go through?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Input & Output: Talking to a Person\n", "\n", "Two built-in functions let a program hold a conversation. You've seen both; now we make them precise:\n", "\n", "- **`print(...)`** shows a value to the person at the keyboard.\n", "- **`input(prompt)`** shows a prompt, waits for them to type a line, and hands it back.\n", "\n", "The shape of an input is:\n", "\n", "```python\n", "answer = input(\"a prompt to show: \")\n", "```\n", "\n", "There is one surprise hiding in that line, and it is responsible for the most common bug in this entire course โ€” so let's meet it head-on.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# This cell PAUSES and waits for you to type. That's expected, not a freeze.\n", "typed = input(\"Type any number: \")\n", "print(typed, \"has type\", type(typed))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Type `42` and look at what Python reports: the type is `str`, not `int`. **`input()` always hands back a string**, every time, even when the person typed digits. In Colab the cell pauses until you press Enter โ€” if you ever \"Run all\" and the notebook seems stuck, it's probably waiting politely at an `input()`. (This is exactly why our *learning* examples set values directly instead: editing a box is faster and never pauses.)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The #1 Beginner Bug\n", "\n", "Because `input()` returns a string, doing arithmetic on it goes wrong in a way that looks *almost* right โ€” which is the most dangerous kind of wrong:\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "a = \"5\" # pretend these two arrived from input()\n", "b = \"3\"\n", "# ----------------------------------\n", "\n", "print(a + b) # \"53\" โ€” NOT 8!\n", "print(int(a) + int(b)) # 8 โ€” fixed" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`\"5\" + \"3\"` is `\"53\"`, because for strings `+` means **glue together**, not add. No error appears โ€” Python silently does the wrong thing. The fix is **type casting**: `int(\"5\")` deliberately converts the text into the number `5`. The casts you'll reach for most are `int(...)`, `float(...)`, and `str(...)`.\n", "\n", "**The rule:** any number that came from `input()` must be wrapped in `int(...)` or `float(...)` before you do math with it:\n", "\n", "```python\n", "count = int(input(\"How many feathers? \"))\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### โœ๏ธ Your Turn โ€” Ask and Answer\n", "\n", "Ask the customer how many phoenix feathers they want and the price per feather, then print the total cost. Remember to cast each input before multiplying.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# TODO: read two numbers with input(), cast them with int(),\n", "# multiply, and print the total cost.\n", "#\n", "# feathers = int(input(\"How many feathers? \"))\n", "# ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Printing Well\n", "\n", "Mirabel doesn't want a bare number flung at the screen โ€” she wants a *readable* receipt, lined up and labelled. Three tools turn raw output into something that looks like a document: **escape characters**, **f-string formatting**, and **string methods**.\n", "\n", "### Escape Characters\n", "\n", "Inside a string, a backslash begins an **escape character** โ€” a little code for something you can't easily type:\n", "\n", "| Escape | Means |\n", "|---|---|\n", "| `\\n` | start a new line |\n", "| `\\t` | a tab (jump to the next column) |\n", "| `\\\"` | a literal double-quote |\n", "| `\\\\` | a literal backslash |\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "print(\"Line one\\nLine two\")\n", "print(\"Item:\\tMoonpetal\")\n", "print(\"Mirabel said \\\"mind the cat\\\"\")\n", "print(\"Path: C:\\\\ledgers\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each backslash code stands in for a character that's awkward to type literally: `\\n` ended the first line and started a second, `\\t` jumped to a tab stop so columns can line up, `\\\"` slipped a quote *inside* a quoted string without ending it early, and `\\\\` printed a single backslash (you write two to get one).\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### f-string Formatting\n", "\n", "An **f-string** is a string with the letter `f` in front of it. Inside, anything in curly braces `{ }` gets replaced by the value of that variable. Add a colon and a **format specifier**, and you also control *how* it prints โ€” the very same machinery as Notebook 2's `{n:08b}`, just different codes:\n", "\n", "```python\n", "f\"text {variable} more text\"\n", "f\"{variable:specifier}\"\n", "```\n", "\n", "| Spec | Effect | Example โ†’ |\n", "|---|---|---|\n", "| `:.2f` | exactly 2 decimal places (money!) | `19.5` โ†’ `19.50` |\n", "| `:>10` | right-align within 10 columns | `[ Fen]` |\n", "| `:<10` | left-align within 10 columns | `[Fen ]` |\n", "| `:^10` | centre within 10 columns | `[ Fen ]` |\n", "| `:,` | thousands separators | `1234567` โ†’ `1,234,567` |\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "price = 19.5\n", "name = \"mirabel\"\n", "count = 1234567\n", "# ----------------------------------\n", "\n", "print(f\"Total: {price:.2f} crowns\") # money -> 19.50\n", "print(f\"[{name:>12}]\") # right-aligned\n", "print(f\"[{name:<12}]\") # left-aligned\n", "print(f\"[{name:^12}]\") # centred\n", "print(f\"Bits counted: {count:,}\") # 1,234,567" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The colon-code only ever changes how a value *prints* โ€” never the value itself. `{price:.2f}` forces two decimals so `19.5` reads as `19.50`, which is what you want for money. The alignment codes `:>12`, `:<12`, `:^12` pad a value out to 12 characters so that stacked rows line up into neat columns; the `[ ]` brackets above are just there to make the padding visible.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### String Methods\n", "\n", "Strings come with built-in **methods** โ€” small tools you call *on* a string by attaching a dot:\n", "\n", "```python\n", "text.method()\n", "```\n", "\n", "| Tool | What it does | Example | Result |\n", "|---|---|---|---|\n", "| `.upper()` | all uppercase | `\"mirabel\".upper()` | `\"MIRABEL\"` |\n", "| `.lower()` | all lowercase | `\"FEN\".lower()` | `\"fen\"` |\n", "| `.title()` | Capitalize Each Word | `\"phoenix feather\".title()` | `\"Phoenix Feather\"` |\n", "| `.strip()` | trim spaces from both ends | `\" Fen \".strip()` | `\"Fen\"` |\n", "| `.replace(old, new)` | swap matching text | `\"moonpetal\".replace(\"petal\",\"dust\")` | `\"moondust\"` |\n", "| `len(s)` | count the characters | `len(\"Fen\")` | `3` |\n", "| `\"x\" * n` | repeat a string `n` times | `\"-\" * 10` | `\"----------\"` |\n", "\n", "Two things to know. Strings are **immutable** โ€” a method never changes the original; it hands back a *new* string. And methods can be **chained** left to right, so `raw.strip().title()` trims first, then title-cases the trimmed result.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# โฌ‡๏ธ CHANGE THIS, THEN RE-RUN\n", "raw = \" mirabel quill \"\n", "# ----------------------------------\n", "\n", "print(raw.strip()) # \"mirabel quill\"\n", "print(raw.strip().title()) # \"Mirabel Quill\" (trim, then title-case)\n", "print(raw.replace(\"quill\", \"QUILL\")) # swap part of the text\n", "print(\"length:\", len(raw.strip()))\n", "print(\"=\" * 30) # a divider line, 30 characters wide" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice `raw` itself never changed โ€” each method returned a brand-new string and left the original alone. That `\"=\" * 30` trick is how you draw divider lines and borders without typing thirty equals signs by hand. Combine repetition with `\\n` and f-string alignment, and you can build a tidy banner โ€” which is exactly the next step.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Putting It Together: a Shop Label\n", "\n", "These tools shine when you use them *at once*. The cell below prints a bordered price label using all three โ€” a repeated-character rule, a centred upper-cased banner, and a right-aligned price column to two decimals.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "shop = \"mirabel's emporium\"\n", "item = \"phoenix feather\"\n", "price = 35.0\n", "# ----------------------------------\n", "\n", "rule = \"-\" * 32\n", "\n", "print(rule)\n", "print(f\"{shop.upper():^32}\")\n", "print(rule)\n", "print(f\"{item.title():<22}{price:>9.2f}\")\n", "print(rule)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Read that cell against its output: a rule line, a centred upper-cased shop name, then a left-aligned item with a right-aligned price. Nothing fancy โ€” just the four tools combined on purpose. Change `shop` to your own name and re-run; the banner re-centres itself, because the width (`32`) is fixed and `:^32` does the arithmetic for you.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### โœ๏ธ Your Turn โ€” Your Own Price Label\n", "\n", "Make a label for an item of your own invention (a *self-stirring teaspoon*? a *jar of bottled Tuesday*?). Print a bordered label with the shop name centred and the price right-aligned to two decimals โ€” start from the cell above and make it yours.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "shop = \"your shop name\"\n", "item = \"your wondrous item\"\n", "price = 12.5\n", "# ----------------------------------\n", "\n", "# TODO: print a bordered label. Use \"-\" * n for the rule, :^ to centre\n", "# the shop name, .title() on the item, and :>9.2f for the price." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Workflow: Problem โ†’ Pseudocode โ†’ Flowchart โ†’ Python\n", "\n", "You now have enough Python to be dangerous. This section gives you the *method* that keeps you safe โ€” the one the whole course uses. Wren Hollow never writes a line of ledger-code before she has written down what she intends to do. Four steps:\n", "\n", "1. **Problem** โ€” state what's needed in plain English, including the inputs and outputs.\n", "2. **Pseudocode** โ€” the steps, written in structured plain language. Language-neutral.\n", "3. **Flowchart** โ€” those same steps drawn as a picture, so the shape is obvious at a glance.\n", "4. **Python** โ€” translate the pseudocode line by line, then **verify** the result by hand.\n", "\n", "Jumping straight to step 4 is the most common reason beginners get stuck. The first three steps are where the *thinking* happens; the Python is just the transcription.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### One Algorithm, Three Ways of Writing It Down\n", "\n", "Here's the idea that ties the workflow together: steps 2, 3, and 4 are *not* three different things. They are the **same algorithm, written three different ways** โ€” pseudocode in structured words, a flowchart as a picture, Python as code a machine can run. Change the representation and the underlying algorithm doesn't change, the same way ยฃ100 is the same amount whether you write it in numerals, spell it in words, or stack it in coins.\n", "\n", "That is your first real taste of **abstraction** โ€” separating *what* a process does from *how* it happens to be written down. Pseudocode lets you think purely about the *what*; Python worries about the *how*. Getting the *what* right first is why the planning steps matter more than the typing.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Pseudocode: the House Style\n", "\n", "There's no official pseudocode language, so a consistent style keeps it readable. Ours:\n", "\n", "- A header naming the **ALGORITHM**, its **INPUT**, and its **OUTPUT**.\n", "- **Numbered steps**, one action each.\n", "- Keywords in capitals: **READ**, **SET**, **PRINT** (and later **IF**, **REPEAT**).\n", "- Plain arithmetic, in words or symbols โ€” whatever reads clearest.\n", "\n", "It is deliberately *not* Python: no colons, no quotes, no syntax to trip over. The test is simple โ€” if you can read it aloud and a non-programmer follows along, it's good pseudocode.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Flowchart Notation\n", "\n", "A flowchart draws that same algorithm. Four shapes cover everything; you need three of them today (the fourth, the decision diamond, waits for Notebook 4).\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| echo: false\n", "#@title ๐Ÿ“Š Flowchart legend code (click to show)\n", "from graphviz import Digraph\n", "legend = Digraph(graph_attr={\"rankdir\": \"TB\"})\n", "legend.node(\"S\", \"Start / End\", shape=\"ellipse\",\n", " style=\"filled\", fillcolor=\"lightgreen\")\n", "legend.node(\"I\", \"Input / Output\", shape=\"parallelogram\",\n", " style=\"filled\", fillcolor=\"lightblue\")\n", "legend.node(\"P\", \"Process\\n(a calculation)\", shape=\"box\",\n", " style=\"filled\", fillcolor=\"lightyellow\")\n", "legend.node(\"D\", \"Decision\\n(โ† Notebook 4, not yet)\", shape=\"diamond\",\n", " style=\"filled\", fillcolor=\"mistyrose\")\n", "legend.edge(\"S\", \"I\", style=\"invis\")\n", "legend.edge(\"I\", \"P\", style=\"invis\")\n", "legend.edge(\"P\", \"D\", style=\"invis\")\n", "legend" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**The shapes:** an ellipse marks Start and End, a parallelogram marks Input or Output, a rectangle marks a Process (a calculation), and the rose-coloured diamond marks a Decision โ€” greyed out here because choices arrive in Notebook 4.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### A Worked Example, All Four Steps\n", "\n", "**Step 1 โ€” The Problem.** A customer arrives with a cache of mana-crystals to be shared out among the shop's apprentices:\n", "\n", "> *A cache holds a whole number of mana-crystals. Divide them **evenly** among the apprentices so each gets an equal whole number of crystals. Any crystals that don't divide evenly are handed back to the customer. Report each apprentice's share and the number handed back.*\n", "\n", "Pinned down precisely:\n", "\n", "- **Inputs:** `crystals` (a whole number), `apprentices` (a count)\n", "- **Outputs:** `share` (crystals per apprentice), `leftover` (crystals handed back)\n", "- **The relationship:** \"how many whole groups, and how much left over?\" โ€” our old friends `//` and `%`.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Step 2 โ€” Pseudocode.** The steps, in the house style, with no Python anywhere in sight:\n", "\n", "```text\n", "ALGORITHM: share_crystals\n", "INPUT: crystals โ€” total crystals in the cache\n", " apprentices โ€” how many apprentices share them\n", "OUTPUT: share โ€” crystals each apprentice receives\n", " leftover โ€” crystals handed back to the customer\n", "\n", "1. READ crystals\n", "2. READ apprentices\n", "3. SET share = crystals // apprentices\n", "4. SET leftover = crystals % apprentices\n", "5. PRINT share\n", "6. PRINT leftover\n", "```\n", "\n", "Six numbered steps anyone could follow โ€” including a tired future you, debugging this at midnight.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Step 2ยฝ โ€” The Flowchart.** The same six steps, drawn so the straight-line shape is obvious: Start, two inputs, two calculations, one output, End.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| echo: false\n", "#@title ๐Ÿ“Š Flowchart code (click to show)\n", "fc = Digraph(graph_attr={\"rankdir\": \"TB\"})\n", "fc.node(\"S\", \"Start\", shape=\"ellipse\",\n", " style=\"filled\", fillcolor=\"lightgreen\")\n", "fc.node(\"R1\", \"READ crystals\", shape=\"parallelogram\",\n", " style=\"filled\", fillcolor=\"lightblue\")\n", "fc.node(\"R2\", \"READ apprentices\", shape=\"parallelogram\",\n", " style=\"filled\", fillcolor=\"lightblue\")\n", "fc.node(\"P1\", \"share = crystals // apprentices\", shape=\"box\",\n", " style=\"filled\", fillcolor=\"lightyellow\")\n", "fc.node(\"P2\", \"leftover = crystals % apprentices\", shape=\"box\",\n", " style=\"filled\", fillcolor=\"lightyellow\")\n", "fc.node(\"O\", \"PRINT share, leftover\", shape=\"parallelogram\",\n", " style=\"filled\", fillcolor=\"lightblue\")\n", "fc.node(\"E\", \"End\", shape=\"ellipse\",\n", " style=\"filled\", fillcolor=\"lightgreen\")\n", "fc.edges([(\"S\",\"R1\"), (\"R1\",\"R2\"), (\"R2\",\"P1\"),\n", " (\"P1\",\"P2\"), (\"P2\",\"O\"), (\"O\",\"E\")])\n", "fc" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Step 3 โ€” Python.** Now โ€” and only now โ€” translate the pseudocode line for line. We use an editable value block first, so the output is reproducible and we can check it by hand:\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "# โฌ‡๏ธ CHANGE THESE, THEN RE-RUN\n", "crystals = 1000 # step 1: READ crystals\n", "apprentices = 7 # step 2: READ apprentices\n", "# ----------------------------------\n", "\n", "share = crystals // apprentices # step 3\n", "leftover = crystals % apprentices # step 4\n", "\n", "print(f\"Each apprentice receives {share} crystals.\") # step 5\n", "print(f\"{leftover} crystals are handed back.\") # step 6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Step 4 โ€” Verify by hand.** Never trust output you haven't checked. With `crystals = 1000`, `apprentices = 7`:\n", "\n", "- `1000 // 7` โ†’ 7 goes into 1000 **142** times (142 ร— 7 = 994)\n", "- `1000 % 7` โ†’ leftover is `1000 โˆ’ 994 =` **6**\n", "- **Cross-check:** 142 ร— 7 + 6 = 994 + 6 = **1000** โœ“ โ€” the shares plus the leftover must add back up to the whole cache. They do.\n", "\n", "That `(quotient ร— divisor) + remainder = original` check works for *any* `//` and `%` pair. Get in the habit of running it.\n", "\n", "Here is the same algorithm wired to a real person, with `int(input(...))` standing in for steps 1โ€“2 โ€” the type-casting rule applied. The *thinking* was finished before a line of Python got written. That's the whole method.\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "crystals = int(input(\"Crystals in the cache: \"))\n", "apprentices = int(input(\"Number of apprentices: \"))\n", "\n", "share = crystals // apprentices\n", "leftover = crystals % apprentices\n", "\n", "print(f\"Each apprentice receives {share} crystals.\")\n", "print(f\"{leftover} crystals are handed back.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### โœ๏ธ Exercise โ€” Run the Whole Pipeline\n", "\n", "Take this one through **all four steps** yourself โ€” the planning steps are not optional:\n", "\n", "> *A customer pays with a heap of loose copper bits. Convert it into whole crowns and leftover bits, where 100 bits = 1 crown. Report the crowns and the bits.*\n", "\n", "1. **Problem:** write down the inputs and outputs.\n", "2. **Pseudocode:** in a markdown cell, in the house style.\n", "3. **Flowchart:** describe it in words, *or* copy the flowchart cell above and adapt it.\n", "4. **Python:** in a code cell with an editable value block โ€” then **verify by hand** with one example and show the cross-check.\n", "\n", "*Hint: it's the same `//` and `%` shape as the crystal split.*\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# โœ๏ธ Your Python for the bits-to-crowns exercise.\n", "# Write your pseudocode in a markdown cell FIRST, then translate it here.\n", "\n", "# โฌ‡๏ธ CHANGE THIS, THEN RE-RUN\n", "paid_bits = 925\n", "# ----------------------------------\n", "\n", "# TODO: split paid_bits into whole crowns and leftover bits, and print both." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Building With AI: Plan First, Then Code\n", "\n", "Notebook 1 left us with a warning: an AI generates *plausible-looking* text, which is not the same as *correct* text. The right response isn't to avoid AI โ€” it's to **do the thinking yourself first** and then use the AI to pressure-test that thinking. When you have your own plan to compare against, you can actually tell whether the AI's code is right.\n", "\n", "A verification checklist for any code, yours or an AI's:\n", "\n", "1. **Does it run?** Errors are the *easy* case โ€” Python tells you about them.\n", "2. **Test a known input.** Feed it something you worked out by hand. Does the answer match?\n", "3. **Read every line.** Is each `input()` cast with `int()`? Is it `//` or `/`? Is it `==` or `=`?\n", "4. **Does it match your plan?** Without pseudocode to compare against, \"it didn't crash\" is all you really know โ€” and that's not the same as \"it's correct.\"\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ๐Ÿ’ญ Think About It โ€” Who Does the Thinking?\n", "\n", "You just saw the habit of planning in pseudocode *before* asking an AI to write the code.\n", "\n", "- If an AI can write the code for you, why bother learning to plan it yourself first? What might you lose by skipping straight to \"AI, just build this\"?\n", "- When an AI hands you code that runs but you don't understand it, what should you do โ€” and whose responsibility is it if that code turns out to be wrong?\n", "- Compare leaning on AI to write code with using GPS to navigate. What does each make easier, and what skill might quietly fade if you rely on it for everything?\n", "\n", "There are no single right answers here โ€” share a sentence or two on each." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Practice: PyQuiz\n", "\n", "Time to write some code of your own against a tool that checks it for you. **PyQuiz** gives you short problems, lets you write a solution, and runs it against several test inputs so you can see exactly where it works and where it doesn't.\n", "\n", "### A quick word about functions\n", "\n", "PyQuiz frames every problem the same way: you write a **function** that takes some inputs and **returns** an answer. You'll learn `def` properly in Notebook 4, but the pattern is short enough to read now:\n", "\n", "```python\n", "def double_number(number): # name, and the input it takes\n", " return number * 2 # the answer to hand back\n", "```\n", "\n", "- The `def` line names the function and lists its **parameters** (the inputs).\n", "- The indented `return` line says **what value to give back** โ€” note there's no `print()`; PyQuiz reads the returned value directly.\n", "\n", "PyQuiz writes the `def` line for you. You just fill in the body.\n", "\n", "### How to use it\n", "\n", "For each problem: read the description and sample runs, edit the code in the box, and click **Run Tests** to see how you did. Stuck? Click **Hint**. Use **Next** to move on, or the dropdown to jump around โ€” your code is checked per test case, so you can see partial progress clearly.\n", "\n", "Run the cell below to start. *(The first time, it downloads `pyquiz.py` from the course repo โ€” a brief pause, then the tool appears.)*\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# PyQuiz bootstrap โ€” works in Colab or any local Jupyter.\n", "import os, urllib.request\n", "REPO = \"https://raw.githubusercontent.com/brendanpshea/computing_concepts_python/main\"\n", "if not os.path.exists(\"pyquiz.py\"):\n", " urllib.request.urlretrieve(f\"{REPO}/tools/python_code_quiz/pyquiz.py\", \"pyquiz.py\")\n", "\n", "from pyquiz import PracticeTool\n", "practice_tool = PracticeTool(\n", " json_url=f\"{REPO}/tools/python_code_quiz/banks/nb03_python_basics.json\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## โœ๏ธ Capstone โ€” Build a Trading Game (AI-Assisted)\n", "\n", "In this exercise you'll build a **trading game**. The core idea is always the same โ€” start with some money, **buy low and sell high**, and try to end up richer โ€” but the theme is yours: a magic shop, a **space trader** hauling cargo, a **sneaker reseller** flipping drops, a **lemonade stand**, a **card- or crypto-market** where prices swing. You'll build it the way a pro does: **plan first, let an AI help you write it, then verify.**\n", "\n", "*One note:* a real game *repeats* over many turns, and repetition needs **loops**, which arrive in Notebook 4. That's fine here โ€” the AI will reach for a few tools you haven't formally met. Your job is to **plan the game and check that it works**, not to know every line by heart.\n", "\n", "**Step 1 โ€” Design it first (before touching the AI).** A generic prompt makes a generic game. Jot these in a markdown cell:\n", "\n", "- **Setting & goods:** your theme, plus 3โ€“5 things to trade and a price for each.\n", "- **The purse:** how much money does the player start with?\n", "- **The goal:** end richer than you started โ€” or hit a target before you run out.\n", "- **The catch:** what makes it fun? Prices that drift each turn? A limited number of turns? A risky item?\n", "\n", "**Step 2 โ€” Turn your design into a prompt.** Fill in the blanks and send it to Gemini (or Claude / ChatGPT):\n", "\n", "> *Write a small text trading game as a Python program for Google Colab. The player starts with **[N]** money and can buy or sell these goods each turn: **[your goods and prices]**. Prices **[stay fixed / drift each turn]**. The game lasts **[number]** turns or until **[your end condition]**. Each turn, show the player's money and inventory; at the end, say whether they finished richer. Keep it short and beginner-readable.*\n", "\n", "**Step 3 โ€” Get the bones working, then test.** Paste it into the cell below and **run it now**. It won't be perfect. Get the simplest version working first โ€” buy one item, sell it, watch the money change โ€” and check that by hand before adding anything.\n", "\n", "**Step 4 โ€” Add the bells and whistles.** Once the core works, add **one or two** extras, testing after each: prices that change each turn, a sell price different from the buy price (where profit lives), a win/lose message, or a risky item that might be worthless.\n", "\n", "**Step 5 โ€” Reflect.** In a markdown cell, write 2โ€“3 sentences: what did the AI get wrong or what did you improve, and how did you fix it?\n", "\n", "Remember the course rule: *AI is a fast first draft. You verify.*\n" ] }, { "cell_type": "code", "metadata": {}, "execution_count": null, "outputs": [], "source": [ "#| eval: false\n", "# โœ๏ธ Paste your AI-built trading game here, then run it and fix what's broken." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Key Terms\n", "\n", "- **Algorithm** โ€” A finite list of clear, definite steps that takes input, does a fixed amount of work, terminates, and produces output.\n", "- **Representation** โ€” One way of writing an algorithm down; pseudocode, a flowchart, and Python are three representations of the same algorithm.\n", "- **Abstraction** โ€” Separating *what* a process does from *how* it is written down or carried out.\n", "- **Variable** โ€” A named box that holds one value.\n", "- **Assignment (`=`)** โ€” Stores the right-hand value into a variable; read it as \"gets,\" and remember the right side runs first.\n", "- **Data type** โ€” The kind of a value: `int`, `float`, `str`, `bool`.\n", "- **int / float** โ€” A whole number vs. a number with a decimal point.\n", "- **str / bool** โ€” Text in quotes; a truth value (`True` / `False`).\n", "- **Expression / statement** โ€” Code that computes a value vs. a complete instruction.\n", "- **Operator / operand** โ€” The verb (`+`, `//`, `and`) and the values it acts on.\n", "- **Floor division (`//`) / modulo (`%`)** โ€” The whole part of a division / the remainder left over.\n", "- **Comparison operators** โ€” `== != < > <= >=`; each produces a `bool`.\n", "- **Boolean operators** โ€” `and`, `or`, `not`; combine truth values.\n", "- **Operator precedence** โ€” The order operators resolve: arithmetic โ†’ comparison โ†’ `not` โ†’ `and` โ†’ `or`.\n", "- **Type casting** โ€” Deliberately converting a value's type, e.g. `int(\"5\")`.\n", "- **Escape character** โ€” A backslash code inside a string: `\\n`, `\\t`, `\\\"`, `\\\\`.\n", "- **f-string / format specifier** โ€” `f\"...\"` text with `{var}`; codes like `:.2f`, `:>10`, `:,` control how a value prints.\n", "- **String method** โ€” A function called on a string with a dot: `.upper()`, `.strip()`, `.replace()`.\n", "- **Pseudocode** โ€” Structured, language-neutral plain English describing an algorithm.\n", "- **Flowchart** โ€” A diagram of an algorithm: ellipse = start/end, parallelogram = input/output, box = process, diamond = decision.\n", "- **Trace** โ€” To run code in your head, line by line, predicting each result.\n", "- **Comment (`#`)** โ€” A note for humans; Python ignores it.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary\n", "\n", "- An **algorithm** is a finite, definite, terminating recipe of steps from input to output โ€” the central idea of the course โ€” and one problem can have many algorithms.\n", "- Pseudocode, flowcharts, and Python are three **representations** of one algorithm; get the algorithm right first, then translate.\n", "- A **variable** is a named box; `=` stores into it, and the **right side runs first**.\n", "- Every value has a **type**; quotes always mean `str`, and `input()` always returns `str`.\n", "- `/` always gives a `float`; `//` and `%` answer *\"how many whole groups, how much left over.\"*\n", "- **Boolean** expressions resolve from the innermost, simplest part outward.\n", "- **Printing well** = escape characters + f-string specifiers (`:.2f`, alignment) + string methods + repetition.\n", "- The course workflow is **problem โ†’ pseudocode โ†’ flowchart โ†’ Python โ†’ verify**. Plan by hand; let the AI critique the *plan*, not hand you the answer.\n", "\n", "Write it down before you write it up. Wren Hollow would insist.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What's Next\n", "\n", "Every program in this notebook ran straight down, top to bottom. **Notebook 4** brings the shape we left greyed-out in the flowchart legend: the **decision diamond**. Programs will start making choices and repeating work โ€” `if`, `else`, and loops. Fen restocks the shelves by repeating the same handful of steps for every jar; soon you'll write the loop that does it without losing count.\n", "\n", "*COMP 1150 โ€” Computer Science Concepts ยท Brendan Shea, PhD*\n", "*Content licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).*\n" ] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3", "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.9" } }, "nbformat": 4, "nbformat_minor": 0 }