C ++中M盒中N个球的排列

时间:2011-07-07 09:05:33

标签: c++ python permutation

我上周问了一个关于C ++中排列的问题(List of combinations of N balls in M boxes in C++)。

答案对我帮助很大,但我的问题现在已经改变了。 我想要做的是从这个python函数到C ++的转换,在结果中保持相同的顺序:

def combinations_with_replacement_counts(n, r):  #(n-boxes, r-balls)
   size = n + r - 1
   for indices in itertools.combinations(range(size), n-1):
       #print indices
       starts = [0] + [index+1 for index in indices]
       stops = indices + (size,)
       yield tuple(map(operator.sub, stops, starts))

我没有蟒蛇的技能,尽管我阅读了文档,但我不明白这个功能。

3 个答案:

答案 0 :(得分:3)

你知道python是解释的,对吗?你可以直接在python中输入你不理解的行,看看会发生什么......首先从小值开始。

  

我不理解itertools.combinations()算法

文档为here,包含示例输出。 请注意,combinations返回的值是惰性的,因此您需要强制进行评估才能看到它:

>>> import itertools
>>> itertools.combinations(range(4), 2)
<itertools.combinations object at 0x979a964>
>>> list(itertools.combinations(range(4), 2))
[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]

现在combinations做了什么?如果没有,请玩它。

  

...和“stops = indices +(size,)”

的语法

所以尝试它,它不会咬人:

>>> indices=list(itertools.combinations(range(4), 2))[0]
>>> size=4
>>> stops=indices + (size,)
>>> indices
(0, 1)
>>> stops
(0, 1, 4)

语法(x,)创建一个单元素元组(一个不变的序列 - 就像list一样,你不能改变但是用圆括号()而不是方括号{{1} }})。您可以使用[]创建单元素列表,但[x]不明确,因为圆括号也用于其他事情,如函数参数和分组。

  

关于map(),...

阅读doc,玩一下,这并不难。

答案 1 :(得分:2)

这个C ++代码似乎与你的python示例具有相同的结果。它远非完美的,你仍然可以理解算法甚至使用这个实现。

#include <deque>
typedef std::deque<size_t> BoxList;

class Generator {
    size_t boxNum, ballNum, ownBox;
    Generator* recursive;
public:
    ~Generator() { if ( recursive == NULL ) delete recursive; }
    Generator( size_t boxes, size_t balls ) : boxNum(boxes), ballNum(balls) {
        if ( boxes > 1 ) {
            recursive = new Generator( boxes-1, balls );
            ownBox = 0;
        } else {
            recursive = NULL;
            ownBox = balls;
        }
    }
    BoxList operator()() {
        if ( ownBox > ballNum ) throw 1;
        if ( boxNum <= 1 ) return BoxList( 1, ownBox++ );
        try {
            BoxList res = recursive->operator()(); 
            res.push_front( ownBox );
            return res;
        }
        catch(...) {
            delete recursive;
            ownBox++;
            recursive = new Generator( boxNum-1, ballNum-ownBox );
            return operator()();
        }
    }
};

类接口允许您将其用作标准生成器。当已经迭代了所有可能的选项时,Operator()将生成异常。

Generator g( boxes, balls );
try{
    while( true )
        g();
}
catch(...) {}

答案 2 :(得分:0)

你引用的Python代码正在实现我在my answer to your question中描述的算法:它正在迭代放置 r 的可能方法 - 在 n +中的1个框 r - 1个位置,然后列出相邻位置之间的差异(计算扫入该方框的球数)。