Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spliting a list into n uneven buckets with all combinations

I have a list like:

lst = [1,2,3,4,5,6,7,8,9,10]

and I want to get the combination of all splits for a given n bucket without changing the order of the list. Output exp for n=3:

[
 [1],[2],[3,4,5,6,7,8,9,10],
 [1],[2,3],[4,5,6,7,8,9,10],
 [1],[2,3,4],[5,6,7,8,9,10],
 .
 .
 .
 [1,2,3,4,5,6,7,8],[9],[10],
]

Python is the language I use but if you can direct me to an algorithm that would nice as well. I see this problem is usually apllied on strings. But couldn't figure it out on the list.

P.S. this is my first question. Any feedback is appreciated on how to improve the question.

like image 833
Poyraz Tahan Avatar asked Sep 01 '21 14:09

Poyraz Tahan


3 Answers

Try:

from itertools import product


def generate(n, l):
    for c in product(range(1, l), repeat=n - 1):
        s = sum(c)
        if s > l - 1:
            continue
        yield *c, l - s


lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
n = 3

for groups in generate(n, len(lst)):
    l, out = lst, []
    for g in groups:
        out.append(l[:g])
        l = l[g:]
    print(out)

Prints:

[[1], [2], [3, 4, 5, 6, 7, 8, 9, 10]]
[[1], [2, 3], [4, 5, 6, 7, 8, 9, 10]]
[[1], [2, 3, 4], [5, 6, 7, 8, 9, 10]]
[[1], [2, 3, 4, 5], [6, 7, 8, 9, 10]]
[[1], [2, 3, 4, 5, 6], [7, 8, 9, 10]]
[[1], [2, 3, 4, 5, 6, 7], [8, 9, 10]]
[[1], [2, 3, 4, 5, 6, 7, 8], [9, 10]]
[[1], [2, 3, 4, 5, 6, 7, 8, 9], [10]]
[[1, 2], [3], [4, 5, 6, 7, 8, 9, 10]]
[[1, 2], [3, 4], [5, 6, 7, 8, 9, 10]]
[[1, 2], [3, 4, 5], [6, 7, 8, 9, 10]]
[[1, 2], [3, 4, 5, 6], [7, 8, 9, 10]]
[[1, 2], [3, 4, 5, 6, 7], [8, 9, 10]]
[[1, 2], [3, 4, 5, 6, 7, 8], [9, 10]]
[[1, 2], [3, 4, 5, 6, 7, 8, 9], [10]]
[[1, 2, 3], [4], [5, 6, 7, 8, 9, 10]]
[[1, 2, 3], [4, 5], [6, 7, 8, 9, 10]]
[[1, 2, 3], [4, 5, 6], [7, 8, 9, 10]]
[[1, 2, 3], [4, 5, 6, 7], [8, 9, 10]]
[[1, 2, 3], [4, 5, 6, 7, 8], [9, 10]]
[[1, 2, 3], [4, 5, 6, 7, 8, 9], [10]]
[[1, 2, 3, 4], [5], [6, 7, 8, 9, 10]]
[[1, 2, 3, 4], [5, 6], [7, 8, 9, 10]]
[[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
[[1, 2, 3, 4], [5, 6, 7, 8, 9], [10]]
[[1, 2, 3, 4, 5], [6], [7, 8, 9, 10]]
[[1, 2, 3, 4, 5], [6, 7], [8, 9, 10]]
[[1, 2, 3, 4, 5], [6, 7, 8], [9, 10]]
[[1, 2, 3, 4, 5], [6, 7, 8, 9], [10]]
[[1, 2, 3, 4, 5, 6], [7], [8, 9, 10]]
[[1, 2, 3, 4, 5, 6], [7, 8], [9, 10]]
[[1, 2, 3, 4, 5, 6], [7, 8, 9], [10]]
[[1, 2, 3, 4, 5, 6, 7], [8], [9, 10]]
[[1, 2, 3, 4, 5, 6, 7], [8, 9], [10]]
[[1, 2, 3, 4, 5, 6, 7, 8], [9], [10]]
like image 79
Andrej Kesely Avatar answered Nov 15 '22 00:11

Andrej Kesely


For a manual implementation, you could use a recursive generator function:

def parts(lst, n):
    if 0 < n <= len(lst):
        if n == 1:
            yield [lst]
        else:
            for i in range(1, len(lst)-n+2):
                for part in parts(lst[i:], n-1):
                    yield [lst[:i]] + part



pprint(list(parts([1,2,3,4], 3)))
# [[[1], [2], [3, 4]], 
#  [[1], [2, 3], [4]], 
#  [[1, 2], [3], [4]]]
pprint(list(parts([1,2,3,4,5,6], 3)))
# [[[1], [2], [3, 4, 5, 6]],
#  [[1], [2, 3], [4, 5, 6]],
#  [[1], [2, 3, 4], [5, 6]],
#  [[1], [2, 3, 4, 5], [6]],
#  [[1, 2], [3], [4, 5, 6]],
#  [[1, 2], [3, 4], [5, 6]],
#  [[1, 2], [3, 4, 5], [6]],
#  [[1, 2, 3], [4], [5, 6]],
#  [[1, 2, 3], [4, 5], [6]],
#  [[1, 2, 3, 4], [5], [6]]]
like image 38
user2390182 Avatar answered Nov 15 '22 01:11

user2390182


A slightly shorter recursive approach:

lst, n = [1,2,3,4,5,6,7,8,9,10], 3
def group(d, c = []):
   if not d and len(c) == n:
      yield c
   if d and c:
       yield from group(d[1:], c[:-1]+[c[-1]+[d[0]]])
   if d and len(c) < n:
       yield from group(d[1:], c+[[d[0]]])

print(list(group(lst)))

Output:

[[[1, 2, 3, 4, 5, 6, 7, 8], [9], [10]],
 [[1, 2, 3, 4, 5, 6, 7], [8, 9], [10]],
 [[1, 2, 3, 4, 5, 6, 7], [8], [9, 10]],
 [[1, 2, 3, 4, 5, 6], [7, 8, 9], [10]],
 [[1, 2, 3, 4, 5, 6], [7, 8], [9, 10]],
 [[1, 2, 3, 4, 5, 6], [7], [8, 9, 10]],
 [[1, 2, 3, 4, 5], [6, 7, 8, 9], [10]],
 [[1, 2, 3, 4, 5], [6, 7, 8], [9, 10]],
 [[1, 2, 3, 4, 5], [6, 7], [8, 9, 10]],
 [[1, 2, 3, 4, 5], [6], [7, 8, 9, 10]],
 [[1, 2, 3, 4], [5, 6, 7, 8, 9], [10]],
 [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]],
 [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]],
 [[1, 2, 3, 4], [5, 6], [7, 8, 9, 10]],
 [[1, 2, 3, 4], [5], [6, 7, 8, 9, 10]],
 [[1, 2, 3], [4, 5, 6, 7, 8, 9], [10]],
 [[1, 2, 3], [4, 5, 6, 7, 8], [9, 10]],
 [[1, 2, 3], [4, 5, 6, 7], [8, 9, 10]],
 [[1, 2, 3], [4, 5, 6], [7, 8, 9, 10]],
 [[1, 2, 3], [4, 5], [6, 7, 8, 9, 10]],
 [[1, 2, 3], [4], [5, 6, 7, 8, 9, 10]],
 [[1, 2], [3, 4, 5, 6, 7, 8, 9], [10]],
 [[1, 2], [3, 4, 5, 6, 7, 8], [9, 10]],
 [[1, 2], [3, 4, 5, 6, 7], [8, 9, 10]],
 [[1, 2], [3, 4, 5, 6], [7, 8, 9, 10]],
 [[1, 2], [3, 4, 5], [6, 7, 8, 9, 10]],
 [[1, 2], [3, 4], [5, 6, 7, 8, 9, 10]],
 [[1, 2], [3], [4, 5, 6, 7, 8, 9, 10]],
 [[1], [2, 3, 4, 5, 6, 7, 8, 9], [10]],
 [[1], [2, 3, 4, 5, 6, 7, 8], [9, 10]],
 [[1], [2, 3, 4, 5, 6, 7], [8, 9, 10]],
 [[1], [2, 3, 4, 5, 6], [7, 8, 9, 10]],
 [[1], [2, 3, 4, 5], [6, 7, 8, 9, 10]],
 [[1], [2, 3, 4], [5, 6, 7, 8, 9, 10]],
 [[1], [2, 3], [4, 5, 6, 7, 8, 9, 10]],
 [[1], [2], [3, 4, 5, 6, 7, 8, 9, 10]]]
like image 35
Ajax1234 Avatar answered Nov 15 '22 01:11

Ajax1234