seed: curriculum content

This commit is contained in:
2026-05-07 14:32:44 +00:00
parent 9258534803
commit ec76f4f56b
100 changed files with 2846 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
---
type: module
title: "First Light"
description: "Your first Python — REPL, scripts, variables, and the syntax to write small real programs."
---
# First Light
Bash and Git got you off the ground. Now we put a real programming
language in your hands. Python is small enough to learn fast and big
enough to power half the systems running in production right now.
Ten blocks. About four and a half hours.
## What You'll Do
- Print your first Python output
- Use the interactive REPL
- Run a `.py` script
- Declare variables of every basic type
- Read input from a cadet, transform it, print it back
- Write a small calculator
## Pace
About 4.5 hours. After this you'll know enough Python syntax to
write real programs in the next module.

View File

@@ -0,0 +1,71 @@
---
type: story
title: "First Light"
xp: 25
duration: 25
difficulty: 1
---
# First Light
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, you've got the ground beneath you. Bash, Git, the cohort —
> all there. Now we hand you a language.
>
> Python. We picked it because it's small enough to learn fast, big
> enough to power half the systems running in production right now,
> and clear enough that you can read it like prose. The trade for
> "easy to read" is that some advanced concepts come later than they
> would in C or Java. We'll get to them.
>
> [TRANSMISSION CONTINUES]
## Why Python
Three reasons:
1. **Syntax that gets out of your way.** No semicolons. No braces.
Indentation is structure. You'll spend more time thinking about
the problem than fighting the language.
2. **Batteries included.** A standard library that lets you do
networking, data, files, math, dates, and more without installing
anything.
3. **It runs everywhere.** Web servers, data pipelines, scripts,
embedded systems, machine learning. The skills transfer.
## How You'll Run It
You'll meet Python in three ways:
- **`python3 -c 'expression'`** — run a one-liner from the shell
- **The REPL** — type `python3` with no argument; you get an
interactive prompt where every line runs immediately
- **A script** — write code in a `.py` file and run it with
`python3 file.py`
The next three blocks walk you through all three.
## What's Coming
After this module:
- `strings` — text processing
- `flow` — conditionals and loops
- `collections` — lists, dicts, sets
- `functions` — your own building blocks
- `files-errors` — read/write files, handle failures
- `algorithms` — recursion, classic problems
- `oop` — classes
- `capstone` — the hard ones (8 queens, sudoku, more)
Then the checkpoint.
> **[CLOSING — Mission Control]**
>
> You already know how to learn here. The hard part — the courage to
> open a terminal — is behind you. The rest is practice and patience.
>
> Open Python on the next block.
>
> [END TRANSMISSION]

View File

@@ -0,0 +1,35 @@
---
type: challenge
title: "The Greeting"
xp: 25
duration: 15
difficulty: 1
---
# The Greeting
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, your first Python. Implement a function called `greet` that
> returns the exact string:
>
> ```
> Hello, Python
> ```
>
> Two pieces of syntax:
>
> - `def name():` defines a function
> - `return value` sends a value back to whoever called it
>
> [END TRANSMISSION]
## Your Task
Open `starter/starter.py`. Replace `pass` with a `return` statement
that returns `"Hello, Python"`.
## Objectives
- A function `greet` exists
- `greet()` returns `"Hello, Python"`

View File

@@ -0,0 +1,3 @@
def greet():
"""Return the string 'Hello, Python'."""
pass

View File

@@ -0,0 +1,5 @@
from solution import greet
def test_greet_returns_hello_python():
assert greet() == "Hello, Python"

View File

@@ -0,0 +1,43 @@
---
type: challenge
title: "The REPL"
xp: 25
duration: 25
difficulty: 1
---
# The REPL
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, the *REPL* — Read, Evaluate, Print, Loop — is Python's
> interactive shell. Open it on your machine with `python3` and
> every line you type runs immediately:
>
> ```
> >>> 5 + 7
> 12
> >>> "Hello".upper()
> 'HELLO'
> ```
>
> Use the REPL to figure out the answers. Then write them into a
> function `compute` that returns a tuple of all five, in order:
>
> 1. `5 + 7`
> 2. `100 - 25`
> 3. `6 * 8`
> 4. `"Hello" + " " + "World"`
> 5. `2 ** 10`
>
> [END TRANSMISSION]
## Your Task
Open `starter/starter.py`. Replace `pass` with a `return` of a
5-element tuple containing the values above.
## Objectives
- `compute()` returns a 5-element tuple
- Each element matches the corresponding expression

