Python Forum

Full Version: Sum of elements on the list recursive
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,
my homework is to create a program which sums elements of the list (from current index to the last) and inserts its result to the appropriate cell on the new list.
I have to do it in both ways, 1 - iteration, 2 - recursive.
Now the iteration version works flawlessly, but recursive takes the cut of already cut list. How to prevent it to make the recursive function the cut of original list in every step?

A=[1,0,2,0,0,3,1,3,2,1]

def iter_45(lista):
    nowa_lista_i = []
    for i in range (0, len(lista)):
        suma_elementow = 0
        for i in range(i, len(lista)):
            suma_elementow += lista[i]
        
        nowa_lista_i.append(suma_elementow)
    return nowa_lista_i


i = 0
dlugosc = len(A)
nowa_lista = []

def req_45(lista):
    global i
    if i == (dlugosc):
        return nowa_lista
    else:

        nowa_lista.append(sum(lista[i:]))
        i += 1              
        return req_45(lista[i:])


print('iteracyjnie:\n')
print(iter_45(A))
print('\nrekurencyjnie:\n')
print(req_45(A))
Hi,

Quote:which sums elements of the list (from current index to the last)
Your current code doesn't reflect that, as you always start at the 1st element?

Quote: and inserts its result to the appropriate cell on the new list.
What does that means exactly? Does mean if your input list is [1, 2, 3, 4], the result list is supposed to be [3, 6, 10]?

Except this, iteration by for i in range(len(iterable)) combined with accessing elements of iterable by index is an bad anti-pattern in Python. Python supports direct iteration of iterables.

And your variable names are pretty weird... why do you have at nearly all variables the letter a post-fixed?

Regards, noisefloor
I deduct that if your 'iteration version works flawlessly' then objective is:

[1,0,2,0,0,3,1,3,2,1] --> [13, 12, 12, 10, 10, 10, 7, 6, 3, 1]

I think that your solution is too complicated.

Lists support sum(), so:

>>> sum([1, 2])
3
Lists also support slicing:

>>> a = [1, 2, 3, 4, 5]
>>> a[1:]
[2, 3, 4, 5]
>>> sum(a[1:])
14
Combining those two things into list comprehension and taking into account noisefloor comment about Python antipattern you can write simply:

>>> a = [1,0,2,0,0,3,1,3,2,1] 
>>> [sum(a[i:]) for i, v in enumerate(a)]
[13, 12, 12, 10, 10, 10, 7, 6, 3, 1]
Iterative solution should give you pretty good idea how to proceed with recursive solution.

EDIT: how Python core developers do it

There is built-in module itertools which have function accumulate (Make an iterator that returns accumulated sums).

There is rough equivalent provided:

def accumulate(iterable, func=operator.add):
    'Return running totals'
    # accumulate([1,2,3,4,5]) --> 1 3 6 10 15
    # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
    it = iter(iterable)
    try:
        total = next(it)
    except StopIteration:
        return
    yield total
    for element in it:
        total = func(total, element)
        yield total
Thank you guys for the advices, I have now completed my task, by adding another argument to the recursive function, and now I send full list instead of a slice to the function. I have also simplified the iteration version of the function.

noisefloor,
I wanted to achieve what was made by iter_45 function, like you mentioned, but opposite way:
Input: [1, 2, 3, 4], output [10, 6, 3].
The supplement at the end of my variable names is just my ID required by the teacher, it doesn't mean anything :)

I know it could be simplier and/or better, but now it looks like this:
A=[1,0,2,0,0,3,1,3,2,1]

def iter_45(lista):
    nowa_lista_i = []
    for i in range (0, len(lista)):
        nowa_lista_i.append(sum(lista[i:]))
    return nowa_lista_i


nowa_lista = []
i = 0

def req_45(lista, i):
    global nowa_lista
    
    if i == len(lista):
        return nowa_lista

    else:
        nowa_lista = nowa_lista + [sum(lista[i:])]
        i += 1
        return req_45(lista, i)


print('iteracyjnie:\n')
print(iter_45(A))
print('\nrekurencyjnie:\n')
print(req_45(A,0))
Thanks again for help :)