生成具有指定条目长度重复的有序选择
Generating an ordered selection with repetition of designated length of entry
我正在编写一个函数,从python中可用的sage组合函数中模拟unordered_tuple
。
然而,它的不同之处在于,我使用的输入集总是[10,9,8,7,6],并且只有条目的数量不同(不大于10)。
因此,条目=3和条目=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;
}
查看此处:
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的藏身之地。请注意,c
和it
在循环的之前设置为,在循环的末尾设置为,并且不再使用;我们可以在循环的开始设置它们,代码会更短更清晰:
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());
处理排列问题的一个好方法是递归。采用这种方法,要构建长度为3的所有输出,您可以从集合[6, 7, 8, 9, 10]
中选择一个数字,然后将长度为2的所有输出附加到该数字上,并将输入集限制为从所选数字开始。因此,如果您选择了7
,那么第一个递归调用的输入集将是[ 7, 8, 9, 10]
。也就是说,在这种情况下,递归调用将从输入[ 7, 8, 9, 10]
附加到[ 7 ]
所有长度为2
的输出
下面是一个实现这一想法的程序。我很想看看是否有人能想出一个非递归的解决方案。
#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;
}
它似乎对你的两个例子都有效(但我只彻底检查了第一个)。如果你不能通过阅读代码来了解它是如何工作的,一个好的方法是在调试器中运行它(这就是我必须做的事情!:)
- 如何使用默认参数等选择模板专业化
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 选择要调用的构造函数
- C++选择排序算法中的逻辑错误
- QTreeView幻灯片多选后无法使用单击选择
- 无法获取菜单选择以运行函数.C++
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 在C++中,如何通过几种类型从元组中选择多个元素
- 讨论 - 创建矩阵时的数组与向量的向量 - 什么是最实用的选择
- 对可变参数使用声明.如何选择正确的功能
- 选择选举获胜者的程序
- 如何选择在 csv 文件中输出的位置
- 根据用户回答声明"Players"。用户选择玩家数量。播放器是结构体
- 程序在尝试猜测它选择的随机数时进入无限循环?
- 选择和修改嵌套向量中的条目的最佳实践
- 在PostgreSQL中根据它们的ID选择大量行的最快方法是什么?
- 表达式 SFINAE:如何根据类型是否包含具有一个或多个参数的函数来选择模板版本
- 在运行时选择父类的实现
- 数数并选择 sqlite 中的前三名
- 列表视图更改选择颜色