A program is a sequence of precise decisions
A computer does not infer what you intended. A program represents inputs, performs operations and produces outputs. Begin by describing the rule in ordinary language: “If the total is greater than the budget, report over budget.” Identify equality separately. Many bugs come from a rule that was never made precise.
Use Python 3 for these exercises. Run code in the Code Playground, or save it as practice.py and run python3 practice.py locally. These examples avoid version-specific syntax.
Values, variables and types
A variable names a value. Integers are useful for counts, strings for text and booleans for true/false decisions. Choose units explicitly. For money, integer paise avoids binary floating-point rounding in this exercise.
price_paise = 12500
quantity = 2
customer = "Asha"
is_student = True
total_paise = price_paise * quantity
assert total_paise == 25000
print(customer, total_paise)
Assignment changes what a name refers to. Comparison asks a question. In Python, = assigns and == compares. A value returned by input() is a string; convert it before numeric arithmetic.
raw = "12" # Replace with input("Quantity: ") in a terminal.
quantity = int(raw)
assert quantity + 3 == 15
assert raw + "3" == "123"
The conversion fails for nonnumeric input. Do not silently turn invalid input into zero: that conceals the difference between “no quantity” and “could not parse quantity.”
Conditions and boundary cases
def budget_status(total, budget):
if total < 0 or budget < 0:
raise ValueError("Amounts must be non-negative")
if total > budget:
return "over"
if total == budget:
return "exact"
return "within"
assert budget_status(90, 100) == "within"
assert budget_status(100, 100) == "exact"
assert budget_status(101, 100) == "over"
Test just below, exactly at and just above a boundary. A condition that works on one ordinary input may still misclassify equality. Boolean and requires both conditions; or requires at least one. Parentheses help communicate combined rules.
Loops and invariants
A loop repeats work. An invariant describes what remains true as it progresses. In this sum, after processing each value, total equals the sum of the values seen so far.
values = [4, 7, 2]
total = 0
for value in values:
total += value
assert total == 13
Python's range(1, 5) includes 1 through 4, not 5. A while loop requires a state change that eventually makes the condition false. If you remove remaining -= 1 below, the loop does not terminate.
remaining = 3
while remaining > 0:
remaining -= 1
assert remaining == 0
Exercises — attempt before reading the answers
- Convert a non-negative number of minutes into complete hours and leftover minutes. For 135, expect 2 hours and 15 minutes. Reject negative inputs.
- Return whether an integer is divisible by both 3 and 5. Check zero and a negative integer as well as 15 and 9.
- Count even integers in a list, including negative values and zero. For
[0, -2, 3, 4], expect 3. - Compute the sum from 1 through n with a loop. Reject negative n. For n equal to zero, expect zero.
- Find the maximum value in a list. For an empty list return
None; do not use zero as the initial maximum because every input may be negative.
Explained answers
def split_minutes(minutes):
if minutes < 0:
raise ValueError("Minutes must be non-negative")
return minutes // 60, minutes % 60
def divisible_by_both(number):
return number % 3 == 0 and number % 5 == 0
def count_even(numbers):
count = 0
for number in numbers:
if number % 2 == 0:
count += 1
return count
def sum_to(n):
if n < 0:
raise ValueError("n must be non-negative")
total = 0
for number in range(1, n + 1):
total += number
return total
def maximum(numbers):
if not numbers:
return None
best = numbers[0]
for number in numbers[1:]:
if number > best:
best = number
return best
assert split_minutes(135) == (2, 15)
assert split_minutes(0) == (0, 0)
assert divisible_by_both(0)
assert divisible_by_both(-15)
assert not divisible_by_both(9)
assert count_even([0, -2, 3, 4]) == 3
assert sum_to(0) == 0
assert sum_to(4) == 10
assert maximum([-8, -3, -5]) == -3
assert maximum([]) is None
Integer division calculates complete groups; modulo calculates the remainder. The even-counting loop performs one test per input, so it takes O(n) time and O(1) extra space. The maximum function's slice creates an extra list in Python; to avoid it, iterate by index or use an iterator. This is an example of a language detail changing space usage even when the algorithm looks simple.
Checkpoint and next step
Reimplement these functions without looking. Add one invalid-input test and one boundary test for each function. Explain why the maximum of negative numbers cannot start at zero. Then continue to Functions and collections.
Reference: Python control flow tutorial. The examples above are original teaching exercises.