2

I need to write a recursive function that calculates all the possible combinations of length "n" in a list, in Python, without importing anything like itertools etc.

So what I have so far is:

if n == 0:
    return [[]]
elif lst == []:
    return []
else:
    rest = subsets(lst[1:], n-1)
    for next in lst:  # Loop through something?
        return lst[0] + rest #Add something?

I seem to be lacking an understanding of how the recursive calls work, can someone explain this to me?

6
  • 1
    Can you fix up your indenting for us? Click the "edit" button beneath your post. Commented Jul 9, 2014 at 0:36
  • Sorry about that it should be more clear now Commented Jul 9, 2014 at 0:49
  • 1
    Is your function called subsets? If so, can you include the function heading in it? Commented Jul 9, 2014 at 0:53
  • A question that I have asked myself a whole bunch of times. Perhaps start be getting all the combinations of 'n' numbers below the length of the list (including zero) and then getting the elements by index. Commented Jul 9, 2014 at 0:57
  • Also: it is important to know if the order of the combinations matter, if you just want unique outputs. Are both [a, b] and [b, a] counted? Or just [a, b]? And say the list is [a, b, c] and you want 2-len subsets. Is [a, a] a valid output? Commented Jul 9, 2014 at 0:58

3 Answers 3

1

In the absence of the required output specifications, we could write some pseudo-code like this:

def combinations(sub, data_set, items_needed):
    if you dont need, return sub
    for item in data_set:
        append item to sub
        #pop() item from data_set?
        decrease items_needed # added one more, so we need one less
        combinations(new_sub, data_set, items_needed)

Where poping() or not will depend on you wanting (or not) unique items in the subset.

If you say you don't want both [a, b] and [b, a] you would have to also keep track of the index of the last item added, in order to only add new items to create new combinations.

def combinations(sub, data_set, index, still_needed):
    if you dont need any, return
    for i in range(index, len(data_set)):
        append data_set[i] to sub
        decrease still_needed
        combinations(sub, data_set, index+1, still_needed)
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, sorry for not providing the specifications I just needed an explanation of how the algorithm would work, this cleared it up!
@BurhanKhalid changed variable name to data_set. thanks for the heads-up
0

This sounds dangerously like a homework problem. Why does it have to be recursive, as that just seems bad.

Regardless, recursively what you are doing is going through every element in the list and then appending that to the beginning of every other combination of length n - 1. So, if your list was [1, 2, 3], you are wanting an algorithm where the call stack will look like:

foo([], [1, 2, 3], n) ==
  foo([1], [2, 3], n - 1) +
  foo([2], [1, 3], n - 1) +
  foo([3], [1, 2], n - 1)

Where,

foo([1], [2, 3], n - 1) ==
  foo([1, 2], [3], n - 2) +
  foo([1, 3], [2], n - 2)

etc...

You can terminate the recursive calls whenever you have n == 0, or the middle list is empty. And you just return the first argument.

This all make sense? (I can code it up, if desired. I think if you look at the desired callstacks, it should mostly put itself together.)

4 Comments

You probably don't need the n because that can be calculated from the length of one of the lists.
Just bear in mind that since the foo() function is being called recursively, you do the inner call always with n - 1
@ssm it is probably better to have a variable holding that value than calling len(subset) endless times.
Yeah, writing it as n - 2 is rather misleading. Would it look better as (n - 1) - 1?
-1

A useful trick when faced with such a basic question (one that is frequently used as introductory level homework or in some programming interviews) is to look at RosetteCode (From which you, too, can learn to impress your friends with words like "chrestomathy"). For this one, in particular we find:

#/usr/bin/env python
# From: http://rosettacode.org/wiki/Combinations#Python
def comb(m, lst):
if m == 0:
    return [[]]
else:
    return [[x] + suffix for i, x in enumerate(lst)
            for suffix in comb(m - 1, lst[i + 1:])]

... along with implementations in dozens of other languages for comparison.

Another handy site is PLEAC (for the "Programming Language Examples Alike Cookbook" project) ... though it has less academic and leans towards more practical programming tasks.

1 Comment

-1 It is a basic question because he is learning, and getting the answer immediately does not help him with his true objective

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.