List the combinations of elements in a set

Haskell - 57 46 bytes

Bring it on, golfscripters.

0%_=[[]]
n%(x:y)=map(x:)((n-1)%y)++n%y
_%_=[]

Use case (same function works polymorphicaly):

2%[1,2,3,4] ➔ [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]

3%"cheat" ➔ ["che","cha","cht","cea","cet","cat","hea","het","hat","eat"]

2%["Charlie", "Alice", "Daniel", "Bob"] ➔ [["Charlie","Alice"],["Charlie","Daniel"],["Charlie","Bob"],["Alice","Daniel"],["Alice","Bob"],["Daniel","Bob"]]


Python (72)

f=lambda S,k:S and[T+S[:1]for T in f(S[1:],k-1)]+f(S[1:],k)or[[]]*(k==0)

The function f takes a list S and number k and returns a list of all sublists of length k of S. Rather than listing all subsets and then filtering by size, I only get the subsets of the needed size at each step.

I'd like to get S.pop() to work in order to combine getting S[:1] with passing S[1:] later, but it seems to consume the list too much.

To preempt the objection any such Python solution breaks the rule that "The code should work in any number of input variables" because of recursion limits, I'll note that the Stackless Python implementation has no recursion limits (though I haven't actually tested this code with it).

Demonstration:

S = [1, 2, 6, 8]
for i in range(-1,6):print(i, f(S,i))

#Output:    
-1 []
0 [[]]
1 [[1], [2], [6], [8]]
2 [[2, 1], [6, 1], [8, 1], [6, 2], [8, 2], [8, 6]]
3 [[6, 2, 1], [8, 2, 1], [8, 6, 1], [8, 6, 2]]
4 [[8, 6, 2, 1]]
5 []

Mathematica 10, 70 chars

Just a translation of the Haskell answer.

_~f~_={};_~f~0={{}};{x_,y___}~f~n_:=Join[Append@x/@f[{y},n-1],{y}~f~n]

Usage:

In[1]:= f[{1, 7, 4}, 2]

Out[1]= {{7, 1}, {4, 1}, {4, 7}}

Tags:

Code Golf