Practice Problems 2 Solutions

  1. Each of the following loops is an attempt to sum up the numbers from 1 to n, e.g.1+2+ ... +n (you can assume n is initialized to some value). For each case, explain why the code doesn’t actually sum the numbers 1 through n.

    a.

     sum = 0
     for i in range(n):
         sum = sum + i
    

    This is close, but recall that range(n) is equivalent to range(0,n) and produce the sequence 0, 1, …, n-1 and so this loop sums 0, 1, …, n-1. It can be fixed as:

     sum = 0
     for i in range(n):
         sum = sum + (i + 1)
    

    b.

     sum = 0
     for i in range(n):
         temp = sum + (i+1)
     sum = temp
    

    Here we’re not updating sum every time through the loop, so each time we access sum in temp = sum + (i+1) the value will still be 0. The final value of temp (and therefor sum) when this code finishes will just be n. It can be fixed as shown above (eliminate temp).

    c.

     sum = 0
     for i in range(n):
         sum = (i+1)
    

    Here we’re are updating sum, but we’re not accumulating. Instead, each time sum will just get i+1. Again, when we’re done, sum will just be n. The loop body needs to be changed to sum = sum + (i+1).

    d.

     sum = 0
     for i in range(n):
         temp = (i+1)
         sum = temp
    

    This is the same problem as c., except now we’ve broken it into two steps, first assigning (i+1) to temp and then temp to sum. Again the loop body needs to be change to accumulate.

  2. Write a function named factorial that has a single parameter, an integer n, and returns n!, i.e. 1*2*3* ... n.

     def factorial(n):
         """
         Return n factorial for integer argument
         """
         result = 1
         for i in range(n):
             result = result * (i + 1)
         return result
    

    Recall that range(n) starts with 0. Alternately recall that range allows you to specify the start value, so you could implement factorial as:

     def factorial2(n):
         """
         Return n factorial for integer argument
         """
         result = 1
         for i in range(1, n+1):
             result = result * i
         return result
    
  3. Write a docstring for the following function

    Recall from lecture that a docstring should include a brief description of what the function does, what, if any, arguments it expects (i.e. what are its parameters), and what, if any, it returns.

     def mystery():
         """
         Print the first 5 even numbers, one per line
            
         Args:
           None
              
         Returns:
           None
         """
         for i in range(5):
             print(2 + 2*i)
    
  4. Write a function named rand_time that returns a random valid time in HH:MM format as a string. The result can have only a single hour digit, i.e. 1:01 and 10:15 are valid results, but must have two minutes digits, i.e. 1:1 is not a valid result. As a trickier extension, adapt your function to always generate two hour digits, i.e. 1:01 should be represented as 01:01.

     def rand_time():
         """
         Generate a random time in HH:MM format
    
         Args:
           None
    
         Returns:
           Time as a string
         """
         return str(randint(1, 12)) + ":" + str(randint(0, 5)) + str(randint(0, 9))
    

    Note that we need to generate each minutes digit separately to ensure we always get two digits. If we want to do the same for the hours digits as well, we will need to be more sophisticated because the range of the “ones place” depends on the tens place. We can use floor division and modulus to extract those two digits from a randomly generated hour.

     def rand_time2():
         """
         Generate a random time in HH:MM format
    
         Args:
           None
    
         Returns:
           Time as a string
         """
         hours = randint(1, 12)
         return str(hours // 10) + str(hours % 10) + ":" + str(randint(0, 5)) + str(randint(0, 9))