473,756 Members | 2,117 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Passing vectors as parameters to a recursive function

This might be more appropriate here. I'm new to C++, coming from a
background in another languages that allowed a similar solution to work
(Python). I wrote the following code in C++ based on the Python code
found here:

http://aspn.activestate.com/ASPN/Coo.../Recipe/302478

//beginning

#include <vector>
#include <iostream.h>
using namespace std;

void looper(vector <vector<int> > nseq, vector<int> comb);
vector <vector<int> > master;

int main() {
int n, C;
vector <vector<int> > seq;
vector<int> holder;
cout << "Enter constant: ";
cin >> C;
cout << "Enter n: ";
cin >> n;
for(i=0; i<=n; i++) {
vector <int> tmp;
for(int j=0; j<=C; j++) {
tmp.push_back(j );
}
seq.push_back(t mp);
}
looper(seq, holder);
return 0;
}

void looper(vector <vector<int> > nseq, vector<int> comb) {
if(nseq.size()> 0) {
vector<int> tseq = nseq.at(0);
for(int i=0; i<tseq.size(); i++) {
vector <vector<int> > gseq = nseq;
vector<int> tcomb = comb;
gseq.erase(0);
tcomb.push_back (tseq[i]);
looper(gseq, tcomb);
}
} else {
master.push_bac k(comb);
}
}

// end

The program dies on the line:

tcomb.push_back (tseq[i]);

It seems vectors can't be passed effectively as parameters to recursive
functions (at least how I'm doing it). Is this true?

Jul 23 '05 #1
5 9015
lugal wrote:
[snip]

void looper(vector <vector<int> > nseq, vector<int> comb) {
if(nseq.size()> 0) {
vector<int> tseq = nseq.at(0);
for(int i=0; i<tseq.size(); i++) {
vector <vector<int> > gseq = nseq;
vector<int> tcomb = comb;
gseq.erase(0); Try to replace the above line by "qseq.erase(1); " and see what your
compiler says about it ;) tcomb.push_back (tseq[i]);
looper(gseq, tcomb);
}
} else {
master.push_bac k(comb);
}
}

// end
[snip] It seems vectors can't be passed effectively as parameters to recursive functions (at least how I'm doing it). Is this true?

NO! :)

Best regards,
Bogdan Sintoma

Jul 23 '05 #2
lugal wrote:
This might be more appropriate here. I'm new to C++, coming from a
background in another languages that allowed a similar solution to work
(Python). I wrote the following code in C++ based on the Python code
found here:

http://aspn.activestate.com/ASPN/Coo.../Recipe/302478
I don't as much python as I would like... What are you trying to do?
Sorry, sometimes code just ain't enough.

<snip> code reproduced below </>
It seems vectors can't be passed effectively as parameters to recursive
functions (at least how I'm doing it). Is this true?


Not at all, except that you might use up all of your machine's stack
space. :) Try passing big data structures by constant reference (const&
pronounced "const ref"). Here are a few fixes to try for now.

//beginning

#include <vector>
//#include <iostream.h>

// <iostream.h> is ancient. Use <iostream> instead.
#include <iostream>

using namespace std;

//void looper(vector <vector<int> > nseq, vector<int> comb);

// Passing big objects by value can be really inefficient. Try
// passing by reference instead:

void looper(
vector< vector< int > > const& nseq,
vector< int > const& comb );
vector <vector<int> > master;

// Why the global variable?

int main() {
int n, C;
vector <vector<int> > seq;
vector<int> holder;
cout << "Enter constant: ";
cin >> C;
cout << "Enter n: ";
cin >> n;
//for(i=0; i<=n; i++) {

// You have to declare the type of i.
for(int i=0; i<=n; i++) {

vector <int> tmp;
for(int j=0; j<=C; j++) {
tmp.push_back(j );
}
seq.push_back(t mp);
}
looper(seq, holder);
return 0;
}

//void looper(vector <vector<int> > nseq, vector<int> comb) {

void looper( vector <vector<int> > const& nseq,
vector<int> const& comb) {

if(nseq.size()> 0) {
vector<int> tseq = nseq.at(0);

// You just copied a whole vector. Could be
// expensive.
for(int i=0; i<tseq.size(); i++) {
vector <vector<int> > gseq = nseq;
vector<int> tcomb = comb;

// Once again, these make copies of the
// vectors.

//gseq.erase(0);

// vector<>::erase wants an iterator, not an
// integer.

gseq.erase( gseq.begin( ) );

tcomb.push_back (tseq[i]);
looper(gseq, tcomb);
}
}
else {
master.push_bac k(comb);
}
}

