Place n indistinguishable items into k distinguishable boxes
Arnaud Delobelle
arnodel at googlemail.com
Thu Feb 28 11:44:43 EST 2008
On Feb 28, 2:40 am, Michael Robertson <mcrobert... at hotmail.com> wrote:
> Hi,
>
> I need a generator which produces all ways to place n indistinguishable
> items into k distinguishable boxes.
>
> For n=4, k=3, there are (4+3-1)!/(3-1)!/4! = 15 ways.
>
> (0,0,4)
[...]
Here is my little function:
---------------
from itertools import chain
from operator import sub
def boxings(n, k):
"""boxings(n, k) -> iterator
Generate all ways to place n indistiguishable items into k
distinguishable boxes
"""
seq = [n] * (k-1)
while True:
yield map(sub, chain(seq, [n]), chain([0], seq))
for i, x in enumerate(seq):
if x:
seq[:i+1] = [x-1] * (i+1)
break
else:
return
---------------
It is purely iterative. I think it is not too wasteful but I haven't
tried to optimise it in any way.
In the function, 'seq' iterates over all increasing sequences of
length k-1 over {0,1,..n}.
Example:
>>> for b in boxings(4, 3): print b
...
[4, 0, 0]
[3, 1, 0]
[2, 2, 0]
[1, 3, 0]
[0, 4, 0]
[3, 0, 1]
[2, 1, 1]
[1, 2, 1]
[0, 3, 1]
[2, 0, 2]
[1, 1, 2]
[0, 2, 2]
[1, 0, 3]
[0, 1, 3]
[0, 0, 4]
... here is another attempt on the same principle:
---------------
def boxings(n, k):
"""boxings(n, k) -> iterator
Generate all ways to place n indistiguishable items into k
distinguishable boxes
"""
seq = [n]*k + [0]
while True:
yield tuple(seq[i] - seq[i+1] for i in xrange(k))
i = seq.index(0) - 1
if i >= 1:
seq[i:k] = [seq[i] - 1] * (k - i)
else:
return
--
Arnaud
More information about the Python-list
mailing list