I\'m new to programming and I\'m trying to do the codingbat.com problems to start. I came across this problem:
Given an array calculate the sum except when there is
I think this is the most compact solution:
def triskaidekaphobicSum(sequence):
return sum(sequence[i] for i in range(len(sequence))
if sequence[i] != 13 and (i == 0 or sequence[i-1] != 13))
This uses the builtin sum() function on a generator expression. The generator produces all the elements in the sequence as long as they are not 13, or immediately following a 13. The extra "or" condition is to handle the first item in the sequence (which has no previous item).
One tricky thing to notice is something like this: [1, 13, 13, 2, 3]
You need to skip 2
too
def getSum(l):
sum = 0
skip = False
for i in l:
if i == 13:
skip = True
continue
if skip:
skip = False
continue
sum += i
return sum
Explanation:
You go through the items in the list one by one
Each time you
skip
as True
, so that you can also skip next item.skip
is True
, if it is, which means it's a item right after 13, so you need to skip this one too, and you also need to set skip
back to False
so that you don't skip next item.sum
Use a while loop to walk through the list, incrementing i
manually. On each iteration, if you encounter a 13, increment i
twice; otherwise, add the value to a running sum and increment i
once.
def skip13s(l):
i = 0
s = 0
while (i < len(l)):
if l[i] == 13:
i += 1
else:
s += l[i]
i += 1
return s
Some FP-style :)
def add_but_skip_13_and_next(acc, x):
prev, sum_ = acc
if prev != 13 and x != 13:
sum_ += x
return x, sum_
filter_and_sum = lambda l: reduce(add_but_skip_13_and_next, l, (0,0))[1]
>>> print filter_and_sum([13,13,1,4])
4
>>> print filter_and_sum([1,2,13,5,13,13,-9,13,13,13,13,13,1,1])
4
This code works for any iterator, even it not provide the random access (direct indexing) - socket for example :)
Oneliner :)
>>> filter_and_sum = lambda l: reduce(
... lambda acc, x: (x, acc[1] + (x if x != 13 and acc[0] != 13 else 0)),
... l, (0,0))[1]
>>> print filter_and_sum([1,2,13,5,13,13,-9,13,13,13,13,13,1,1])
4
You can use the zip function to loop the values in pairs:
def special_sum(numbers):
s = 0
for (prev, current) in zip([None] + numbers[:-1], numbers):
if prev != 13 and current != 13:
s += current
return s
or you can do a oneliner:
def special_sum(numbers):
return sum(current for (prev, current) in zip([None] + numbers[:-1], numbers)
if prev != 13 and current != 13)
You can also use iterators:
from itertools import izip, chain
def special_sum(numbers):
return sum(current for (prev, current) in izip(chain([None], numbers), numbers)
if prev != 13 and current != 13)
(the first list in the izip is longer than the second, zip and izip ignore the extra values).
def skipAndAddFun(inputVal, skipList):
sum = 0
for i in inputVal:
if not i in skipList:
sum += i
return sum
Usage:
skipAndAddFun([1,2,13,5,1], [13, 5])
4
This simple function will be a generic solution for your question.