Как разложить число на слагаемые в двумерный массив?

Пример n = 4

l = [[1,1,1,1],[1,1,2],[1,3],[2,2],[4]]

Как это сделать?


Ответы (2 шт):

Автор решения: Zhihar
n = 4

def prepare_arr(arr, n):
  arr.append(arr[-1][:-2] + [arr[-1][-2] + arr[-1][-1]] if len(arr) else [1] * n)

  if len(arr[-1]) != 1:
    prepare_arr(arr, n)

  return arr


print(prepare_arr([], n)[:-1])

но для получения всех слагаемых алгоритм конечно иной несколько, да и всех слагаемых чуть больше

ну или так:

n = 4

arr = [[1] * (n - i) + [i] for i in range(1, n)]

print(arr)
→ Ссылка
Автор решения: vp_arth

foo(n, k) возвращает все разбиения числа n, в которых слагаемые не больше k.
foo(0, k) возвращает пустой список

Находим рекуррентное соотношение, как [i] + каждое разбиение из foo(n-i, i) для i = (0, min(n, k))

def foo(n, k = None):
    if k is None:
        k = n

    if n == 0:
        return []

    result = []
    if n <= k:
        result.append([n])
    for i in range(1, 1+min(n, k)):
        for l in foo(n-i, i):
            result.append(l + [i])

    return result

print(*foo(5), sep='\n')  
[5]
[1, 1, 1, 1, 1]
[1, 1, 1, 2]
[1, 2, 2]
[2, 3]
[1, 1, 3]
[1, 4]

То же, с list comprehension:

def foo(n, k = None):
    if k is None:
        k = n

    if n == 0:
        return []

    return ([[n]] if n<=k else []) + [
        l + [i]
        for i in range(1, 1+min(n, k))
        for l in foo(n-i, i)]
→ Ссылка