Matua Doc

Solution: Swift programming revision for Level 3

Sample answer (Swift)

This is one complete working solution that matches the requirements in the revision task. It uses a for loop, a while loop, if statements, and functions.

Full program

This section will not display correctly in presentation mode. Please press Esc to return to web page view.

import Foundation

/// Formats a `Double` as currency with exactly two decimal places.
/// - Parameter value: The numeric value to format.
/// - Returns: A string like `$6.50`.
func money(_ value: Double) -> String {
    "$" + String(format: "%.2f", value)
}

/// Returns the total (sum) of all prices in the array.
/// - Parameter prices: A list of lunch prices.
/// - Returns: The sum of all values in `prices`.
func totalCost(prices: [Double]) -> Double {
    prices.reduce(0, +)
}

/// Returns the average (mean) value of the prices.
/// - Parameter prices: A list of lunch prices.
/// - Returns: The mean of `prices`, or `0` if the array is empty.
func averageCost(prices: [Double]) -> Double {
    guard !prices.isEmpty else { return 0 }
    return totalCost(prices: prices) / Double(prices.count)
}

/// Checks if the total spending is over the given budget.
/// - Parameters:
///   - total: The total amount spent.
///   - budget: The maximum allowed budget.
/// - Returns: `true` when `total` is greater than `budget`.
func isOverBudget(total: Double, budget: Double) -> Bool {
    total > budget
}

/// Finds the most expensive lunch cost.
/// - Parameter prices: A list of lunch prices.
/// - Returns: The maximum value in `prices`, or `0` if the array is empty.
func mostExpensiveDay(prices: [Double]) -> Double {
    prices.max() ?? 0
}

@main
struct SwiftPlayground {
    /// Program entry point (typical Swift Package / SPM style).
    static func main() {
        // Input data: lunch costs for Monday to Friday.
        // Double is used because money values can include decimals.
        let lunches = [6.50, 8.00, 5.75, 9.20, 7.10]

        // The weekly budget is a constant because it does not change.
        let budget = 35.00

        // Part 2 + Part 5
        // A for loop is used to process each day’s lunch cost.
        // enumerated() provides both the index (0...4) and the price.
        for (index, price) in lunches.enumerated() {
            // Convert the zero-based index into a human-friendly day number (1...5).
            let dayNumber = index + 1
            print("Day \(dayNumber): \(money(price))")

            // Part 5: check each day’s lunch as we loop.
            // This condition runs once per lunch value.
            if price > 9.00 {
                print("High spending day detected.")
            }
        }

        // Part 6
        // Use a while loop because we don’t know in advance how many snacks
        // it will take to reach at least $10.
        let snackCost = 2.50
        var snackTotal = 0.0

        // Keep buying snacks until the total reaches the target.
        while snackTotal < 10.0 {
            snackTotal += snackCost
            print("Snack total: \(money(snackTotal))")
        }

        // Part 4 + Part 7
        // Calculate totals once and store them in named constants.
        // This improves readability and avoids repeating calculations.
        let lunchTotal = totalCost(prices: lunches)
        let combinedTotal = lunchTotal + snackTotal
        let averageLunch = averageCost(prices: lunches)

        // Print the final summary in the requested format.
        print("Lunch total: \(money(lunchTotal))")
        print("Snack total: \(money(snackTotal))")
        print("Combined total: \(money(combinedTotal))")
        print("Average lunch cost: \(money(averageLunch))")

        // Part 4: choose the correct message using an if statement.
        // The boolean function keeps the condition clear and testable.
        if isOverBudget(total: lunchTotal, budget: budget) {
            print("Warning: You overspent this week.")
        } else {
            print("You stayed within budget.")
        }

        // Extension output: show the most expensive lunch cost.
        print("Most expensive lunch: \(money(mostExpensiveDay(prices: lunches)))")
    }
}

Breakdown: Data set-up

let lunches = [6.50, 8.00, 5.75, 9.20, 7.10]
let budget = 35.00

lunches is a [Double] because the prices include decimals. budget is a constant (let) because it is a fixed comparison value for the week.

Breakdown: Money formatting

/// Formats a Double as $0.00
func money(_ value: Double) -> String {
    "$" + String(format: "%.2f", value)
}

The task examples show money with exactly two decimal places, so this helper function makes printing consistent everywhere. Putting formatting in one function avoids repeating the same formatting logic in multiple print statements.

Breakdown: Required functions (totals, average, budget)

func totalCost(prices: [Double]) -> Double {
    prices.reduce(0, +)
}

func averageCost(prices: [Double]) -> Double {
    guard !prices.isEmpty else { return 0 }
    return totalCost(prices: prices) / Double(prices.count)
}

func isOverBudget(total: Double, budget: Double) -> Bool {
    total > budget
}

totalCost uses reduce because it is the clearest way to add all values in an array. averageCost uses guard to prevent division by zero, then divides by the number of days. isOverBudget returns a boolean so the final if statement reads clearly.

Breakdown: For loop (print each day)

for (index, price) in lunches.enumerated() {
    let dayNumber = index + 1
    print("Day \(dayNumber): \(money(price))")
}

enumerated() provides both the index and the value, which is useful for producing “Day 1 … Day 5”. Adding 1 converts the zero-based index into a human-friendly day number.

Breakdown: If inside the loop (high spending day)

if price > 9.00 {
    print("High spending day detected.")
}

This if is inside the loop so it runs once per day and can detect any lunch over $9.00. It prints immediately when the condition is met, matching the task requirement.

Breakdown: While loop (snack simulation)

let snackCost = 2.50
var snackTotal = 0.0

while snackTotal < 10.0 {
    snackTotal += snackCost
    print("Snack total: \(money(snackTotal))")
}

A while loop is appropriate because you don’t know ahead of time how many snacks are needed to reach $10. The running total is printed each iteration to show the accumulation step-by-step.

Breakdown: Final summary + budget decision

let lunchTotal = totalCost(prices: lunches)
let combinedTotal = lunchTotal + snackTotal
let averageLunch = averageCost(prices: lunches)

print("Lunch total: \(money(lunchTotal))")
print("Snack total: \(money(snackTotal))")
print("Combined total: \(money(combinedTotal))")
print("Average lunch cost: \(money(averageLunch))")

if isOverBudget(total: lunchTotal, budget: budget) {
    print("Warning: You overspent this week.")
} else {
    print("You stayed within budget.")
}

Totals are calculated once and stored in named constants so the summary prints are easy to read. The budget message uses an if statement driven by the boolean function, keeping the comparison logic separate from the output.

Breakdown: Extension (most expensive lunch)

func mostExpensiveDay(prices: [Double]) -> Double {
    prices.max() ?? 0
}

print("Most expensive lunch: \(money(mostExpensiveDay(prices: lunches)))")

max() directly finds the largest value in the array, which matches “most expensive”. ?? 0 provides a safe default if the array were empty, so the function always returns a Double.