(seq, k=None, repetition=False)
Generates all k-subsets (combinations) from an n-element set, seq.

       A k-subset of an n-element set is any subset of length exactly k. The
       number of k-subsets of an n-element set is given by binomial(n, k),
       whereas there are 2**n subsets all together. If k is None then all
       2**n subsets will be returned from shortest to longest.

       Examples
       ========

       >>> from sympy.utilities.iterables import subsets

       subsets(seq, k) will return the n!/k!/(n - k)! k-subsets (combinations)
       without repetition, i.e. once an item has been removed, it can no
       longer be "taken":

           >>> list(subsets([1, 2], 2))
           [(1, 2)]
           >>> list(subsets([1, 2]))
           [(), (1,), (2,), (1, 2)]
           >>> list(subsets([1, 2, 3], 2))
           [(1, 2), (1, 3), (2, 3)]


       subsets(seq, k, repetition=True) will return the (n - 1 + k)!/k!/(n - 1)!
       combinations *with* repetition:

           >>> list(subsets([1, 2], 2, repetition=True))
           [(1, 1), (1, 2), (2, 2)]

       If you ask for more items than are in the set you get the empty set unless
       you allow repetitions:

           >>> list(subsets([0, 1], 3, repetition=False))
           []
           >>> list(subsets([0, 1], 3, repetition=True))
           [(0, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1)]
Generates all k-subsets (combinations) from an n-element set, seq.
Generates all k - subsets ( combinations ) from an n - element set seq .
def subsets(seq, k=None, repetition=False):
    """Generates all k-subsets (combinations) from an n-element set, seq.

       A k-subset of an n-element set is any subset of length exactly k. The
       number of k-subsets of an n-element set is given by binomial(n, k),
       whereas there are 2**n subsets all together. If k is None then all
       2**n subsets will be returned from shortest to longest.

       Examples
       ========

       >>> from sympy.utilities.iterables import subsets

       subsets(seq, k) will return the n!/k!/(n - k)! k-subsets (combinations)
       without repetition, i.e. once an item has been removed, it can no
       longer be "taken":

           >>> list(subsets([1, 2], 2))
           [(1, 2)]
           >>> list(subsets([1, 2]))
           [(), (1,), (2,), (1, 2)]
           >>> list(subsets([1, 2, 3], 2))
           [(1, 2), (1, 3), (2, 3)]


       subsets(seq, k, repetition=True) will return the (n - 1 + k)!/k!/(n - 1)!
       combinations *with* repetition:

           >>> list(subsets([1, 2], 2, repetition=True))
           [(1, 1), (1, 2), (2, 2)]

       If you ask for more items than are in the set you get the empty set unless
       you allow repetitions:

           >>> list(subsets([0, 1], 3, repetition=False))
           []
           >>> list(subsets([0, 1], 3, repetition=True))
           [(0, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1)]

       """
    if k is None:
        for k in range(len(seq) + 1):
            for i in subsets(seq, k, repetition):
                yield i
    else:
        if not repetition:
            for i in combinations(seq, k):
                yield i
        else:
            for i in combinations_with_replacement(seq, k):
                yield i
def subsets ( seq , k = None , repetition = False ) : if k is None : for k in range ( len ( seq ) + 1 ) : for i in subsets ( seq , k , repetition ) : yield i else : if not repetition : for i in combinations ( seq , k ) : yield i else : for i in combinations_with_replacement ( seq , k ) : yield i