Перестановки предназначены для того, чтобы взять упорядоченный набор вещей и переместить эти вещи (то есть изменить порядок).Ваш вопрос касается комбинаций вещей из вашего списка.
Теперь простой способ перечисления комбинаций - это сопоставление записей из вашего списка с битами в числе.Например, предположим, что если установлен бит № 0 (т. Е. 1), то в комбинации участвует число lst[0]
, если установлен бит № 1, то в комбинации участвует lst[1]
и т. Д. Таким образом, числа вдиапазон 0 <= n < 2**(len(lst))
идентифицирует все возможные комбинации lst
членов, включая пустой (n = 0
) и целое lst
(n = 2**(len(lst)) - 1
).
Вам нужны только комбинации из 2 или более элементовт.е. только те идентификаторы комбинации, которые имеют по крайней мере два ненулевых бита в своем двоичном представлении.Вот как это определить:
def HasAtLeastTwoBitsSet(x) :
return (x & (x-1)) != 0
# Testing:
>>> [x for x in range(33) if HasAtLeastTwoBitsSet(x)]
[3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
Следующим шагом является извлечение комбинации элементов списка, идентифицируемых идентификатором комбинации.Это легко, благодаря возможности понимания списка:
def GetSublistByCombination(lst, combination_id) :
res = [x for (i,x) in enumerate(lst) if combination_id & (1 << i)]
return res
# Testing:
>>> GetSublistByCombination([0,1,2,3], 1)
[0]
>>> GetSublistByCombination([0,1,2,3], 3)
[0, 1]
>>> GetSublistByCombination([0,1,2,3], 12)
[2, 3]
>>> GetSublistByCombination([0,1,2,3], 15)
[0, 1, 2, 3]
Теперь давайте создадим генератор, который генерирует все суммы вместе с их строковыми представлениями:
def IterAllSums(lst) :
combinations = [i for i in range(1 << len(lst)) if HasAtLeastTwoBitsSet(i)]
for comb in combinations :
sublist = GetSublistByCombination(lst, comb)
sum_str = '+'.join(map(str, sublist))
sum_val = sum(sublist)
yield (sum_str, sum_val)
И, наконец,давайте использовать это:
>>> for sum_str, sum_val in IterAllSums([1,2,3,4]) : print sum_str, sum_val
1+2 3
1+3 4
2+3 5
1+2+3 6
1+4 5
2+4 6
1+2+4 7
3+4 7
1+3+4 8
2+3+4 9
1+2+3+4 10