I am very new to Python and have been going through multiple tutorials to get better.
I have straggled with one difficult problem and found a solution. But it feels, works very newbie like. I think that I have tailored it to answer the specific question.
So the question is:
SUMMER OF ’69: Return the sum of the numbers in the array, except ignore sections of numbers starting with a 6 and extending to the next 9 (every 6 will be followed by at least one 9). Return 0 for no numbers.
summer_69([1, 3, 5]) --> 9
summer_69([4, 5, 6, 7, 8, 9]) --> 9
summer_69([2, 1, 6, 9, 11]) --> 14
My code to solve this is:
def summer_69(arr):
list1 = arr
summ = int()
for i in range(0, len(arr)):
if 6 in list1:
listOfRange = range(list1.index(6), list1.index(9) + 1)
for index in listOfRange:
print(listOfRange)
arr[index] = 0
if 6 != arr[i]:
summ += arr[i]
else:
continue
else:
summ += arr[i]
return summ
It is a very basic problem and I am very alerted that I have struggled with something like this already.
Advertisement
Answer
Short O(n) solution using an iterator and the in
operator to search for (and thereby skip to) the 9 following each 6:
def summer_69(lst):
it = iter(lst)
return sum(x for x in it
if x != 6 or 9 not in it)
Less dense version:
def summer_69(lst):
it = iter(lst)
total = 0
for x in it:
if x == 6:
9 in it
else:
total += x
return total
Correctness check (random test cases) and benchmark (with [1] * 5000 + [6, 9] * 2500
) along with the accepted answer’s solution (which takes O(n2)):
30 out of 30 tests correct
303045 us 303714 us 304335 us 306007 us 309986 us summer_69_Accepted
444 us 446 us 464 us 478 us 527 us summer_69_Kelly1
442 us 448 us 453 us 465 us 500 us summer_69_Kelly2
Code (Try it online!):
from timeit import repeat
def summer_69_Accepted(lst):
copyoflist = lst[:] # makes shallow copy of list
while True:
if 6 not in copyoflist:
return sum(copyoflist)
indexof6 = copyoflist.index(6)
indexof9 = copyoflist.index(9, indexof6+1) # begin search for 9 after 6
del copyoflist[indexof6:indexof9+1]
def summer_69_Kelly1(lst):
it = iter(lst)
return sum(x for x in it
if x != 6 or 9 not in it)
def summer_69_Kelly2(lst):
it = iter(lst)
total = 0
for x in it:
if x == 6:
9 in it
else:
total += x
return total
funcs = summer_69_Accepted, summer_69_Kelly1, summer_69_Kelly2
from random import randrange, choices
def testcase():
def others():
return choices([0, 1, 2, 3, 4, 5, 7, 8], k=randrange(10))
lst = others()
for _ in range(10):
lst += [6, *others(), 9, *others()]
return lst
tests = correct = 0
for _ in range(10):
lst = testcase()
expect = funcs[0](lst.copy())
for func in funcs:
result = func(lst.copy())
correct += result == expect
tests += 1
print(correct, 'out of', tests, 'tests correct')
print()
lst = [1] * 5000 + [6, 9] * 2500
for func in funcs:
times = repeat(lambda: func(lst), number=1)
print(*('%6d us ' % (t * 1e6) for t in sorted(times)), func.__name__)