''int' object is not subscriptable?

I'm doing an algorithm challenge on www.edabit.com, where you have a list of dice rolls, and:

  • if the number is 6, the next number on the list is amplified by a factor of 2

  • if the number is 1, the next number on the list is 0

this is my code:

def rolls(lst):
out = 0
iterate = 0
if lst[iterate] == 1:
    out+=lst[iterate]
    lst[iterate+1] = 0
    iterate+=1
    rolls(lst[iterate])
elif lst[iterate] == 6:
    out+=lst[iterate]
    lst[iterate+1] = lst[iterate+1]*2
    iterate+=1
    rolls(lst[iterate])
else:
    out+=lst[iterate]
    iterate+=1

The console gives me "TypeError: 'int' object is not subscriptable"

Any ideas? Also any other errors you spot would be useful.

I tried on other IDE's, but it gives the same output.

for a series like "1, 6, 2, 3, 2, 4, 5, 6, 2" I expect 27



Solution 1:[1]

As stated in the comments, for this kind of problem I wouldn't use recursion. A loop will be enough:

l = [1, 6, 2, 3, 2, 4, 5, 6, 2]

from itertools import accumulate

print(sum(accumulate([0] + l, lambda a, b: b*{1:0, 6:2}.get(a, 1))))

Prints:

27

Solution 2:[2]

If you have to use recursion for this problem, then you will need to pass two arguments first lst and second iterate. Note that lst[iterate] is a single element which you are passing to the function when calling it recursively.

Thus modify the function to take two arguments lst and iterate. And initially pass arguments as full list for lst and a 0 for iterate. rolls(lst, 0) should be your initial function call.

I suppose you want out variable to contain sum of all entries in lst when you visit them, so that also needs to be passed as an argument, making your initial call rolls(lst, 0, 0). I have edited the function to return the sum calculated in out accordingly.

def rolls(lst, iterate, out):
    if iterate == len(lst):
        return out
    if lst[iterate] == 1:
        out += lst[iterate]
        if iterate + 1 < len(lst): #In order to avoid index out of bounds exception
            lst[iterate + 1] = 0
        rolls(lst, iterate + 1, out)
    elif lst[iterate] == 6:
        out += lst[iterate]
        if iterate + 1 < len(lst): #In order to avoid index out of bounds exception
            lst[iterate + 1] = lst[iterate + 1] * 2
        rolls(lst, iterate + 1, out)
    else:
        out += lst[iterate]
        rolls(lst, iterate+1, out)

Solution 3:[3]

Instead of looking to the next item, you can look at the previous item:

from itertools import islice

def rolls(lst):
    if not lst:
        return 0
    total = prev = lst[0]
    for x in islice(lst, 1, None):
        if prev == 1:
            x = 0
        elif prev == 6:
            x *= 2
        prev = x
        total += x
    return total

For example:

>>> rolls([1, 6, 2, 3, 2, 4, 5, 6, 2])
27
>>> rolls([])
0
>>> rolls([1])
1
>>> rolls([2])
2
>>> rolls([3])
3
>>> rolls([4])
4
>>> rolls([6,1])
8
>>> rolls([6,2])
10
>>> rolls([6,1,5])
13

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Andrej Kesely
Solution 2 Prajyot Naik
Solution 3