View File

@@ -0,0 +1,10 @@
def compute():
"""Return a tuple of 5 computed values, in this order:
1. 5 + 7
2. 100 - 25
3. 6 * 8
4. "Hello" + " " + "World"
5. 2 ** 10
"""
pass

View File

@@ -0,0 +1,25 @@
from solution import compute
def test_returns_five_values():
assert len(compute()) == 5
def test_first_is_addition():
assert compute()[0] == 12
def test_second_is_subtraction():
assert compute()[1] == 75
def test_third_is_multiplication():
assert compute()[2] == 48
def test_fourth_is_string_concat():
assert compute()[3] == "Hello World"
def test_fifth_is_power():
assert compute()[4] == 1024

View File

@@ -0,0 +1,31 @@
---
type: challenge
title: "The Script"
xp: 25
duration: 20
difficulty: 1
---
# The Script
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, real Python files hold *multiple* functions. Each one does
> a single, named job. The grader can call any of them by name.
>
> Implement two functions in the same file:
>
> - `hello()` returns `"From the script"`
> - `goodbye()` returns `"Out"`
>
> [END TRANSMISSION]
## Your Task
Open `starter/starter.py`. Replace each `pass` with the right
`return` statement.
## Objectives
- `hello()` returns `"From the script"`
- `goodbye()` returns `"Out"`

View File

@@ -0,0 +1,8 @@
def hello():
"""Return the string 'From the script'."""
pass
def goodbye():
"""Return the string 'Out'."""
pass

View File

@@ -0,0 +1,9 @@
from solution import hello, goodbye
def test_hello_returns_correct_string():
assert hello() == "From the script"
def test_goodbye_returns_correct_string():
assert goodbye() == "Out"

View File

@@ -0,0 +1,40 @@
---
type: challenge
title: "The Vault"
xp: 50
duration: 25
difficulty: 1
---
# The Vault
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, every program needs to remember things. Variables hold
> values; types tell Python what kind of value:
>
> - `int` — whole numbers, like `3`
> - `float` — decimals, like `4500.5`
> - `str` — text in quotes, like `"Apollo"`
> - `bool` — `True` or `False`
>
> A **dictionary** maps keys to values. Implement a function `vault`
> that returns a dictionary with exactly these four keys and values:
>
> ```
> "mission": "Apollo"
> "crew_size": 3
> "fuel_kg": 4500.5
> "ready": True
> ```
>
> [END TRANSMISSION]
## Your Task
Open `starter/starter.py`. Replace `pass` with `return { ... }`.
## Objectives
- `vault()` returns a dict
- Each key holds the exact value above (and the right type)

View File

@@ -0,0 +1,9 @@
def vault():
"""Return a dictionary with these four keys and exact values:
"mission": "Apollo" (str)
"crew_size": 3 (int)
"fuel_kg": 4500.5 (float)
"ready": True (bool)
"""
pass

View File

@@ -0,0 +1,29 @@
from solution import vault
def test_returns_dict():
assert isinstance(vault(), dict)
def test_mission_is_correct_string():
v = vault()
assert v["mission"] == "Apollo"
assert isinstance(v["mission"], str)
def test_crew_size_is_correct_int():
v = vault()
assert v["crew_size"] == 3
assert isinstance(v["crew_size"], int)
assert not isinstance(v["crew_size"], bool)
def test_fuel_kg_is_correct_float():
v = vault()
assert v["fuel_kg"] == 4500.5
assert isinstance(v["fuel_kg"], float)
def test_ready_is_true_bool():
v = vault()
assert v["ready"] is True

View File

@@ -0,0 +1,37 @@
---
type: challenge
title: "The Translator"
xp: 50
duration: 25
difficulty: 2
---
# The Translator
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, when input comes in as text (a `str`), you can't do math
> with it directly. You have to *translate* it to a number.
>
> Three converters:
>
> - `int("42")` → `42`
> - `float("3.14")` → `3.14`
> - `str(42)` → `"42"`
>
> Implement `years_until(age)` that returns `100 - age` as an `int`.
> The argument may arrive as either `int` or `str` — handle both
> by calling `int()` on it first.
>
> [END TRANSMISSION]
## Your Task
Open `starter/starter.py`. Convert `age` with `int()`, then return
`100 - age`.
## Objectives
- `years_until(25)` returns `75`
- `years_until("25")` also returns `75` (handles string input)
- Works for any integer age 0100

