Book-matched resources · Chapter 07 · Challenges 061–070

Debugging and Testing

Try the printed challenge before revealing a hint or the example solution. Starter files are available only where the book supplies one.

Challenge hints & worked solutions

CHALLENGE 061 · DEBUG IT

The Missing Variable

A ticket calculator should add a £12 ticket to a £3 booking fee. Instead, Python stops with a NameError. Read the error message, trace the variable names and correct the fault without changing the calculation.

Reveal a hint (from the printed book)

Compare ticket_price with ticket_prce letter by letter. A NameError often reveals an inconsistent spelling.

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 61 - The Missing Variable
# Use one spelling for each variable name.
ticket_price = 12
booking_fee = 3
total = ticket_price + booking_fee
print(f"Total: {total}")
Save this Python file ↓
CHALLENGE 062 · DEBUG IT

The Indentation Trap

The age-checking starter has the correct idea but cannot run: a return statement does not belong to the block Python expects. Repair only the indentation, then verify both decision paths.

Reveal a hint (from the printed book)

The return after if must be indented under if; the return under else must be indented under else.

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 62 - The Indentation Trap
def eligibility(age):
    if age >= 16:
        return "Eligible"
    else:
        return "Not yet eligible"

age = int(input("Enter age: "))
print(eligibility(age))
Save this Python file ↓
CHALLENGE 063 · DEBUG IT

The Price That Became Text

Two prices are entered, but the faulty program joins the text rather than adding the numbers. Repair it so the total is calculated numerically and always displays two decimal places.

Reveal a hint (from the printed book)

input() always gives text. Use float() on each input before adding; format with :.2f when printing.

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 63 - The Price That Became Text
first = float(input("First price: "))
second = float(input("Second price: "))
total = first + second
print(f"Total: {total:.2f}")
Save this Python file ↓
CHALLENGE 064 · DEBUG IT

One Extra Turn

A quiz-game loop is meant to number each turn from 1 to the chosen limit, but the starter gives the player one extra turn. Fix the endpoint and test more than one turn count.

Reveal a hint (from the printed book)

range() excludes its stop value. For N inclusive turns, use range(1, N + 1), not N + 2.

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 64 - One Extra Turn
def show_turns(turns):
    if turns < 1:
        return []
    return list(range(1, turns + 1))

turns = int(input("How many turns? "))
for turn in show_turns(turns):
    print(f"Turn {turn}")
Save this Python file ↓
CHALLENGE 065 · DEBUG IT

Validation That Never Ends

A score-entry starter repeats when a score is valid and can accept invalid scores. Its Boolean condition has been reversed. Rebuild the validation so only a whole-number score from 0 to 100 is accepted.

Reveal a hint (from the printed book)

The condition should cause repetition only when the entered value is invalid. A while True loop with break is one simple fix. Stop the faulty starter with Ctrl+C if it keeps asking.

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 65 - Validation That Never Ends
def valid_score(value):
    return 0 <= value <= 100

while True:
    score = int(input("Enter score (0-100): "))
    if valid_score(score):
        break
    print("Out of range. Try again.")
print(f"Accepted: {score}")
Save this Python file ↓
CHALLENGE 066 · SOLVE IT

The Empty String Crash

A program needs to display the first initial of a name. Directly accessing text[0] crashes when the user presses Enter without typing anything. Write safe logic that also ignores leading and trailing spaces.

Start from a blank Python file; no starter supplied for this challenge.Download worked solution .py ↓
Reveal a hint (from the printed book)

Call strip() first, then test if the result is empty before attempting [0].

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 66 - The Empty String Crash
def first_initial(text):
    name = text.strip()
    if not name:
        return "No initial"
    return name[0].upper()

name = input("Enter a name: ")
print(f"Initial: {first_initial(name)}")
Save this Python file ↓
CHALLENGE 067 · IMPROVE IT

No Items in the List

An average-calculation starter crashes if a list is empty or contains text such as absent. Improve it so only valid numeric entries count and it reports when none are available.

Reveal a hint (from the printed book)

Filter to numbers before calling sum() and len(). If none remain, return None instead of dividing.

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 67 - No Items in the List
def average_numeric(values):
    numbers = [v for v in values if isinstance(v, (int, float)) and not isinstance(v, bool)]
    if not numbers:
        return None
    return sum(numbers) / len(numbers)

for scores in ([10, 20, "absent", 30], [], [0]):
    result = average_numeric(scores)
    print("No numeric scores." if result is None else f"Average: {result:.2f}")
Save this Python file ↓
CHALLENGE 068 · SOLVE IT

The Incorrect Average

A list of 10, 20 and 30 produces an average of 30 because the program divides by one fewer item than it should. Devise checks that expose the faulty divisor, then repair it.

Reveal a hint (from the printed book)

Count how many values are present, not how many gaps are between them. Be sure the single-item test does not divide by zero.

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 68 - The Incorrect Average
def average(scores):
    if not scores:
        return None
    return sum(scores) / len(scores)

for scores in ([10, 20, 30], [5], [2, 4, 6, 8]):
    result = average(scores)
    print(f"Average: {result:.2f}" if result is not None else "No scores.")
Save this Python file ↓
CHALLENGE 069 · BUILD IT

Where Did the Answer Go?

The starter displays a triple but returns None to the caller. Replace the printed result with a returned value, then build a small test runner that checks five input/expected-output pairs.

Reveal a hint (from the printed book)

Use return number * 3, not print(). A good test stores or compares the returned result.

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 69 - Where Did the Answer Go?
def triple(number):
    return number * 3

def check_cases(cases):
    passed = 0
    for value, expected in cases:
        actual = triple(value)
        if actual == expected:
            passed += 1
        else:
            print(f"FAIL {value}: expected {expected}, got {actual}")
    print(f"Passed: {passed}/{len(cases)}")
    return passed

cases = [(0, 0), (1, 3), (2, 6), (-2, -6), (4, 12)]
check_cases(cases)
Save this Python file ↓
CHALLENGE 070 · BUILD IT

The Three-Fault Challenge

A mini test suite contains three incorrect actual results and one correct result. Build a diagnostic report so a developer can see which checks failed, what was expected and what was produced.

Reveal a hint (from the printed book)

Loop over (name, expected, actual). Compare values, count mismatches and include all details in each FAIL message.

Reveal a worked Python solution

One possible implementation. Check the book's tests and try an extension after comparing.

# Challenge 70 - The Three-Fault Challenge
def faulty_double(n):
    return n + 2  # Wrong for most inputs

def faulty_initial(text):
    return text[0].upper()  # Does not remove leading spaces

def faulty_total(items):
    return items[0]  # Ignores the remaining item prices

def report_results(cases):
    failures = 0
    for name, expected, actual in cases:
        if expected == actual:
            print(f"PASS {name}")
        else:
            failures += 1
            print(f"FAIL {name}: expected {expected!r}, actual {actual!r}")
    print(f"Failures: {failures}/{len(cases)}")
    return failures

cases = [
    ("doubling", 8, faulty_double(4)),
    ("first initial", "A", faulty_initial("  Alex")),
    ("total cost", 9, faulty_total([4, 5])),
    ("sanity check", 2, 1 + 1),
]
report_results(cases)
Save this Python file ↓