# 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
"""
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.