View File

@@ -0,0 +1,11 @@
def years_until(age):
"""Return how many years remain until age 100.
The argument may arrive as an int OR as a string (like "25"),
so convert it to int first.
years_until(25) -> 75
years_until("7") -> 93
years_until(60) -> 40
"""
pass

View File

@@ -0,0 +1,21 @@
from solution import years_until
def test_int_input_25():
assert years_until(25) == 75
def test_int_input_7():
assert years_until(7) == 93
def test_int_input_60():
assert years_until(60) == 40
def test_string_input_converted():
assert years_until("25") == 75
def test_zero():
assert years_until(0) == 100

View File

@@ -0,0 +1,40 @@
---
type: challenge
title: "The Prompt"
xp: 50
duration: 25
difficulty: 2
---
# The Prompt
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, every program takes input. In this stage, your functions
> receive input as *parameters* — values passed in by whoever called
> you.
>
> *f-strings* (formatted strings) embed values directly into text:
>
> ```python
> name = "Vega"
> f"Hello, {name}!" # → "Hello, Vega!"
> ```
>
> Implement `welcome(name, planet)` that returns:
>
> ```
> Welcome, <name> from <planet>.
> ```
>
> [END TRANSMISSION]
## Your Task
Open `starter/starter.py`. Use an f-string to return the welcome
message.
## Objectives
- `welcome("Vega", "Mars")``"Welcome, Vega from Mars."`
- Works for any name and planet

View File

@@ -0,0 +1,8 @@
def welcome(name, planet):
"""Return a welcome string of the form:
"Welcome, <name> from <planet>."
welcome("Vega", "Mars") -> "Welcome, Vega from Mars."
"""
pass

View File

@@ -0,0 +1,13 @@
from solution import welcome
def test_vega_mars():
assert welcome("Vega", "Mars") == "Welcome, Vega from Mars."
def test_halo_earth():
assert welcome("Halo", "Earth") == "Welcome, Halo from Earth."
def test_orbit_seven_europa():
assert welcome("Orbit-7", "Europa") == "Welcome, Orbit-7 from Europa."

View File

@@ -0,0 +1,44 @@
---
type: challenge
title: "The Formatter"
xp: 50
duration: 25
difficulty: 2
---
# The Formatter
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, raw numbers like `9.99` print fine, but `29.970000000000002`
> doesn't. Real programs *format* numbers. f-strings can do it inline:
>
> ```python
> price = 9.99
> f"${price:.2f}" # → "$9.99"
> ```
>
> The `:.2f` is a *format spec*: two decimal places, fixed-point.
>
> Implement `format_receipt(price, qty)` that returns a 3-line string:
>
> ```
> Item price: $<price>
> Quantity: <qty>
> Total: $<price * qty>
> ```
>
> Both prices use 2-decimal formatting. Use `\n` to join lines.
>
> [END TRANSMISSION]
## Your Task
Open `starter/starter.py`. Compute `total`, then return a single
f-string with `\n` separators.
## Objectives
- `format_receipt(9.99, 3)` returns the exact 3-line string
- Prices format to 2 decimal places
- Works for any positive `price` and `qty`

View File

@@ -0,0 +1,13 @@
def format_receipt(price, qty):
"""Return a 3-line formatted receipt as a single string.
Format (note the dollar sign and 2-decimal places on prices):
Item price: $<price>
Quantity: <qty>
Total: $<price * qty>
format_receipt(9.99, 3) returns:
"Item price: $9.99\nQuantity: 3\nTotal: $29.97"
"""
pass

View File

@@ -0,0 +1,13 @@
from solution import format_receipt
def test_basic():
assert format_receipt(9.99, 3) == "Item price: $9.99\nQuantity: 3\nTotal: $29.97"
def test_round_numbers():
assert format_receipt(100, 1) == "Item price: $100.00\nQuantity: 1\nTotal: $100.00"
def test_decimal_quantity_one():
assert format_receipt(1.5, 10) == "Item price: $1.50\nQuantity: 10\nTotal: $15.00"

