This repository contains solutions to exercises from the Introduction to Programming course in the Python programming language.
- Clone the repository
git clone https://github.com/askmadsen/introduction-to-programming.git
cd introduction-to-programming- Install dependencies
- Python 3.10+
- tyro
- pytest
Install all Python dependencies via:
pip install -r requirements.txt- Run all tests
python run.pyThe repository contains exercises organized by topic and programming paradigm. Each module corresponds to one or more exercises from the course PDF:
The exercises are grouped as follows:
- 2 Recursive programming with numbers
- 3 Recursive programming with lists
- 4 Recursive programming with strings
- 6 List comprehension
- 8 Imperative programming on numbers
- 9 Imperative programming on lists
- 10 Imperative programming on strings
This project uses pytest as the testing framework together with JSON-driven test cases.
Each main exercise folder (e.g. recursion/, functional/, imperative/, etc.) contains a tests/ subfolder with:
- a
test_*.pyfile — the actual pytest test code - a
test_*_cases.jsonfile — the test input/output data
You can run tests in different scopes using the provided run.py helper:
| Scope | Command | Description |
|---|---|---|
| All tests | python run.py |
Runs every test in the repository. |
| A specific folder | python run.py --folder recursion |
Runs all tests in the recursion module. |
| A specific test file | python run.py --folder recursion --file test_numbers.py |
Runs tests only for that file. |
| A specific function | python run.py --folder recursion --file test_numbers.py --func test_sum_between |
Runs only tests for that function. |
Note: Any functions that are not yet implemented will be skipped during testing and will not cause an error.
Each test file loads its input and expected output values from a JSON file, making it easy to extend or modify tests without touching the Python code.
"sum_up_to": [
[0, 0],
[1, 1],
[5, 15]
],
"sum_even": [
[7, 12],
[17, 72],
[40, 420]
],
"sum_between": [
[[1, 5], 15],
[[3, 7], 25]
]Each entry is a list of test cases:
[input_values, expected_output]- For functions with a single argument, input_values is just the value itself.
- For functions with multiple arguments, input_values is a list containing all arguments.
- expected_output is the value that the function should return.
- [5, 15] -> calls sum_up_to(5) and checks that the result equals 15.
- [[3, 7], 25] -> calls sum_between(3, 7) and checks that the result equals 25.
This structure makes it easy to add new test cases or functions without modifying the Python test code.
To add new tests, simply extend the JSON arrays with more input/output pairs.
For instance, to add another case for sum_up_to:
"sum_up_to": [
[0, 0],
[1, 1],
[5, 15],
[10, 55]
]Save the file and rerun your tests without the need to change the Python test file.
- Implement the new function in the relevant module file (e.g. recursion/numbers.py)
- Add test cases for it to the matching JSON file. For example
"new_function": [
[0, 0],
[1, 1],
[5, 15],
[10, 55]
]- Add a corresponding test block in the test_*.py file, assuming that the desired module has been imported as module:
import my_module as module # Replace `my_module` with the actual module name
@pytest.mark.parametrize("inp,expected", cases["new_function"])
def test_new_function(inp, expected):
if not hasattr(module, "new_function"):
pytest.skip("new_function() not implemented yet")
assert module.new_function(*inp) == expected- Use *inp when the function takes multiple arguments (as shown above).
- For functions with a single argument, you can pass inp directly without unpacking.