# Within Margin Percentage¶

An algorithm is required to test out what percentage of the parts that a factory is producing fall within a safety margin of the design specifications. Given a list of values recording the metrics of the manufactured parts, a list of values representing the desired metrics required by the design, and a margin of error allowed by the design, compute what fraction of the values are within the safety margin (

`<=`

)

```
# example behavior
>>> within_margin_percentage(desired=[10.0, 5.0, 8.0, 3.0, 2.0],
... actual= [10.3, 5.2, 8.4, 3.0, 1.2],
... margin=0.5)
0.8
```

See that \(4/5\) of the values fall within the margin of error: \(1.2\) deviates from \(2\) by more than \(0.5\).

Complete the following function; consider the edge case where `desired`

and `actual`

are empty lists.

```
def within_margin_percentage(desired, actual, margin):
""" Compute the percentage of values that fall within
a margin of error of the desired values
Parameters
----------
desired: List[float]
The desired metrics
actual: List[float]
The corresponding actual metrics.
Assume `len(actual) == len(desired)`
margin: float
The allowed margin of error
Returns
-------
float
The fraction of values where |actual - desired| <= margin
"""
# YOUR CODE HERE
pass
```

You will want to be familiar with comparison operators, control flow, and indexing lists lists to solve this problem.

## Solution¶

This problem can solved by simply looping over the pairs of actual and desired values and tallying the pairs that fall within the margin:

```
def within_margin_percentage(desired, actual, margin):
""" Compute the percentage of values that fall within
a margin of error of the desired values
Parameters
----------
desired: List[float]
The desired metrics
actual: List[float]
The actual metrics
margin: float
The allowed margin of error
Returns
-------
float
The fraction of values where |actual - desired| <= margin
"""
count = 0 # tally of how values are within margin
total = len(desired)
for i in range(total):
if abs(desired[i] - actual[i]) <= margin:
count += 1 # Equivalent to `count = count + 1`
return count / total if total > 0 else 1.0
```

See that we handle the edge case where `desired`

and `actual`

are empty lists: the inline if-else statement `count / total if total > 0 else 1`

will return `1`

when `total`

is 0:

```
>>> within_margin_percentage([], [], margin=0.5)
1.0
```

which is arguably the appropriate behavior for this scenario (no values fall outside of the margin). Had we not anticipated this edge case, `within_margin_percentage([], [], margin=0.5)`

would raise `ZeroDivisionError`

.

It is also possible to write this solution using the built-in `sum`

function and a generator comprehension that filters out those pairs of items that fall outside of the desired margin:

```
def within_margin_percentage(desired, actual, margin):
total = len(desired)
count = sum(1 for i in range(total) if abs(actual[i] - desired[i]) <= margin)
return count / total if total > 0 else 1.0
```

It is debatable whether this refactored solution is superior to the original one - it depends largely on how comfortable you, and anyone else who will be reading your code, are with the generator comprehension syntax.