back

python workout: exercise 3

run timing

problem

For this exercise, then, we’ll assume that you run 10 km each day as part of your exercise regime. You want to know how long, on average, that run takes.

Write a function (run_timing) that asks how long it took for you to run 10 km. The function continues to ask how long (in minutes) it took for additional runs, until the user presses Enter. At that point, the function exits—but only after calculating and displaying the average time that the 10 km runs took.

For example, here’s what the output would look like if the user entered three data points:

Enter 10 km run time: 15
Enter 10 km run time: 20
Enter 10 km run time: 10
Enter 10 km run time: <enter>

Average of 15.0, over 3 runs

Note that the numeric inputs and outputs should all be floating-point values.

attempts

Off the top of my head, I’d write something like:

def run_timing():
    run_times, n_runs = 0.0, 0
    while True:
        try:
            run_time = float(input("Enter 10km run time: "))
        except ValueError:
            break
        else:
            n_runs += 1
            run_times += run_time
    print(f"Average of {run_times/n_runs:.2f}, over {n_runs} runs")

We need the except block to handle the <enter>.

Keep in mind this function will actually return on any input that can’t be cast to float not just on <enter>. We could do this by adding a conditional on the input string before casting to float but why not keep things as is for now?

solution

The book’s implementation:

def run_timing():
    """
    Asks the user repeatedly for numeric input. Prints the average time an
    d number of runs.
    """

    number_of_runs = 0
    total_time = 0

    while True:
        one_run = input('Enter 10 km run time: ')

        if not one_run:
            break

        number_of_runs += 1
        total_time += float(one_run)

     average_time = total_time / number_of_runs
     print(f'Average of {average_time}, over {number_of_runs} runs')

beyond the exercise

before & after

  • problem

    Write a function that takes a float and two integers (before and after). The function should return a float consisting of before digits before the decimal point and after digits after. Thus, if we call the function with 1234.5678, 2 and 3, the return value should be 34.567.

  • attempts

    We can just convert the float to a string, split on the dot, and use string indexing:

    def subfloat(n: float, before: int, after: int) -> float:
        before_digits, after_digits = str(n).split(".")
        return float(f"{before_digits[-before:]}.{after_digits[:after]}")
    print(subfloat(1234.5678, 2, 3))
    
    34.567
    

decimal class

  • problem

    Explore the Decimal class (http://mng.bz/oPVr), which has an alternative floating-point representation that’s as accurate as any decimal number can be. Write a function that takes two strings from the user, turns them into decimal instances, and then prints the floating-point sum of the user’s two inputs. In other words, make it possible for the user to enter 0.1 and 0.2, and for us to get 0.3 back.

  • attempts

    I’ve played around with Decimal == before - time to use it again!

    from decimal import Decimal
    def decimal_sum(n1: str, n2: str) -> float:
        return float(Decimal(n1)+Decimal(n2))
    print(decimal_sum('0.1', '0.2'))
    
    0.3
    

    Job done!

mail@jonahv.com