Вот самое простое рекурсивное решение, которое я могу придумать, чтобы «найти все возможные комбинации из n чисел со значениями x такими, что 1 <= x <= max_val и x (1) + ... + x (n) = target ». Я разрабатываю это с нуля. Вот версия без какой-либо оптимизации, просто для простоты: </p>
def apcnx(n, max_val, target, xsofar=(), sumsofar=0):
if n==0:
if sumsofar==target:
yield xsofar
return
if xsofar:
minx = xsofar[-1] - 1
else:
minx = 0
for x in xrange(minx, max_val):
for xposs in apcnx(n-1, max_val, target, xsofar + (x+1,), sumsofar+x+1):
yield xposs
for xs in apcnx(4, 6, 12):
print xs
Базовый случай n==0
(где мы не можем привести больше чисел) либо даст кортеж, если он удовлетворяет условию, либо ничего, затем завершается (возвращает).
Если мы должны дать более длинные кортежи, чем мы построили до сих пор, if/else
гарантирует, что мы будем давать только неубывающие кортежи, чтобы избежать повторения (вы сказали «комбинация», а не «перестановка») .
for
пробует все возможности для элемента "this" и перебирает все, что еще может дать следующий-нижний уровень рекурсии.
Вывод, который я вижу:
(1, 1, 4, 6)
(1, 1, 5, 5)
(1, 2, 3, 6)
(1, 2, 4, 5)
(1, 3, 3, 5)
(1, 3, 4, 4)
(2, 2, 2, 6)
(2, 2, 3, 5)
(2, 2, 4, 4)
(2, 3, 3, 4)
(3, 3, 3, 3)
что кажется правильным.
Существует несколько возможных оптимизаций, но помните:
Сначала заставьте это работать, затем сделайте это быстро
Я переписывался с Кентом Беком, чтобы правильно приписать эту цитату в «Питоне в двух словах», и он сказал мне, что получил ее от своего отца, чья работа была фактически не связана с программированием; -).
В этом случае мне кажется, что ключевым вопросом является понимание того, что происходит, и любая оптимизация может помешать, поэтому я изо всех сил стараюсь "просто и понятно"; мы можем, в случае необходимости, оптимизировать носки, как только ОП подтвердит, что они могут понять, что происходит в этой чистой, неоптимизированной версии!