开发者

Next Composition of n into k parts - does anyone have a working algorithm? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.

We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.

Closed 2 years ago.

Improve this question

Composition of n into k parts - I want to list all the possible compositions of n into k parts - does anyone have an algorithm (preferably in R)? Or know if i开发者_开发百科t's in library anywhere?

For example, if I have n cubes, and k bags, and want to list all the possible arrangements of the cubes in the bags. e.g. there are 3 ways you can arrange 2 cubes into 2 bags:

(2, 0) (1, 1) (0, 2)

I've found the NEXCOM alogarithm. I've found a version of it here (page 46) in Fortran, but don't code in Fortran so really understand what's going on - any help?


Since it took me a bit of effort to read the intention of the other c++ solution here a translation to python (also as generator result instead of string):

def weak_compositions(boxes, balls, parent=tuple()):
  if boxes > 1:
    for i in xrange(balls + 1):
      for x in weak_compositions(boxes - 1, i, parent + (balls - i,)):
        yield x
  else:
    yield parent + (balls,)

test:

>>> for x in weak_compositions(3, 5): print x
(5, 0, 0)
(4, 1, 0)
(4, 0, 1)
(3, 2, 0)
...
(0, 1, 4)
(0, 0, 5)


What you are attempting to list is called an k-multicombination. The problem is often stated this way: given n indistinguishable balls and k boxes, list all possible ways to distribute all of the balls in the boxes. The number of such distributions is:

factorial(n + k - 1) / (factorial(k - 1) * factorial(n))

For further background, see Method 4 of the Twelve-Fold Way.

Here is the code to enumerate the distributions (C++):

string & ListMultisets(unsigned au4Boxes, unsigned au4Balls, string & strOut = string ( ), string strBuild = string ( ))
{
    unsigned au4;
    if (au4Boxes > 1) for (au4 = 0; au4 <= au4Balls; au4++)
    {
        stringstream ss;
        ss << strBuild << (strBuild.size() == 0 ? "" : ",") << au4Balls - au4;
        ListMultisets (au4Boxes - 1, au4, strOut, ss.str ( ));
    }
    else
    {
        stringstream ss;
        ss << "(" << strBuild << (strBuild.size() == 0 ? "" : ",") << au4Balls << ")\n";
        strOut += ss.str ( );
    }
    return strOut;
}



int main(int argc, char * [])
{    
    cout << endl << ListMultisets (3, 5) << endl;
    return 0;
}

Here is the output from the above program (5 balls distributed over three boxes):

(5,0,0)
(4,1,0)
(4,0,1)
(3,2,0)
(3,1,1)
(3,0,2)
(2,3,0)
(2,2,1)
(2,1,2)
(2,0,3)
(1,4,0)
(1,3,1)
(1,2,2)
(1,1,3)
(1,0,4)
(0,5,0)
(0,4,1)
(0,3,2)
(0,2,3)
(0,1,4)
(0,0,5)


Computing compositions (I ignore how standard the term is) and combinations is equivalent in a sense. There's a bijective function between combinations of k + 1 in n + k and compositions of n into k parts. All one has to do is assign a number from 1 to n to each letter of the combinations, order the letters according to their number, then:

  • make a tuple composed of the differences between numbers of consecutive letters
  • subtract 1 to each entry of the tuple, and there you have it.

Assuming your algorithm for computing combinations yields combinations with 'ordered letters', then the rest is a trivial computation.

In Python:

from itertools import combinations, tee 
  #see: 
  #http://docs.python.org/library/itertools.html#itertools.combinations
  #http://docs.python.org/library/itertools.html#itertools.tee

def diffed_tuple(t): # return a new tuple but where the entries are the differences # between consecutive entries of the original tuple. #make two iterator objects which yield entries from t in parallel t2, t1 = tee(t) # advance first iterator one step for x in t2: break # return a tuple made of the entries yielded by the iterators return tuple(e2 - e1 for e2, e1 in zip(t2, t1))

# --The Algorithm-- def compositions(n, k): for t in combinations(range(n+k), k+1): # yield the 'diffed tuple' but subtracting 1 from each entry yield tuple(e-1 for e in diffed_tuple(t))


I've made the translation of the original NEXCOM algorithm to structured Fortran and Java. The Java version is:

public void allCombinations(final int n, final int k) {
    final int[] input = new int[k + 1];
    Boolean mtc = Boolean.FALSE;
    int t = n;
    int h = 0;
    do {
        if (mtc) {
            if (t > 1) {
                h = 0;
            }
            h++;
            t = input[h];
            input[h] = 0;
            input[1] = t - 1;
            input[h + 1]++;
        } else {
            // First permutation is always n00...0 i.e. it's a descending
            // series lexicographically.
            input[1] = n;
            for (int i = 2; i <= k; i++) {
                input[i] = 0;
            }
        }
        System.out.println(java.util.Arrays.toString(input));
        mtc = input[k] != n;
    } while (mtc);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