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']]