生成具有指定长度重复项的有序选择

2024-06-10 21:22:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个类似于python中可用的sage combinatorial functions的函数。你知道吗

不过,它的不同之处在于,我使用的输入集总是[10,9,8,7,6],只有条目数不同(不大于10)。你知道吗

因此,entry=3和entry=4的期望输出是

unordered_tuples([10,9,8,7,6], 3)
[[6, 6, 6],
 [6, 6, 7],
 [6, 6, 8],
 [6, 6, 9],
 [6, 6, 10],
 [6, 7, 7],
 [6, 7, 8],
 [6, 7, 9],
 [6, 7, 10],
 [6, 8, 8],
 [6, 8, 9],
 [6, 8, 10],
 [6, 9, 9],
 [6, 9, 10],
 [6, 10, 10],
 [7, 7, 7],
 [7, 7, 8],
 [7, 7, 9],
 [7, 7, 10],
 [7, 8, 8],
 [7, 8, 9],
 [7, 8, 10],
 [7, 9, 9],
 [7, 9, 10],
 [7, 10, 10],
 [8, 8, 8],
 [8, 8, 9],
 [8, 8, 10],
 [8, 9, 9],
 [8, 9, 10],
 [8, 10, 10],
 [9, 9, 9],
 [9, 9, 10],
 [9, 10, 10],
 [10, 10, 10]]

unordered_tuples([10,9,8,7,6], 4)
[[6, 6, 6, 6],
 [6, 6, 6, 7],
 [6, 6, 6, 8],
 [6, 6, 6, 9],
 [6, 6, 6, 10],
 [6, 6, 7, 7],
 [6, 6, 7, 8],
 [6, 6, 7, 9],
 [6, 6, 7, 10],
 [6, 6, 8, 8],
 [6, 6, 8, 9],
 [6, 6, 8, 10],
 [6, 6, 9, 9],
 [6, 6, 9, 10],
 [6, 6, 10, 10],
 [6, 7, 7, 7],
 [6, 7, 7, 8],
 [6, 7, 7, 9],
 [6, 7, 7, 10],
 [6, 7, 8, 8],
 [6, 7, 8, 9],
 [6, 7, 8, 10],
 [6, 7, 9, 9],
 [6, 7, 9, 10],
 [6, 7, 10, 10],
 [6, 8, 8, 8],
 [6, 8, 8, 9],
 [6, 8, 8, 10],
 [6, 8, 9, 9],
 [6, 8, 9, 10],
 [6, 8, 10, 10],
 [6, 9, 9, 9],
 [6, 9, 9, 10],
 [6, 9, 10, 10],
 [6, 10, 10, 10],
 [7, 7, 7, 7],
 [7, 7, 7, 8],
 [7, 7, 7, 9],
 [7, 7, 7, 10],
 [7, 7, 8, 8],
 [7, 7, 8, 9],
 [7, 7, 8, 10],
 [7, 7, 9, 9],
 [7, 7, 9, 10],
 [7, 7, 10, 10],
 [7, 8, 8, 8],
 [7, 8, 8, 9],
 [7, 8, 8, 10],
 [7, 8, 9, 9],
 [7, 8, 9, 10],
 [7, 8, 10, 10],
 [7, 9, 9, 9],
 [7, 9, 9, 10],
 [7, 9, 10, 10],
 [7, 10, 10, 10],
 [8, 8, 8, 8],
 [8, 8, 8, 9],
 [8, 8, 8, 10],
 [8, 8, 9, 9],
 [8, 8, 9, 10],
 [8, 8, 10, 10],
 [8, 9, 9, 9],
 [8, 9, 9, 10],
 [8, 9, 10, 10],
 [8, 10, 10, 10],
 [9, 9, 9, 9],
 [9, 9, 9, 10],
 [9, 9, 10, 10],
 [9, 10, 10, 10],
 [10, 10, 10, 10]]

我写的c++函数如下。你知道吗

我其实不是一个经验丰富的程序员,我只是试图提出正确的解决方案,但它是正确的工作,但它给出了很多重复的解决方案。你知道吗

老实说,我写的函数,但我甚至不知道我写了什么。你知道吗

我可以使用set,但是效率很低,我想知道这个问题的正确解决方案。你知道吗

有人能把它修好,这样它就可以输出上面的结果了吗?你知道吗

    #include<iostream>
    #include<string>
    #include<cstdlib>
    #include<vector>

    using namespace std;

    vector<vector<int> > ut(int);

    int main(int argc, char** argv) {
        int entry = atoi(argv[1]);
        ut(entry);
        return 1;
    }

    vector<vector<int> > ut(int entry) {
        vector<vector<int> > ret;

        int upper = 10;
        vector<int> v(entry, upper);
        ret.push_back(v);

        typedef vector<int>::iterator iter_t;

        iter_t it = v.begin();
        int count=0;
        int c = 0;
        while(v.back() != 6) {
            v = ret[count+c];
            while(it != v.end()) {
                --(*it);
                ++it;
                ret.push_back(v);
                ++c;
            }
            it = v.begin();
            c=0;
            ++count;
        }


        for(int i=0; i<ret.size(); ++i) {
            vector<int> tuple = ret[i];
            for(int j=0; j<tuple.size(); ++j) {
                cout << tuple[j] << ' ';
            }
            cout<<endl;
        }
        cout << endl;
        return ret;
    }

