【问题标题】:permutations of N balls in M boxes in C++C++中M个盒子中N个球的排列
【发布时间】:2011-07-07 20:39:23
【问题描述】:

上周我问了一个关于 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))

我没有 python 技能,尽管我阅读了文档,但我不明白这个函数。

【问题讨论】:

  • 具体哪些部分你不明白?
  • 我不明白 itertools.combinations() 算法和“stops = indices + (size,)”的语法。关于map(),它是否分别减去starts和stop的元素,例如stops[i] - starts[i]或stops[1] -stops[2]...和starts[1] -starts[2]?跨度>

标签: c++ python permutation


【解决方案1】:

你知道 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 一样,您无法更改,但使用圆括号 () 而不是方括号 [])。您可以使用 [x] 创建一个单元素列表,但 (x) 会产生歧义,因为圆括号也用于其他事物,例如函数参数和分组。

关于map(),...

阅读doc,试一试,不难。

【讨论】:

  • 感谢您的帮助。关于组合()这不是结果,而是我不理解的算法本身。我玩得很好:)
  • @eryksun,谢谢你 - 我忘了单独使用逗号
【解决方案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()();
        }
    }
};

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多