
On 10/13/2013 02:02 PM, Tim Peters wrote:> [MRAB, posts a beautiful solution]
I don't really have a use for this, but it was a lovely programming puzzle, so I'll include an elaborate elaboration of MRAB's algorithm below. And that's the end of my interest in this;-)
A what the heck... :-) This is what I came up with which works like MRAB's by removing the first element and using recursion on the rest. (It's how you do it in lisp or scheme.) It's just two generators working together. You can get items with specified length by using a list comprehension or filter. (Disclaimer... I didn't do any more testing (performance or otherwise) than you see below.) Cheers, Ron Adam def combine_with_all(x, seq): """Combine item x to every item in seq.""" for s in seq: if (not (isinstance(s, list))): s = [s] yield s + [x] def unique_sets(seq): """Return all unique combinations of elements in seq.""" if len(seq) == 0: return [] first, rest = seq[0], seq[1:] yield [first] yield from unique_sets(rest) yield from combine_with_all(first, unique_sets(rest)) ### EXAMPLES ### for args in [('x', []), ('x', [1, 2]), ('x', [[1], [2]]), ('x', [[1, 2], 3]), ('x', [[1, 2], [3]]), ('x', ['abc']), ('x', ['ab', 'c'])]: print(list(combine_with_all(*args))) # [] # [[1, 'x'], [2, 'x']] # [[1, 'x'], [2, 'x']] # [[1, 2, 'x'], [3, 'x']] # [[1, 2, 'x'], [3, 'x']] # [['a', 'x'], ['b', 'x'], ['c', 'x']] # [['abc', 'x']] # [['ab', 'x'], ['c', 'x']] print(list(unique_sets('abc'))) # [['a'], ['b'], ['c'], ['c', 'b'], ['b', 'a'], ['c', 'a'], # ['c', 'b', 'a']] print(list(unique_sets(['abc']))) # [['abc']] print(list(unique_sets(['a', 'b', 'c']) )) # [['a'], ['b'], ['c'], ['c', 'b'], ['b', 'a'], ['c', 'a'], # ['c', 'b', 'a']] print(list (unique_sets( [(1,2), (3,4)] ))) # [[(1, 2)], [(3, 4)], [(3, 4), (1, 2)]] print(list (unique_sets( [[1,2], [3,4]] ))) # [[[1, 2]], [[3, 4]], [[3, 4], [1, 2]]] print([x for x in unique_sets(['a', 'b', 'c']) if len(x) == 2]) # [['c', 'a'], ['b', 'a'], ['c', 'b']] print([x for x in unique_sets(["a1", "b", "a2"]) if len(x) == 2]) # [['a2', 'b'], ['b', 'a1'], ['a2', 'a1']]