Tags: 函数includecountbackit解决方案intentry
2条回答

从排列问题开始的一个好地方是递归。采用这种方法,要构建长度为3的所有输出,您可以从集合[6, 7, 8, 9, 10]中选择一个数字,然后将长度为2的所有输出附加到该集合中,并将输入集合约束为从所选数字开始。因此,如果您选择了7,那么第一个递归调用的输入集将是[ 7, 8, 9, 10]。也就是说,在这种情况下,递归调用将附加到来自输入[ 7, 8, 9, 10]的长度为2的所有输出[ 7 ]

下面是一个实现这个想法的程序。我想看看是否有人能想出一个非递归的解决方案。你知道吗

#include "stdafx.h"
#include <iostream>
#include <vector>

typedef std::vector<int> intvec;
typedef std::vector<intvec> intvecs;

void GenerateUnOrderedIntVecs(
    const int* remainingInput, int remainingInputLen, 
    const intvec& outputSoFar, int remainingOutputLen,
    intvecs& output)
{
    if (remainingOutputLen == 0) { // base case of recursion
        output.push_back(outputSoFar);
        return;
    }

    // For all digits in our input
    for(int i=0; i<remainingInputLen; ++i) {
        // Add the ith digit to our output so far
        intvec outputSoFar2(outputSoFar);
        outputSoFar2.push_back(remainingInput[i]);
        // The recursion
        GenerateUnOrderedIntVecs(
            remainingInput + i,    // input set constrained to start from chosen digit
            remainingInputLen - i, // input set is shorter
            outputSoFar2,          // one digit longer than the parameter outputSoFar
            remainingOutputLen -1, // so we need one digit less as we recurse
            output);
    }
}

int main(int argc, _TCHAR* argv[])
{
    const int nToChooseFrom = 5;
    const int nToChooose = 3;
    const int input[nToChooseFrom] = { 6, 7, 8, 9, 10 }; // provide input in sorted order (or sort it!)

    intvecs output;
    GenerateUnOrderedIntVecs(
        input, nToChooseFrom,
        intvec(), nToChooose,
        output);

    for(intvecs::const_iterator i=output.begin(); i!=output.end(); ++i) {
        std::cout << "[ ";
        const intvec& unordered_tuple = *i;
        for(intvec::const_iterator j = unordered_tuple.begin(); j!=unordered_tuple.end(); ++j) {
            std::cout << *j << " ";
        }
        std::cout << "]\n";
    }

    return 0;
}

这似乎对你的两个例子都有效(但我只彻底检查了第一个)。如果您无法通过读取代码来了解它的工作原理,那么一个好的方法就是在调试器中运行它(这就是我必须要做的!:)

看这里:

vector<vector<int> > ret;

int upper = 10;
vector<int> v(entry, upper);
ret.push_back(v);

typedef vector<int>::iterator iter_t;

iter_t it = v.begin();
int count=0;
int c = 0;
while(v.back() != 6) {
  v = ret[count+c];
  while(it != v.end()) {
     (*it);
    ++it;
    ret.push_back(v);
    ++c;
  }
  it = v.begin();
  c=0;
  ++count;
}

这太可怕了。(我知道你是个初学者;请理解我的批评是为了帮助你。)通常这种密集的复杂性是不必要的,是bug的藏身之地。请注意,cit在循环之前设置,在循环的末尾设置,并且不再使用;我们可以在循环的开头设置它们,代码将更短更清晰:

int count=0;
while(v.back() != 6) {
  iter_t it = v.begin();
  int c = 0;
  v = ret[count+c];
  while(it != v.end()) {
     (*it);
    ++it;
    ret.push_back(v);
    ++c;
  }
  ++count;
}

现在我们可以看到c从不被使用,除非它是零。(如果你不相信我,请看原始代码。)但更糟糕的是it指向v,然后v被赋予一个新值。所以it可能指向死内存,取消对它的引用会导致未定义的行为。现在还不清楚这段代码到底是如何工作的。你知道吗

试试这个:

vector<int> v(n,6);

vector<int>::iterator itr1;
do{
  ret.push_back(v);

  itr1 = v.begin();

  while(++(*itr1)>10){
      if(++itr1==v.end())
        break;
  }
  for(vector<int>::iterator itr2 = v.begin(); itr2!=itr1; ++itr2)
    *itr2 = *itr1;
}
while(itr1!=v.end());

相关问题 更多 >