View File

@@ -0,0 +1,44 @@
---
type: challenge
title: "The Temperature"
xp: 75
duration: 30
difficulty: 2
---
# The Temperature
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, half the world reads temperature in Fahrenheit, the other
> half in Celsius. Build a converter.
>
> Formula: `C = (F - 32) * 5 / 9`
>
> Implement `f_to_c(f)` that returns a string of the form:
>
> ```
> <F>°F = <C>°C
> ```
>
> Where `<C>` is rounded to one decimal place using `:.1f`. Convert
> the input with `float()` first so the output is consistent for
> int and float inputs.
>
> Examples:
>
> - `f_to_c(32)` → `"32.0°F = 0.0°C"`
> - `f_to_c(212)` → `"212.0°F = 100.0°C"`
> - `f_to_c(98.6)` → `"98.6°F = 37.0°C"`
>
> [END TRANSMISSION]
## Your Task
In `starter/starter.py`, convert `f` to float, compute Celsius,
return the formatted string.
## Objectives
- All three examples produce the exact expected string
- Works for any numeric F input

View File

@@ -0,0 +1,13 @@
def f_to_c(f):
"""Convert Fahrenheit to Celsius and return a formatted string.
Formula: C = (F - 32) * 5 / 9
The Celsius value should be formatted with 1 decimal place.
Convert the Fahrenheit input with float() so output is consistent.
f_to_c(32) -> "32.0°F = 0.0°C"
f_to_c(212) -> "212.0°F = 100.0°C"
f_to_c(98.6) -> "98.6°F = 37.0°C"
"""
pass

View File

@@ -0,0 +1,17 @@
from solution import f_to_c
def test_freezing():
assert f_to_c(32) == "32.0°F = 0.0°C"
def test_boiling():
assert f_to_c(212) == "212.0°F = 100.0°C"
def test_body_temp():
assert f_to_c(98.6) == "98.6°F = 37.0°C"
def test_zero_fahrenheit():
assert f_to_c(0) == "0.0°F = -17.8°C"

View File

@@ -0,0 +1,42 @@
---
type: challenge
title: "The Calculator"
xp: 100
duration: 35
difficulty: 2
---
# The Calculator
> **[INCOMING — Mission Control, Earth]**
>
> Cadet, capstone. Combine everything you've learned in this module
> into one program.
>
> Implement `calculate(a, b)` that returns a dictionary with all four
> basic operations:
>
> ```python
> {
> "sum": a + b,
> "difference": a - b,
> "product": a * b,
> "quotient": a / b,
> }
> ```
>
> Convert both inputs with `float()` so results are consistent — and
> so string inputs work too.
>
> [END TRANSMISSION]
## Your Task
In `starter/starter.py`, convert both inputs to float, then return
the dictionary with the four keys above.
## Objectives
- `calculate(10, 5)` returns the four operations as a dict
- Works with int, float, and string inputs
- All values are floats

View File

@@ -0,0 +1,15 @@
def calculate(a, b):
"""Return a dict with the four basic operations on (a, b).
Convert both inputs with float() so output is consistent.
Returned dict has these exact keys:
"sum" — a + b
"difference" — a - b
"product" — a * b
"quotient" — a / b
calculate(10, 5) -> {"sum": 15.0, "difference": 5.0,
"product": 50.0, "quotient": 2.0}
"""
pass

View File

@@ -0,0 +1,34 @@
from solution import calculate
def test_returns_dict_with_four_keys():
r = calculate(10, 5)
assert set(r.keys()) == {"sum", "difference", "product", "quotient"}
def test_basic_ten_five():
r = calculate(10, 5)
assert r["sum"] == 15.0
assert r["difference"] == 5.0
assert r["product"] == 50.0
assert r["quotient"] == 2.0
def test_seven_two():
r = calculate(7, 2)
assert r["sum"] == 9.0
assert r["difference"] == 5.0
assert r["product"] == 14.0
assert r["quotient"] == 3.5
def test_decimals():
r = calculate(3.5, 1.5)
assert r["sum"] == 5.0
assert r["difference"] == 2.0
assert r["product"] == 5.25
def test_string_inputs_converted():
r = calculate("10", "5")
assert r["sum"] == 15.0