// end
Jul 23 '05 #3
"lugal" <lc****@gmail.c om> wrote in message
news:11******** **************@ f14g2000cwb.goo glegroups.com.. .
This might be more appropriate here. I'm new to C++, coming from a
background in another languages that allowed a similar solution to work
(Python). I wrote the following code in C++ based on the Python code
found here:

http://aspn.activestate.com/ASPN/Coo.../Recipe/302478 .... void looper(vector <vector<int> > nseq, vector<int> comb); First of all, in C++, when you pass parameters by value (as above),
a copy of the whole collection of items is created at each call.
Do get the equivalent of what Python does, you should pass
(large) parameters by reference:
void looper(vector< vector<int> > const& nseq, vector<int> comb);

Then, the efficient C++ equivalent of passing a sub-rage of a
collection, like "seqin[1:]" does in Python, is to pass a pair
if iterators within the collection.

From a quick read of the article, a C++ equivalent of the
"combine" function could be written as follows:
(Warning: quickly typed, not tested)
typedef vector<int> VI;
typedef vector<VI> VVI;

// the recursively called function
void combine( VVI::const_iter ator i_begin
, VVI::const_iter ator i_end
, VI& curBase, VVI& destination )
{
VI const& src = *i_begin;
++i_begin;
curBase.push_ba ck(0); // add placeholder last item
for( VI::const_itera tor scan=src.begin( )
; scan != src.end() ; ++scan )
{
curBase.back() = *scan;
if( i_begin==i_end )
destination.pus h_back( curBase );
else
combine(i_begin ,i_end,curBase, destination);
}
curBase.pop_bac k();
}

// the top-level function
VVI combine( VVI const& src )
{
VVI result;
VI base;
combine( src.begin(), src.end(), base, result );
return result;
}

It seems vectors can't be passed effectively as parameters to recursive
functions (at least how I'm doing it). Is this true?

Yes, at least how you were doing it.
The code above should work better, although it does
leave room for optimization.
I hope this helps,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact form
Jul 23 '05 #4
I think at least one of the arguments to looper is supposed to be an
out-argument, so it needs to be a non-const ref.

Besides, all this copying of sequences is expensive, when you could use
the std::algorithm idiom of pairs of iterators in your recursion. This
is loosely equivalent to passing seq[begin:end] in Python, which
refcounts rather than copies the storage iiuc.

Try this (works for me):
#include <vector>
#include <utility>
#include <iostream>

// might as well make it easy to use different containers for our
// algorithm: now we only need to change one line and the rest should
// still work (if we write it correctly). We're calling the list of
// arguments a Sequence, the output list of combinations can also be a
// Sequence, and the individual tuples in the input, and nested lists
// in the output, can both be 'Tuple's.
//
typedef int ValueT;
typedef std::vector<Val ueT> Tuple;
typedef std::vector<Tup le> Sequence;

// we're going to do this using iterators instead of whole containers,
// so these typedefs will make it easy on the eye
typedef Tuple::const_it erator InputVal;
typedef Sequence::const _iterator InputIter;
typedef std::pair<Input Iter,InputIter> SubSequence;

// note the use of non-const refs for out-parameters. We're passing
// the SubSequence by value, because it is cheap to copy
void looper( const SubSequence& inseq, // = seqin
Sequence& completed, // = listout
Tuple& current ) // = comb
{
if(inseq.first != inseq.second) { // = if seqin:
InputIter first = inseq.first;
const Tuple& curTuple = *first;
SubSequence recSeq(++first, inseq.second);
// calc seqin[1:] in advance, and we just avoided copying
// anything :-)

for(InputVal i = curTuple.begin( ); i != curTuple.end(); ++i) {
// rather than create a new current combination each call,
// we just modify the existing one
current.push_ba ck(*i);
looper(recSeq,c ompleted,curren t);
// ~= rloop(seqin[1:],listout,newcom b)
current.pop_bac k();
}
} else {
// this does make a copy,
// but we've avoided the intermediate ones
completed.push_ back(current);
}
}

// we can provide overloads for convenience here
void looper( const SubSequence& inseq, Sequence& completed )
{
Tuple scratch;
looper(inseq,co mpleted,scratch );
}

void looper( const Sequence& inseq, Sequence& outseq )
{
looper( SubSequence(ins eq.begin(),inse q.end()), outseq );
}

int main()
{
std::cout << "Enter constant tuple size: ";
int tupleSize;
std::cin >> tupleSize;

std::cout << "Enter number of tuples: ";
int numTuples;
std::cin >> numTuples;

Sequence inseq(numTuples );
for(int i=0; i<numTuples; ++i) {
for(int j=0; j<tupleSize; ++j) {
inseq[i].push_back(j);
}
}

Sequence outseq;
looper(inseq,ou tseq);

std::cout << "Output =\n[\n";
for(int k=0; k<outseq.size() ; ++k) {
std::cout << " [ ";
for(int l=0; l<numTuples; ++l) {
std::cout << outseq[k][l] << ", ";
}
std::cout << "],\n";
}
std::cout << "]\n";
}

Jul 23 '05 #5
simont wrote:
I think at least one of the arguments to looper is supposed to be an
out-argument, so it needs to be a non-const ref.

Besides, all this copying of sequences is expensive, when you could use
the std::algorithm idiom of pairs of iterators in your recursion. This
is loosely equivalent to passing seq[begin:end] in Python, which
refcounts rather than copies the storage iiuc.

Try this (works for me):
#include <vector>
#include <utility>
#include <iostream>

// might as well make it easy to use different containers for our
// algorithm: now we only need to change one line and the rest should
// still work (if we write it correctly). We're calling the list of
// arguments a Sequence, the output list of combinations can also be a
// Sequence, and the individual tuples in the input, and nested lists
// in the output, can both be 'Tuple's.
//
typedef int ValueT;
typedef std::vector<Val ueT> Tuple;
typedef std::vector<Tup le> Sequence;
<snip> commented code </>

If the type of the container is to be flexible, it is probably best to
avoid numeric indexing and calls to Sequence::size( ) like those in the
loop below. For example, std::list does not have an overloaded operator
[], and calls to std::list::size () may be O(n).
for(int k=0; k<outseq.size() ; ++k) {
std::cout << " [ ";
for(int l=0; l<numTuples; ++l) {
std::cout << outseq[k][l] << ", ";
}
std::cout << "],\n";
}
std::cout << "]\n";
}

