Hoist
Hoist

Reputation: 29

Python loop to calculate sum of elements in a list except 13

I am trying to write a function that iterates through a list to return the sum of the integer elements in the list. However if there is a 13 in the list, it needs to exclude the 13 and whatever comes right after it from the sum. So far I have come up with the following code. This works for almost all cases except when there are two 13's back to back. It only excludes the two 13's instead of the two 13's plus whatever is after the second 13. For example, when I call the function with print(sum13([13, 13, 2, 13, 1, 5, 6, 13])), instead of giving the output of 11 it gives 13. Any help is appreciated.

    def sum13(nums):

      while 13 in nums:
          index13 = nums.index(13)
          nums = nums[0:index13]+nums[index13+2:]
      return sum(nums)

Upvotes: 0

Views: 1962

Answers (5)

Amadan
Amadan

Reputation: 198436

You can do it functionally:

def sum13(nums):
    return sum(current
               for current, following
               in zip(nums, [None] + nums[:-1])
               if current != 13 and following != 13)

"Gimme a sum of all numbers that are not 13, and whose next number is not 13".

Upvotes: 1

BA.
BA.

Reputation: 934

Try the below. Note that this is using nexted function to remove 13s, or a series of 13s and the number right after

def refine(nums, index_i):
    while 13 in nums:
        print(nums)
        index = len(nums) - nums[::-1].index(13) - 1
        if index == index_i -1:
            nums = refine(nums[0:index] + nums[index+1:], index)
        else:
            nums = refine(nums[0:index] + nums[index+2:], index)
    return nums

    print( sum(refine([0, 13, 1, 2, 3, 4, 13, 13, 7, 13, 13, 5, 6, 13], 0)) )

This will sum only [0, 2, 3, 4, 6]

However, this is assuming you have a small list to manage With large list, you might want to think of the performance of such manipulation

Upvotes: 0

Philip B.
Philip B.

Reputation: 637

Because generators need love too:

l = [13, 13, 2, 13, 1, 5, 6, 13]

def sanitize(list):
    il = iter(list)
    for e in il:
        while e == 13:
            e = next(il)
            if e != 13:
                e = next(il)
        yield e

print(sum(sanitize(l)))

The idea being that you clean up your list first and then sum it up.

Upvotes: 0

Zach Gates
Zach Gates

Reputation: 4155

You could use a slice to determine whether a 13 precedes a number:

def sum13(nums):
    sum_ = 0
    for index, elem in enumerate(nums):
        if 13 not in nums[max(index-1, 0):index+1]:
            sum_ += elem
    return sum_

The max is needed only for the first element, being that i-1 would be 0-1, so the slice would be [-1:1], which is empty. You can even cut it down to one line, if you really wanted to:

sum(e for i, e in enumerate(nums) if 13 not in nums[max(i-1, 0):i+1])

Upvotes: 0

Akavall
Akavall

Reputation: 86276

The idiomatic way of doing something like this is to keep track of the previous variable, for example:

def sum13(nums):
    prev = None
    my_sum = 0 
    for ele in nums:
        if ele != 13 and prev != 13: 
            my_sum += ele 
        prev = ele 
    return my_sum

if __name__ == "__main__":

    print(sum13([1,2,13,3,4]))
    print(sum13([13, 13, 2, 13, 1, 5, 6, 13]))

Result:

7
11

Upvotes: 1

Related Questions