user2101517
user2101517

Reputation: 720

trouble appending lists to another list

I have this code which takes a list of numbers and groups together all those that add up to 21. My problem is that in the end I want the numbers to all be lists in a list, but I am having trouble achieving that. Any advise would be appreciated

def twentyone(seq, groups = []):
goal = 21
s = sum(groups)
final = []
if s == goal:
    final.append(groups)
    print (final)
if s >= goal:
    return

for i in range(len(seq)):
    n = seq[i]       
    remaining = seq[i+1:]
    twentyone(remaining, groups + [n])


#
seq = [1, 5, 6, 7, 10, 2, 11]
(twentyone(seq))

current output is:

[[1, 5, 6, 7, 2]]
[[1, 7, 2, 11]]
[[5, 6, 10]]
[[10, 11]]

I want the output to be:

[[1, 5, 6, 7, 2], [1, 7, 2, 11], [5, 6, 10], [10, 11]]

Upvotes: 1

Views: 60

Answers (2)

Tanveer Alam
Tanveer Alam

Reputation: 5275

You are creating new final list each time when it recursively calls itself. You just have to pass it as a default argument.

def twentyone(seq, groups = [], final = []): #default final list
    goal = 21
    s = sum(groups)

    if s == goal:
        final.append(groups)

    if s >= goal:
        return

    for i in range(len(seq)):
        n = seq[i]       
        remaining = seq[i+1:]
        twentyone(remaining, groups + [n])

    return final


seq = [1, 5, 6, 7, 10, 2, 11]
print twentyone(seq)

Results:-

[[1, 5, 6, 7, 2], [1, 7, 2, 11], [5, 6, 10], [10, 11]]

But the above solution will cause the final list grow each time twentyone function will be called. So we can create a new final list only for the first time it is called using first_call flag as follows:

def twentyone(seq, groups = None, final = None, first_call=True): 

    if not groups:
        groups = []

    if first_call:
        final = []

    goal = 21
    s = sum(groups)

    if s == goal:
        final.append(groups)

    if s >= goal:
        return

    for i in range(len(seq)):
        n = seq[i]       
        remaining = seq[i+1:]
        twentyone(remaining, groups + [n], final, False)

    return final


seq = [1, 5, 6, 7, 10, 2, 11]
print twentyone(seq)
print twentyone(seq)

Yields:

[[1, 5, 6, 7, 2], [1, 7, 2, 11], [5, 6, 10], [10, 11]]
[[1, 5, 6, 7, 2], [1, 7, 2, 11], [5, 6, 10], [10, 11]]

Upvotes: 2

Shayan C
Shayan C

Reputation: 1580

extending on Tanveers answer (which is the best approach in my opinion), you could also move the final variable outside or even use a static variable. The main problem in your code is that you are creating new final variable in each recursive call. These code below fixes that.

Local variable approach:

final = []

def twentyone(seq, groups = []):
    goal = 21
    s = sum(groups)
    if s == goal:
        final.append(groups)
    if s >= goal:
        return

    for i in range(len(seq)):
        n = seq[i]       
        remaining = seq[i+1:]
        twentyone(remaining, groups + [n])
seq = [1, 5, 6, 7, 10, 2, 11]
twentyone(seq)
print (final)

Static variable approach:

class myfinal:
    final=[]
def twentyone(seq, groups = []):
    goal = 21
    s = sum(groups)
    if s == goal:
        myfinal.final.append(groups)
    if s >= goal:
        return

    for i in range(len(seq)):
        n = seq[i]       
        remaining = seq[i+1:]
        twentyone(remaining, groups + [n])


seq = [1, 5, 6, 7, 10, 2, 11]
twentyone(seq)
print (myfinal.final)

Upvotes: 0

Related Questions