# More breaking down problems

We ended last time with this 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. See the lecture capture for details.

#### 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 = [reading for reading in period if reading >= 0] 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.

:EXPORT_{FILE}_{NAME}: repo/website/lectures/more-breaking-down-problems

## Shopping discount problem

We’re working for an online artisanal vegan fair-trade clothing retailer. We want to write a function that takes in a customer’s shopping cart and returns the pre-shipping, pre-tax total. There are a couple of discounts we want to apply:

- If the customer is purchasing at least $100 worth of shoes, take 20% off the cost of all shoes in the cart
- If the customer is purchasing at least two hats, take $10 off the cart’s total

Items in the shopping cart look like this:

from dataclasses import dataclass @dataclass class CartItem: name: str price: int

How would we write a `checkout`

function to compute the total price of a cart?
What are the subproblems?

We discussed two solutions–see the lecture capture for details.

### Solution 1

def checkout(cart: list): shoes = [item for item in cart if item.name == "shoes"] shoes_cost = sum([item.cost for item in shoes]) shoes_discount = 0 if shoes_cost > 100: shoes_discount = shoes_cost * 0.20 hats = [item for item in cart if item.name == "hat"] hats_discount = 0 if len(hats) >= 2: hats_discount = 10 return sum([item.cost for item in cart]) - shoes_discount - hats_discount

### Solution 2

def checkout(cart: list): shoe_total = 0 hats_seen = 0 total = 0 for item in cart: if item.name == "shoes": shoe_total += item.cost if item.name == "hats": hats_seen += 1 total += item.cost if shoe_total >= 100: total -= shoe_total * 0.20 if hats_seen >= 2: total -= 10 return total