EDIT : customize the answer according to the clarified question
The main idea: again, the resulting selection can be encoded in the same way as the special numeral system. One could increase the counter and interpret this counter as a choice.
However, since there is an additional limit on the size of the allocation == target . A naive way to implement the constraint is to simply check the size of the resulting selection and skip those that do not satisfy the constraints. But it is slow.
So, all I did was make a slightly smarter increment that jumps the selection with the correct size directly.
Sorry, the code is in Python. But I did it the same way as the Java iterator interface. Input and output format:
haves[i] := multiplicity of the i-th item in the collection target := output collection must have this size
The code:
class Perm(object): def __init__(self,items,haves,target): assert sum(haves) >= target assert all(h > 0 for h in haves) self.items = items self.haves = haves self.target = target self.ans = None self.stop = False def __iter__(self): return self def reset(self): self.ans = [0]*len(self.haves) self.__fill(self.target) self.stop = False def __fill(self,n): """fill ans from LSB with n bits""" if n <= 0: return i = 0 while n > self.haves[i]: assert self.ans[i] == 0 self.ans[i] = self.haves[i] n -= self.haves[i] i += 1 assert self.ans[i] == 0 self.ans[i] = n def __inc(self): """increment from LSB, carry when 'target' or 'haves' constrain is broken"""
Note that the items argument is not used.
assert in __init__ is to exclude my suggestion about input.
assert in __fill should just show the convenient self.ans property in the context invoked by __fill .
Here is a good skeleton for code testing:
test_cases = [([3,2,1], 3), ([3,2,1], 5), ([3,2,1], 6), ([4,3,2,1,1], 4), ([1,3,1,2,4], 4), ] P = Perm(None,*test_cases[-1]) for p in P: print p
Result from input ([1,3,1,2,4], 4) :
[1, 3, 0, 0, 0] [1, 2, 1, 0, 0] [0, 3, 1, 0, 0] [1, 2, 0, 1, 0] [0, 3, 0, 1, 0] [1, 1, 1, 1, 0] [0, 2, 1, 1, 0] [1, 1, 0, 2, 0] [0, 2, 0, 2, 0] [1, 0, 1, 2, 0] [0, 1, 1, 2, 0] [1, 2, 0, 0, 1] [0, 3, 0, 0, 1] [1, 1, 1, 0, 1] [0, 2, 1, 0, 1] [1, 1, 0, 1, 1] [0, 2, 0, 1, 1] [1, 0, 1, 1, 1] [0, 1, 1, 1, 1] [1, 0, 0, 2, 1] [0, 1, 0, 2, 1] [0, 0, 1, 2, 1] [1, 1, 0, 0, 2] [0, 2, 0, 0, 2] [1, 0, 1, 0, 2] [0, 1, 1, 0, 2] [1, 0, 0, 1, 2] [0, 1, 0, 1, 2] [0, 0, 1, 1, 2] [0, 0, 0, 2, 2] [1, 0, 0, 0, 3] [0, 1, 0, 0, 3] [0, 0, 1, 0, 3] [0, 0, 0, 1, 3] [0, 0, 0, 0, 4]
Performance Each call to next() takes O(h) , where h is the number of element types ( haves list size).