Python Foundations · Solutions

Exercise Solutions – Python Foundations (Days 1–7)

These are model solutions for the Python Foundations exercises. They are designed to be clear and idiomatic, but they are not the only valid answers.

Recommendation: try each exercise yourself first on the relevant day page, then come here to compare your approach with these solutions.

Day 1 – Solutions

Exercise 1.1 – Personal Profile

first_name = "Jordan"
age = 28
height_m = 1.78
has_programmed_before = True

print("Name:", first_name)
print("Age:", age)
print("Height (m):", height_m)
print("Has programmed before:", has_programmed_before)

Exercise 1.2 – Type Detective

city = "London"
year = 2025
price = 19.99
is_student = False
temperature = -3

print(city, type(city))
print(year, type(year))
print(price, type(price))
print(is_student, type(is_student))
print(temperature, type(temperature))

Exercise 1.3 – Challenge: What Happens Here?

Expected output:

x = 10
y = x
x = 20
print(x)  # 20
print(y)  # 10

Day 2 – Solutions

Exercise 2.1 – String Surgery

raw_data = "   product_name: Widget Pro   "

clean = raw_data.strip()

print(clean.upper())
print(clean.lower())
print(clean.lower())

Exercise 2.2 – The Calculator

first = float(input("Enter the first number: "))
second = float(input("Enter the second number: "))