Jul 23 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
49581
by: Pavils Jurjans | last post by:
Hallo, I have been programming for restricted environments where Internet Explorer is a standard, so I haven't stumbled upon this problem until now, when I need to write a DOM-compatible code. The question is about best practices for passing parameters to an event function. I have, say, the following HTML:
3
14946
by: domeceo | last post by:
can anyone tell me why I cannot pass values in a setTimeout function whenever I use this function it says "menu is undefined" after th alert. function imgOff(menu, num) { if (document.images) { document.images.src = eval("mt" +menu+ ".src") } alert("imgOff_hidemenu"); hideMenu=setTimeout('Hide(menu,num)',500);
6
2197
by: fivelitermustang | last post by:
I have two matrices allocated dynamically in both directions: matrix x and matrix v. I want to pass these matrices into a function by reference. What I have written down isn't working... can somebody enlighten me on how I would solve this? Here is what my prototype and my function look like: =====================================================
12
2808
by: Joel | last post by:
Hi all, Forgive me if I've expressed the subject line ill. What I'm trying to do is to call a c++ function given the following: a. A function name. This would be used to fetch a list of function descriptors for the overloaded functions of that name. A function descriptor would contain the address of the function to be called, and a description of the parameters that it must take. b. A list of parameters. This would be compared to the...
20
2137
by: christopher diggins | last post by:
I have heard it is considered good practice to pass function parameters as const& as often as possible, is this true? Is it possible to go overboard? And if so why? Thanks a lot in advance everyone! Christopher Diggins http://www.cdiggins.com
6
1751
by: Adam Hartshorne | last post by:
Hi All, I have the following setup. Two 'std::vector's which i iterate through in a for (iterate through vector1 of types X) { for (iterate through vector2 of types Y) { f(x) }
4
3037
by: Alfred Taylor | last post by:
I essentially need a countif() function for xsl. Something to where I could do countif(node-set, condition). Rather than try to get too extreme, i decided to just write one for my countif() with the condition hardcoded. (this was also my first venture into creating "functions") Pseudo-code is essentially this: Look at the current node and check the condition. If the condition is true, call our function again with an incremented...
39
7663
by: Mike MacSween | last post by:
Just spent a happy 10 mins trying to understand a function I wrote sometime ago. Then remembered that arguments are passed by reference, by default. Does the fact that this slowed me down indicate: a) That I don't know enough b) Passing arguments by ref is bad
5
18220
by: madhu | last post by:
http://msdn2.microsoft.com/en-us/library/fs5a18ce(VS.80).aspx vector <intv1; v1.push_back( 10 ); //adds 10 to the tail v1.push_back( 20 ); //adds 20 to the tail cout << "The size of v1 is " << v1.size( ) << endl; v1.clear( ); //clears the vector I have a few questions:
0
9462
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10046
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9886
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9857
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8723
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7259
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5155
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
3369
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2677
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.