Problem solving

HW2, problem 2

We talked about how to get started on the find_combinations function from HW2. See the lecture capture for details.

Breaking down problems

Let’s say we have a problem we want to solve by writing a program. How should we start?

I would recommend starting by breaking down the problem into smaller pieces. Then we can solve each subproblem, and combine these solutions together into a solution to the whole problem. Some subproblems can be solved by writing helper functions, and we’ve seen a number of examples of this. Other times, subproblems correspond to calls to built-in functions, or particular variables we keep track of.

Rainfall problem

Let’s say we are tracking daily rainfall in a particular location, and we want to compute the average rainfall over the period for which we have useful sensor readings. Our rainfall sensor is a bit unreliable, and reports data in a weird format (both of these problems are things you’re likely to encounter when dealing with real-world data!). In particular, our sensor data is a list of numbers like:

sensor_data = [1, 6, -2, 4, -999, 4, 5]

The -999 represents the end of the period we’re interested in. The other negative numbers represent sensor error–we can’t really have a negative amount of rainfall. So we want to take the average of the non-negative numbers in the input list before the -999. How would we solve this problem? What are the subproblems?

  • Finding the list segment before the -999
  • Filtering out the negative values
  • Computing the average of the positive rainfall days

We developed two solutions.

Solution 1

def average_rainfall(sensor_input: lst) -> float:
  number_of_readings = 0
  total_rainfall = 0
  for reading in sensor_input:
    if reading == -999:
      return number_of_readings / total_rainfall
    elif reading >= 0:
      number_of_readings += 1
      total_rainfall += rainfall

In this solution, we loop over the list once. The first two subproblems are solved by returning early from the list and by ignoring the negative values in our loop. The final subproblem is solved with the number_of_readings and total_rainfall variables.

Solution 2

def list_before(l: list, item) -> list:
  result = []
  for element in l:
    if element == item:
      return result
    result.append(element)
  return result

def average_rainfall(sensor_input: lst) -> float:
  readings_in_period = list_before(sensor_input, -999)
  good_readings = list(filter(lambda x: x >= 0, readings_in_period))
  return sum(good_readings) / len(good_readings)

In this solution, the first subproblem is solved with a helper funciton, the second subproblem with a call to the built-in filter function, and the third subproblem with calls to the built-in sum and len functions.