print("Addition:", first + second)
print("Subtraction:", first - second)
print("Multiplication:", first * second)
print("Division:", first / second)
print("Floor division:", first // second)
print("Remainder:", first % second)
print("Power:", first ** second)

Exercise 2.3 – Greeting Card Generator

first_name = input("First name: ")
last_name = input("Last name: ")
age = int(input("Age: "))

border = "=" * 29
in_5_years = age + 5

print(border)
print(f"  Welcome, {first_name} {last_name}!")
print(f"  Age: {age}")
print(f"  In 5 years: {in_5_years}")
print(border)

Exercise 2.4 – Challenge: Slicing Practice

text = "Data Analytics Programme"

print(text[0:4])        # "Data"
print(text[5:14])       # "Analytics"
print(text[15:24])      # "Programme"
print(text[15:24][::-1])  # "emmargorP"

Day 3 – Solutions

Exercise 3.1 – FizzBuzz

for n in range(1, 51):
    if n % 3 == 0 and n % 5 == 0:
        print("FizzBuzz")
    elif n % 3 == 0:
        print("Fizz")
    elif n % 5 == 0:
        print("Buzz")
    else:
        print(n)

Exercise 3.2 – Grade Classifier

while True:
    try:
        score = int(input("Enter score (0–100): "))
    except ValueError:
        print("Please enter a valid integer.")
        continue

    if 0 <= score <= 100:
        break

    print("Score must be between 0 and 100.")

if score >= 90:
    grade = "A"
    message = "Excellent"
elif score >= 75:
    grade = "B"
    message = "Good work"
elif score >= 60:
    grade = "C"
    message = "Satisfactory"
elif score >= 40:
    grade = "D"
    message = "Needs improvement"
else:
    grade = "F"
    message = "Please see your tutor"

print(f"Score: {score} | Grade: {grade} – {message}")

Exercise 3.3 – Multiplication Table Generator

n = int(input("Enter a number: "))

print(f"Multiplication table for {n}")
for i in range(1, 13):
    left = f"{n:2d}"
    right = f"{n * i:3d}"
    print(f"{left} x {i:2d} = {right}")

Exercise 3.4 – Challenge: Number Guessing Game

target = 42
attempts = 0

while True:
    try:
        guess = int(input("Guess the number: "))
    except ValueError:
        print("Please enter an integer.")
        continue

    attempts += 1

    if guess < target:
        print("Too low.")
    elif guess > target:
        print("Too high.")
    else:
        print(f"Correct! You needed {attempts} attempts.")
        break

Day 4 – Solutions

Exercise 4.1 – Student List Manager

students = ["Alice", "Bob", "Charlie"]

students.append("Diana")
students.insert(1, "Eve")
students.remove("Charlie")

students.sort()

print("Students:", students)
print("Count:", len(students))

Exercise 4.2 – Word Frequency Counter

text = "the cat sat on the mat the cat sat"
words = text.split()

counts = {}

for word in words:
    counts[word] = counts.get(word, 0) + 1

print(counts)

Exercise 4.3 – Data Cleaning with List Comprehensions

raw_cities = ["  london", "PARIS  ", "berlin", "  MADRID  ", "rome  "]

clean_cities = [city.strip().title() for city in raw_cities]
print(clean_cities)

Exercise 4.4 – Challenge: Inventory System

inventory = {
    "Laptop": {"price": 899.0, "stock": 3},
    "Mouse": {"price": 25.0, "stock": 15},
    "Monitor": {"price": 180.0, "stock": 2},
    "Keyboard": {"price": 55.0, "stock": 8},
}

print("Low stock items:")
for name, data in inventory.items():
    if data["stock"] < 5:
        print(f"- {name} (stock: {data['stock']})")

for data in inventory.values():
    if data["price"] > 50:
        data["price"] = round(data["price"] * 0.9, 2)

print("\nUpdated inventory:")
for name, data in inventory.items():
    price = f"£{data['price']:.2f}"
    print(f"{name:<10} | Price: {price:<8} | Stock: {data['stock']}")

Day 5 – Solutions

Exercise 5.1 – Temperature Converter

def celsius_to_fahrenheit(celsius):
    return (celsius * 9 / 5) + 32


def fahrenheit_to_celsius(fahrenheit):
    return (fahrenheit - 32) * 5 / 9


def convert_temperature(value, unit):
    if unit == "C":
        result = celsius_to_fahrenheit(value)
        return round(result, 2), "F"
    elif unit == "F":
        result = fahrenheit_to_celsius(value)
        return round(result, 2), "C"
    else:
        raise ValueError("Unit must be 'C' or 'F'")


tests = [(20, "C"), (98.6, "F"), (0, "C"), (212, "F")]

for value, unit in tests:
    converted, target_unit = convert_temperature(value, unit)
    print(f"{value}{unit} -> {converted}{target_unit}")

Exercise 5.2 – Basic Data Cleaning Function

def clean_string(text):
    text = text.strip()
    text = " ".join(text.split())
    return text.title()


def clean_dataset(data):
    return [clean_string(item) for item in data]


raw = ["  alice   smith  ", "BOB    JONES", "   charlie   brown   "]
clean = clean_dataset(raw)
print(clean)

Exercise 5.3 – Statistics Functions

def mean(numbers):
    return sum(numbers) / len(numbers)


def variance(numbers):
    m = mean(numbers)
    squared_diffs = [(x - m) ** 2 for x in numbers]
    return sum(squared_diffs) / len(numbers)


def std_dev(numbers):
    return variance(numbers) ** 0.5


data = [10, 12, 23, 23, 16, 23, 21, 16]
print("Mean:", mean(data))
print("Variance:", variance(data))
print("Std dev:", std_dev(data))

Exercise 5.4 – Challenge: Flexible Report Generator

def generate_report(**data):
    title = data.pop("title", "Untitled")

    lines = []
    lines.append("=" * 29)
    lines.append(f"REPORT: {title}")
    lines.append("-" * 30)

    for key, value in data.items():
        lines.append(f"{key:<8}: {value}")

    lines.append("=" * 29)

    report = "\n".join(lines)
    print(report)
    return report


generate_report(title="Q1 Sales", region="North", total=125000, growth="12%")

Day 6 – Solutions

Exercise 6.1 – File Round-Trip

students = [
    ("Alice", 88, "B"),
    ("Bob", 72, "C"),
    ("Charlie", 59, "D"),
    ("Diana", 95, "A"),
    ("Eve", 81, "B"),
]

with open("students.csv", "w") as f:
    f.write("name,score,grade\n")
    for name, score, grade in students:
        f.write(f"{name},{score},{grade}\n")

with open("students.csv", "r") as f:
    lines = f.readlines()

for line in lines[1:]:
    name, score_str, grade = line.strip().split(",")
    score = int(score_str)
    print(f"{name} – score: {score}, grade: {grade}")

Exercise 6.2 – Robust Input Validator

def get_positive_integer(prompt):
    while True:
        raw = input(prompt)
        try:
            value = int(raw)
        except ValueError:
            print("Please enter a whole number.")
            continue

        if value > 0:
            return value

        print("Please enter a number greater than 0.")


n = get_positive_integer("Enter a positive integer: ")
print("You entered:", n)

Exercise 6.3 – Date Calculator

from datetime import date, datetime

today = date.today()

raw = input("Enter a date (DD/MM/YYYY): ")

try:
    target = datetime.strptime(raw, "%d/%m/%Y").date()
except ValueError:
    print("Invalid date format.")
else:
    delta_days = (target - today).days

    if delta_days == 0:
        print("Today!")
    elif delta_days > 0:
        print(f"{delta_days} days to go.")
    else:
        print(f"{-delta_days} days ago.")

Exercise 6.4 – Challenge: Log File Analyser

filepath = "log.txt"

with open(filepath, "r") as f:
    lines = [line.strip() for line in f if line.strip()]

total_entries = len(lines)
level_counts = {"ERROR": 0, "WARNING": 0, "INFO": 0}
error_entries = []

for line in lines:
    date_str, level, message = line.split(None, 2)
    if level in level_counts:
        level_counts[level] += 1
    if level == "ERROR":
        error_entries.append((date_str, message))

print("Total entries:", total_entries)
print("By level:", level_counts)
print("\nERROR entries:")
for date_str, message in error_entries:
    print(f"- {date_str} – {message}")

Day 7 – Capstone Hints / Skeleton

For the Day 7 capstone project (Student Score Analyser), there are many valid implementations. Below is a clear reference structure rather than a strict “one true” solution.

def get_grade(avg):
    if avg >= 90:
        return "A"
    if avg >= 75:
        return "B"
    if avg >= 60:
        return "C"
    if avg >= 40:
        return "D"
    return "F"


def load_data(filepath):
    students = {}

    with open(filepath, "r") as f:
        lines = f.readlines()

    headers = lines[0].strip().split(",")

    for line in lines[1:]:
        name, subject, score_str = line.strip().split(",")

        if name not in students:
            students[name] = {"scores": [], "invalid": 0}

        try:
            score = float(score_str)
        except ValueError:
            students[name]["invalid"] += 1
            continue

        if 0 <= score <= 100:
            students[name]["scores"].append(score)
        else:
            students[name]["invalid"] += 1

    return students


def build_report(students):
    lines = []
    lines.append("=" * 51)
    lines.append("         STUDENT SCORE ANALYSER REPORT")
    lines.append("=" * 51)
    lines.append("Student       Avg    High   Low    Grade")
    lines.append("-" * 50)

    class_averages = []
    top_name = None
    top_avg = None

    for name, data in students.items():
        scores = data["scores"]
        if not scores:
            continue

        avg = sum(scores) / len(scores)
        high = max(scores)
        low = min(scores)
        grade = get_grade(avg)

        class_averages.append(avg)

        if top_avg is None or avg > top_avg:
            top_avg = avg
            top_name = name

        invalid_note = ""
        if data["invalid"] > 0:
            invalid_note = f"    [{data['invalid']} invalid score(s) skipped]"

        lines.append(
            f"{name:<12}{avg:5.1f}   {high:4.0f}  {low:5.0f}   {grade}{invalid_note}"
        )

    lines.append("-" * 50)

    if class_averages:
        class_avg = sum(class_averages) / len(class_averages)
        lines.append(f"Class average : {class_avg:.1f}")
    if top_name is not None:
        lines.append(f"Top student   : {top_name} ({top_avg:.1f})")

    lines.append("=" * 51)

    return "\n".join(lines)


def main():
    filepath = "students_data.csv"
    students = load_data(filepath)
    report = build_report(students)
    print(report)

    with open("report.txt", "w") as f:
        f.write(report)

    print("Report saved to: report.txt")


if __name__ == "__main__":
    main()