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.