Algorithm to generate all multiset size-n partitions

后端 未结 3 1132
抹茶落季
抹茶落季 2021-02-09 18:42

I\'ve been trying to figure out a way to generate all distinct size-n partitions of a multiset, but so far have come up empty handed. First let me show what I\'m trying to archi

3条回答
  •  广开言路
    2021-02-09 19:16

    A recursive algorithm to distribute the elements one-by-one could be based on a few simple rules:

    • Start by sorting or counting the different elements; they don't have to be in any particular order, you just want to group identical elements together. (This step will simplify some of the following steps, but could be skipped.)
       {A,B,D,C,C,D,B,A,C} -> {A,A,B,B,D,D,C,C,C}  
    
    • Start with an empty solution, and insert the elements one by one, using the following rules:
       { , , } { , , } { , , }  
    
    • Before inserting an element, find the duplicate blocks, e.g.:
       {A, , } { , , } { , , }  
                        ^dup^
    
       {A, , } {A, , } {A, , }  
                ^dup^   ^dup^
    
    • Insert the element into every non-duplicate block with available space:
       partial solution: {A, , } {A, , } { , , }  
                                  ^dup^
    
       insert element B: {A,B, } {A, , } { , , }  
                         {A, , } {A, , } {B, , }  
    
    • If an identical element is already present, don't put the new element before it:
       partial solution:  {A, , } {B, , } { , , }  
       insert another B:  {A,B, } {B, , } { , , }  <- ILLEGAL  
                          {A, , } {B,B, } { , , }  <- OK
                          {A, , } {B, , } {B, , }  <- OK
    
    • When inserting an element of which there are another N identical elements, make sure to leave N open spots after the current element:
       partial solution:  {A, , } {A, , } {B,B, }  
       insert first D:    {A,D, } {A, , } {B,B, }  <- OK  
                          {A, , } {A, , } {B,B,D}  <- ILLEGAL (NO SPACE FOR 2ND D)  
    
    • The last group of identical elements can be inserted in one go:
       partial solution:  {A,A, } {B,B,D} {D, , }  
       insert C,C,C:      {A,A,C} {B,B,D} {D,C,C}  
    

    So the algorithm would be something like this:

    // PREPARATION  
    Sort or group input.              // {A,B,D,C,C,D,B,A,C} -> {A,A,B,B,D,D,C,C,C}  
    Create empty partial solution.    // { , , } { , , } { , , }  
    Start recursion with empty partial solution and index at start of input.  
    
    // RECURSION  
    Receive partial solution, index, group size and last-used block.  
    If group size is zero:  
        Find group size of identical elements in input, starting at index.  
        Set last-used block to first block.  
    Find empty places in partial solution, starting at last-used block.  
    If index is at last group in input:  
        Fill empty spaces with elements of last group.
        Store complete solution.
        Return from recursion.
    Mark duplicate blocks in partial solution.  
    For each block in partial solution, starting at last-used block:  
        If current block is not a duplicate, and has empty places,  
        and the places left in current and later blocks is not less than the group size:
            Insert element into copy of partial solution.
            Recurse with copy, index + 1, group size - 1, current block.
    

    I tested a simple JavaScript implementation of this algorithm, and it gives the correct output.

提交回复
热议问题