У меня есть общее количество плотности N. Мне нужно найти все способы, которыми я могу разделить эту плотность на k групп, предполагая некоторую минимально делимую часть d.
Итак, если N = 4, k =3, d = 1, мне нужно:
[
(1, 1, 2),
(1, 2, 1),
(2, 1, 1),
]
Если N = 5, k = 3, d = 1:
[
(1, 1, 3),
(1, 3, 1),
(3, 1, 1),
(1, 2, 2),
(2, 1, 2),
(2, 2, 1),
]
Такое ощущение, что это должно соответствовать некоторой базовой проблеме комбинаторики, но я не могу думать об этом. Этот пост ссылается на очень похожую операцию в R, но не на python.
Один наивный способ сделать это - отфильтровать результат itertools.product
только для кортежей, которые суммируются с N, но это выглядит не элегантно:
import itertools
def compositions(N, k, d=1):
for seq in itertools.product(*[range(d, N, d)] * k):
if sum(seq) == N:
yield seq
Пример
>>> list(compositions(7, 3))
[(1, 1, 5),
(1, 2, 4),
(1, 3, 3),
(1, 4, 2),
(1, 5, 1),
(2, 1, 4),
(2, 2, 3),
(2, 3, 2),
(2, 4, 1),
(3, 1, 3),
(3, 2, 2),
(3, 3, 1),
(4, 1, 2),
(4, 2, 1),
(5, 1, 1)]
Есть еще идеи?