Here is the problem I am working on:
Return the sum of the numbers in the array, except ignore sections of numbers starting with a 6 and extending to the next 7 (every 6 will be followed by at least one 7). Return 0 for no numbers.
sum67([1, 2, 2])
→ 5sum67([1, 2, 2, 6, 99, 99, 7])
→ 5sum67([1, 1, 6, 7, 2])
→ 4
Here is my solution:
def sum67(nums):
if len(nums) == 0:
return 0
elif 6 not in nums:
return sum(nums)
else:
for num in nums:
if num ==6:
ind_six = nums.index(6)
ind_seven = nums.index(7,ind_six)
del nums[ind_six:ind_seven 1]
else:
pass
return sum(nums)
My code works for all of the listed inputs, but fails "other tests." Please reference the picture. Could anyone help me figure out why? What am I missing? Thank you!! Expected vs run chart
I have tried brainstorming other possible inputs that are failing.
CodePudding user response:
This is a good example of over-reliance on Python's conveniences creating inefficiencies. Your usages of in
, .index()
, slices and sum()
can all walk the whole list, so they're O(n). The overall complexity is O(nn). Take a look at the time complexity of Python lists.
An easier approach is to walk the list and stop summing whenever you see a 6 up to the next 7:
def sum67(nums):
count = True
total = 0
for n in nums:
if n == 6:
count = False
if count:
total = n
if n == 7:
count = True
return total
One pass, O(n).
Armed with the above reference solution, I ran a fuzz test to see if there were any edge cases your solution misses:
import random
for _ in range(10000):
L = [random.randint(0, 20) for _ in range(random.randint(0, 20))]
if all(x != 6 or (7 in L[i:]) for i, x in enumerate(L)):
if sum67_ref(L[:]) != sum67(L[:]):
print(L)
A failing input is L = [6, 7, 6, 1, 7, 7]
. The correct answer is 7 but your code gives 21. The problem is, when you remove elements from a list while iterating over it, the iterator gets confused and skips elements. In this case, the [6, 7]
sublist is deleted, then the iterator skips the next 6 at index 2 and next emits the 1, which is counted, along with the 7 after it when both should be ignored.
Without a reference solution, it can be hard to think of a failing test case (it's good practice to try!), but you can follow a testing principle which says "most incorrect functions can be caused to fail on a small test case". This is true here--we only need a list of length 4 to trigger a failure: [6, 7, 6, 7]
. You can generate permutations of 6s and 7s in a small list and inspect them by hand against your code's output to validate it.