Terence Chow
Terence Chow

Reputation: 11173

Skipping elements in a List Python

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 a 13 in the array. If there is a 13 in the array, skip the 13 and the number immediately following it. For example [1,2,13,5,1] should yield 4 (since the 13 and the 5s are skipped).

This is what I have so far. My problem is that I don't know what to do when there are multiple 13s...And I would like to learn coding efficiently. Can you guys help? (I'm using python 3.2) Thanks!

def pos(nums):
    for i in nums:
        if i == 13:
            return nums.index(13)
    return False

def sum13(lis):
    if pos(lis)!= False:
        return sum(lis[:pos(lis)])+sum(lis[pos(lis)+1:])
    else:
        return sum(lis)

Upvotes: 12

Views: 93388

Answers (7)

Manish Waran
Manish Waran

Reputation: 92

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.

Upvotes: 0

Oren
Oren

Reputation: 2807

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).

Upvotes: 6

Aleksei astynax Pirogov
Aleksei astynax Pirogov

Reputation: 2491

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

Upvotes: 2

Blckknght
Blckknght

Reputation: 104852

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).

Upvotes: 1

plucury
plucury

Reputation: 1120

You can use while loop to treat multiple 13.

def sum13(lis):
    while pos(lis):
        if pos(lis) == len(lis) - 1:
            lis = lis[:pos(lis)]
        else:
            lis = lis[:pos(lis)]+lis[pos(lis)+1:]

    return sum(lis)

Upvotes: 0

xvatar
xvatar

Reputation: 3259

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

  • First check if it's 13, if it is, then you mark skip as True, so that you can also skip next item.
  • Second, you check if 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.
  • Finally, if it's not either case above, you add the value up to sum

Upvotes: 11

cheeken
cheeken

Reputation: 34685

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

Upvotes: 3

Related Questions