1

I have a set of different numbers, e.g. set = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110].

Now I want to partition this list into sublists which are not longer than 5.

I know how I can partition this list into sublists which are exactly 5: partition = numpy.array_split(list, 5)

This will yield [[10, 20, 30, 40, 50], [60, 70, 80, 90, 100], [110]].

But how can I achieve, that I have all possible partitions? So, my "targetpartition" would contain the sets

[ [10, 20, 30, 40, 50], [60, 70, 80, 90, 100], [110] ],

[ [10], [20, 30, 40, 50], [60, 70], [80, 90, 100, 110] ],

[ [10], [20], [30], [40], [50], [60], [70], [80], [90, 100], [110] ]

and many many more.

7
  • Similar question has been answered stackoverflow.com/questions/9671224/… and stackoverflow.com/questions/312443/… Commented Aug 12, 2024 at 12:40
  • This question is similar to: How do I split a list into equally-sized chunks?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Aug 12, 2024 at 12:40
  • imo, your title, 'examples' and supporting text/'explanations' do not make coherent sense, need to rethink,edit and republish. Commented Aug 12, 2024 at 13:39
  • You can try a recursive algorithm: 1) split the first element off the list; 2) get partitions of the rest of the list (recursive); 3) yield all those partitions with the first element being a separate sublist, or part of the first sublist of the partitions of the rest of the list. Commented Aug 12, 2024 at 13:43
  • @ticktalk Should be better now., Commented Aug 12, 2024 at 14:03

1 Answer 1

1

Your "partition" is defined by whether you put a block end between each pair of numbers or not. So, if your list has 11 elements then there are 10 intermediate positions where you can put a block end or not - in binary terms, a 1 or a 0.

So, you can generate ALL partitions simply (in your 11-item example) by counting in binary: in your case from 0 to 210-1:

0000000000
0000000001
..........
1111111111

You can put these in 10-character strings. (Make sure that you include the leading zeros if there are any.)

You would REJECT a string as invalid if there were more than 4 successive spaces; i.e. if you find substring "00000" in the string.

In your example there are 1024 partitions, but only 912 are valid.

You don't say what you want to do with the output. In the below example I have simply written the partition to screen, but you can do what you like with function output().

Fundamentally, however, the partitioning is entirely defined by that binary string. Sometimes this is called "stars and bars".

def toBinary( n, length ):
    return "{0:0{1}b}".format( n, length )

def isValid( s ):
    return s.find( "00000" ) < 0

def output( L, s ):
    print( L[0], end="" )                        # print first value
    for n, b in zip( L[1:], s ):
        if b == "1": print( " | ", end="" )      # print an end block if the relevant entry is "1"
        else       : print( " "  , end="" )      #    or just a space otherwise
        print( n, end="" )                       # print the next number
    print()                                      # finish the line


L = [ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110 ]
N = len( L ) - 1

for i in range( 2 ** N ):
    s = toBinary( i, N )
    if isValid( s ): 
        output( L, s )

Output (912 lines):

10 20 30 40 50 | 60 70 80 90 100 | 110
10 20 30 40 50 | 60 70 80 90 | 100 110
10 20 30 40 50 | 60 70 80 90 | 100 | 110
10 20 30 40 50 | 60 70 80 | 90 100 110
10 20 30 40 50 | 60 70 80 | 90 100 | 110
10 20 30 40 50 | 60 70 80 | 90 | 100 110
10 20 30 40 50 | 60 70 80 | 90 | 100 | 110
10 20 30 40 50 | 60 70 | 80 90 100 110
..........
10 20 | 30 40 50 | 60 70 80 90 100 | 110
10 20 | 30 40 50 | 60 70 80 90 | 100 110
10 20 | 30 40 50 | 60 70 80 90 | 100 | 110
..........
10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 90 | 100 | 110
10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 100 110
10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 100 | 110
10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 110
10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 | 110
Sign up to request clarification or add additional context in comments.

1 Comment

I planned to play around with the itertools module to solve this issue but I have to say I love your solution. It is a great example of how to translate an issue into a slightly different one to approach it systematically. Great job!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.