Although I have a method for generating the arrangement of n distinct/distinguishable items (from set s) into x boxes (which are not distinguishable), I am wondering if anyone has ideas of something more efficient...or is having to check what is generated just par for the course when doing this sort of combinatorics? e.g. 5 items into 3 boxes:
from sympy.utilities.iterables import cartes, partitions, subsets
from functools import reduce
s = [1,2,3,4,5]
x = 3
for c, p in partitions(len(s), x, size=True): # generates {2:2, 1:1}, {3:1, 1:2}
if c != x: continue
args = []
for k,v in p.items():
for vi in range(v):
args.append(subsets(s,k))
for X in cartes(*args):
for i in range(1,len(X)):
if len(X[i]) == len(X[i-1]) and X[i] < X[i-1]: break
else:
if len(set(reduce(lambda x,y:x+y, X))) == len(s):
print(X)
which generates:
((1,), (2,), (3, 4, 5))
((1,), (3,), (2, 4, 5))
((1,), (4,), (2, 3, 5))
((1,), (5,), (2, 3, 4))
((2,), (3,), (1, 4, 5))
((2,), (4,), (1, 3, 5))
((2,), (5,), (1, 3, 4))
((3,), (4,), (1, 2, 5))
((3,), (5,), (1, 2, 4))
((4,), (5,), (1, 2, 3))
((1,), (2, 3), (4, 5))
((1,), (2, 4), (3, 5))
((1,), (2, 5), (3, 4))
((2,), (1, 3), (4, 5))
((2,), (1, 4), (3, 5))
((2,), (1, 5), (3, 4))
((3,), (1, 2), (4, 5))
((3,), (1, 4), (2, 5))
((3,), (1, 5), (2, 4))
((4,), (1, 2), (3, 5))
((4,), (1, 3), (2, 5))
((4,), (1, 5), (2, 3))
((5,), (1, 2), (3, 4))
((5,), (1, 3), (2, 4))
((5,), (1, 4), (2, 3))
To see a simpler results, consider 4 items being put into 2 boxes:
a, bcd
b, acd
c, abd
d, abc
ab, cd
ac, bd
ad, bc