My goal is to take a one-dimensional list l as an argument and return all its partitions as a list. The function returns a three-dimensional Python list, where the lists contained in the second-level lists contain a total of the same elements as the entered list l without repetitions, and separately they contain all combinations of combinations like this.
Where I go wrong seems to be in the part where I'm required to sort the partitions.
This is my code:
from itertools import combinations
def makecomb(l):
def partition(collection):
if len(collection) == 1:
yield [collection]
return
first = collection[0]
for smaller in partition(collection[1:]):
for n, subset in enumerate(smaller):
yield smaller[:n] + [[first] + subset] + smaller[n + 1:]
yield [[first]] + smaller
result = list(partition(l))
unique_result = [list(map(list, set(map(tuple, part)))) for part in result]
def custom_sort(item):
return (len(item), tuple(sorted(item[0], key=lambda x: l.index(x))))
sorted_result = sorted(unique_result, key=custom_sort)
return sorted_result
This is what is expected as an output when calling makecomb([1,2,3])
:
[[[1], [2], [3]], [[1], [2, 3]], [[2], [1, 3]], [[3], [1, 2]], [[1, 2, 3]]]
Instead I get this:
[[[1, 2, 3]], [[1, 2], [3]], [[2], [1, 3]], [[2, 3], [1]], [[1], [2], [3]]]
I have now tried different approached, but nothing produces the correct output. At best I've managed to get:
[[[1], [2], [3]], [[1, 2], [3]], [[2], [1, 3]], [[2, 3], [1]], [[1, 2, 3]]]
I think you can get what you want with a double sort.
from itertools import combinations
def makecomb(l):
def partition(collection):
if len(collection) == 1:
yield [collection]
return
first = collection[0]
for smaller in partition(collection[1:]):
for n, subset in enumerate(smaller):
yield smaller[:n] + [[first] + subset] + smaller[n + 1:]
yield [[first]] + smaller
result = list(partition(l))
unique_result = [list(map(list, set(map(tuple, part)))) for part in result]
for x in unique_result:
x.sort(key=lambda item: (len(item), item))
unique_result.sort(key=lambda item: (-len(item), item))
return unique_result
print(makecomb([1,2,3]))
That should give you:
[[[1], [2], [3]], [[1], [2, 3]], [[2], [1, 3]], [[3], [1, 2]], [[1, 2, 3]]]