Yield all unions of start with other in shortlex order.

    >>> ['{:03b}'.format(s) for s in shortlex(0, [0b100, 0b010, 0b001])]
    ['000', '100', '010', '001', '110', '101', '011', '111']

    >>> ', '.join(''.join(sorted(s))
    ... for s in shortlex(set(), [{'a'}, {'b'}, {'c'}, {'d'}]))
    ', a, b, c, d, ab, ac, ad, bc, bd, cd, abc, abd, acd, bcd, abcd'

    >>> assert list(shortlex(set(), [{1}, {2}], excludestart=True)) == \
        [{1}, {2}, {1, 2}]

def shortlex(start, other, excludestart=False):
    """Yield all unions of start with other in shortlex order.

    >>> ['{:03b}'.format(s) for s in shortlex(0, [0b100, 0b010, 0b001])]
    ['000', '100', '010', '001', '110', '101', '011', '111']

    >>> ', '.join(''.join(sorted(s))
    ... for s in shortlex(set(), [{'a'}, {'b'}, {'c'}, {'d'}]))
    ', a, b, c, d, ab, ac, ad, bc, bd, cd, abc, abd, acd, bcd, abcd'

    >>> assert list(shortlex(set(), [{1}, {2}], excludestart=True)) == \
        [{1}, {2}, {1, 2}]
    """
    if not excludestart:
        yield start

    queue = collections.deque([(start, other)])

    while queue:
        current, other = queue.popleft()

        while other:
            first, other = other[0], other[1:]
            result = current | first

            yield result

            if other:
                queue.append((result, other))