Having a logical issue with recursion-based N-nested for loops - c++

I've searched and found similar problems, but they all didn't seem to fit with mine. Basically, I need to write a recursive function that nests a loop N times and prints everything only on the very last loop. If you can find another solution to the problem, that would be great.
0 = *
1 = +
2 = ABC
3 = DEF
...
8 = STU
9 = VWXYZ
Here is the full code: http://pastebin.com/2YdQ693N
Here is a hard-coded N=3 example:
//sout is a vector<string>
for(int i = 0; i < sout[0].size(); i++)
{
for(int j = 0; j < sout[1].size(); j++)
{
for(int k = 0; k < sout[2].size(); k++)
{
cout << sout[0][i] << sout[1][j] << sout[2][k] << endl;
}
}
}
the following output of this particular example (input is "123"):
+AD
+AE
+AF
+BD
+BE
+BF
+CD
+CE
+CF
The closest I got before coming here was a recursion function similar to this one here: http://v2.cplusplus.com/forum/beginner/68434/ but I couldn't get it to work for my case.
I need the indexes to go in this type of order:
000
001
002
010
011
012
020
021
022
except the length has to be variable (and therefore height as well).
Here is my recursion function I've been trying so far:
void recurseLoop(const vector<string>& sout, int numLoops)
{
if(numLoops > 0)
{
for(int i = 0; i < sout[1].size(); i++)
{
//cout << i;
recurseLoop(sout, numLoops - 1);
}
}
else
{
//cout << endl;
return;
}
}
However the result that 'i' gives is pretty much unintelligible and I'm having trouble getting the correct structure of loops/if statements to get this to work. Any help is appreciated!

void recursion(int N, const vector<string>&sout, vector<int>&index, int I=0)
{
if(I<N-1)
for(index[I]=0; index[I]<sout[I].size(); index[I]++)
recursion(N,sout,index,I+1);
else if(I==N-1)
for(index[I]=0; index[I]<sout[I].size(); index[I]++) {
for(int k=0; k<N; ++k)
std::cout << sout[k][index[k]];
std::cout << std::endl;
}
}
void loop_N_times(const vector<string>&sout)
{
std::vector<int> index(sout.size());
recursion(sout.size(),sout,index,0);
}

Why are you always use sout[1] in recursion? It probably should be something like
for (int i = 0; i < sout[sout.size() - numLoops].size(); ++i)

Related

C++ delete duplicates from cstring [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a c-string that looks something like ABBBCACACACBA and I'm supposed to create a function that deletes the duplicate characters so I end up with ABC. I created a nested for loop that replaces every letter that matches the letter in the outer loop with a \0 and increments a counter that keeps track of the repeats. I'm getting -1 as the amount of repeats that should be documented, and from checking it spits out ABBC instead of ABC. I'm stumped, any ideas?
for (int i = 0; i < SIZE; i++)
{
for (int j = i + 1; j < SIZE; j++)
{
if (letter[i] == letter[j])
{
letter[j] = '\0';
repeatCounter++;
}
}
}
It is not enough to just replace duplicates with '\0', you have to actually remove them from the string and shift the remaining characters down. Try something more like this:
int size = SIZE, i = 0;
while (i < size)
{
int j = i + 1;
while (j < size)
{
if (letter[j] == letter[i])
{
for (int k = j + 1; k < size; k++)
{
letter[k-1] = letter[k];
}
letter[--size] = '\0';
repeatCounter++;
continue;
}
j++;
}
i++;
}
Live Demo
Here's a simple example which does what you want. It uses std::string to store the output. You can copy-n-paste the code here to test and run. Look into using std::string as it has functions which will make your life easy.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string input("ABBBCACACACBA");
string output;
for(size_t i = 0; i < input.size(); i++)
{
if(output.find(input[i]) == string::npos)
{
output += input[i];
}
}
cout << "Input: " << input << endl;
cout << "Output: " << output << endl;
return 0;
}

adjacency list error with list

Basically i generated a adj_matrix and i want to make an adj_list from the adj_matrix...However I keep getting an error saying "no match for call..."
i tried it without aPair i still get the same error i can't seem to figure out what my problem is. Can anyone tell me why list isn't working? the list is at the very end of the code
int **gen_random_graph(int n)
{
srand(time(0));
int **adj_matrix = new int*[n];
for(int i = 0; i < n; i++)
{
for (int j = i; j < n; j++) //generating a N x N matrix based on the # of vertex input
{
adj_matrix[i] = new int[n];
}
}
for(int u = 0; u < n; u++)
{
for (int v = u; v < n; v++)
{
bool edgeOrNot = rand() % 2; //decide whether it has an edge or not
adj_matrix[u][v] = adj_matrix[v][u] = edgeOrNot;
if(adj_matrix[u][v] == true)
{
adj_matrix[v][u] = true;
if(u == v) //We can't have i = j in an undirected graph so we set it to false
{
adj_matrix[u][v] = -1;
}
}
else //if adj_matrix[u][v] is false set the symmetry to be false
{
adj_matrix[v][u] = adj_matrix[u][v] = -1;
}
}
}
for(int i = 0; i < n; i++)
{
for(int j = i; j < n; j++) //create the N x N with edges and sets the weight between the edge randomly
{
if(adj_matrix[i][j] == true)
{
int weight = rand() % 10 + 1;
adj_matrix[i][j] = adj_matrix[j][i] = weight;
cout << " ( " << i << "," << j << " ) " << "weight: " << adj_matrix[i][j] << endl;
}
}
}
for(int i = 0; i < n; i++)
{
vector<int> adj_list;
for(int j = i; j < n; j++)
{
if(adj_matrix[i][j] > 0)
{
int weight = adj_matrix[i][j];
adj_list.push_back(j);
cout << adj_list[i] << " " << endl;
}
}
}
print(n,adj_matrix);
return (adj_matrix);
}
I see that adj_list is not callable, so your code there is broken. There are a couple simple solutions to that. Taking a look at these docs, you may simply either access listObj.front() and listObj.back() OR you may also just create an iterator using listObj.begin() and iterating over the two elements (which may be desirable if you ever decide to put more than two elements in the list). See this tutorial for a simple example on creating an iterator for a list, in the code snippet right above the summary.
Note, here, your list object which I called listObj for simplicity/abstraction would simply be adj_matrix[i][j] in that bottom loop. That should fix your syntax error.
Also, aside from the syntax of your code, I don't get why you're trying to push weights to a list, then you're printing out and returning the adjacency matrix. I also don't get why you would use lists of pair objects when it seems like you only want to push integer weights onto it. For that, you can use a simple vector of integers (i.e.: vector <int> adj_list;)... or even simpler, you could use a simple array of integers... rather than using a vector of lists of pairs.
EDIT: After running the code locally and taking a look at the values, I realized the issue a bug in the OP's output was simply that he was using "true" in C++ in place of an integer, which was creating a bug, as explained in this SO post. The OP also has a further design decision to make where adjacency lists are concerned. More on what an adjacency list is, conceptually, found on Wikipedia.

Can I set up this recursion in a smarter way to avoid calls to an expensive function?

Suppose I have a Matrix class Matrix, and a recursive function that does some computation using it. In particular, heavy_computation is a really expensive function and I'd like to avoid calling it whenever possible.
bool heavy_computation(const Matrix& m)
{
// Expensive stuff ...
}
The do_things function is a top level function the user calls to kick off recursion.
void do_things(const Matrix& m, std::vector<int>& collection)
{
std::vector<int> expensive_result;
if(!heavy_computation(m, expensive_result))
{
return;
}
std::cout << "New result = { ";
for(int i : expensive_result)
std::cout << i << " ";
std::cout << "}\n";
for(int i : expensive_result)
{
collection.emplace_back(i);
}
for(int j = 0; j < 3; ++j)
{
explore(m, j, expensive_result, collection);
}
}
The top level function delegates work to the following explore function.
void explore(
const Matrix& m,
int j,
const std::vector<int>& expensive_result,
std::vector<int>& collection)
{
std::cout << "j = " << j << "\n";
// Compute something based on expensive_result.
Matrix new_matrix = ...;
std::vector<int> new_expensive_result;
heavy_computation(new_matrix , new_expensive_result);
if (!new_expensive_result.empty())
{
std::cout << "New result = { ";
for (int i : new_expensive_result)
std::cout << i << " ";
std::cout << "}\n";
for (int i : new_expensive_result)
{
collection.emplace_back(i);
}
}
for (int i = 0; i < 3; ++i)
{
if (!new_expensive_result.empty())
{
explore(new_matrix, i, expensive_result, collection);
}
}
}
I think I have stared at the structure of the recursion for too long; it could most probably be organized in a more clever way to avoid unnecessary calls to heavy_computation. For example, consider the following output the program gives:
New result = { 9 7 8 }
j = 0
New result = { 5 0 6 }
j = 0
j = 1
j = 2
New result = { 3 1 0 }
j = 0
j = 1
j = 2
j = 1 <--- Oh no, { 5 0 6 } will be recomputed again?!
New result = { 5 0 6 }
j = 0
j = 1
j = 2
New result = { 3 1 0 }
j = 0
j = 1
j = 2
j = 2
New result = { 5 0 6 }
j = 0
j = 1
j = 2
If I understand correctly, the problem here is that as explore returns, heavy_computation can be called again (and of course it'll return the same answer again as it's deterministic). Basically, a branch of explore will be killed if heavy_computation gives false, otherwise the recursion advances deeper. Is there a way to set up do_things and explore so that unnecessary calls to the expensive function are avoided?
When compared to the output, I guess 3 calls to the expensive function should suffice as we don't have any more unique answers.
First of all, there are some things you can improve in the code to make it easier to read and maintain. Why are you passing j to the explore function? You only use it for printing, so just do that before calling the function.
Second, this
for (int i : new_expensive_result)
{
collection.emplace_back(i);
}
is the same (except slower) as
collection.insert(collection.end(),
new_expensive_result.begin(), new_expensive_result.end());
Third, there is a lot of code duplication between your two functions. You should have removed that before posting your code here.
Solving your problem is quite straightforward, really. First, split the explore function into two functions: one containing the code up to and including the call to heavy_computation, and one for the rest. The recursive call will now consist of two calls, where you have to pass some output of the first function to the second. Something like
for (int i = 0; i < 3; ++i)
{
if (!new_expensive_result.empty())
{
std::cout << "j = " << i << "\n";
Matrix matrix_result;
std::vector<int> vector_result;
explore1(new_matrix, expensive_result, matrix_result, vector_result);
explore2(new_matrix, expensive_result, matrix_result, vector_result, collection);
}
}
Now it is obvious that you can lift the call to explore1 (which calls heavy_computation) out of the loop.

how can I work with the last element of iterations

for(int t(0); t < 10;++t) { cout<<t<<endl;}
I'm just biginer in C++, and want to know how can I take the last elemnt of my "cout...."; in this case my laste element is 9
thx for help ;)
int c = 0;
for(int t = 0; t<10; t++)
{
c = t;
}
cout<<c;
This might be what you are looking for I am not sure I understand your question properly though.The variable c should hold the last element of t when the loop ends.
You can extract int t from the for loop :
int t;
for (t = 0; t < 10; ++t)
{
cout << t << endl;
}
int t = 9;
cout << t << endl;
Now you have the last element, #9.
ghagha, in C++ the ranges are run from 0 to n-1, in your example you have a range of 0 to < 10 hence 0 to 9, therefore your last element is 9. But as I said you can do any range as n-1 for the last element, provided that it follows normal conventions (it is possible to have a range from 1 to n if you code it that way)
It is not clear what you want but in any case your loop contains a bug. Instead of
for(int t(0); t < 10; t) { cout<<t<<endl;}
should be
for(int t(0); t < 10; t++) { cout<<t<<endl;}
that is variable t has to be incremented.
One simple way -
int t = 0;
for (; t < 10; ++t)
cout << t << ;
Tough the correct way to do it will be (one variable should not have two meanings, i.e 1. last element, 2. iterator context) -
int last_element;
for (int t = 0; t < 10; ++t;
{
cout << t << ;
last_element = t;
}

Filling a Two Dimensional array with random numbers in C++

I am making a program that inserts a two dimensional array with random integers and locates the highest value to display it and it's coordinates in the array. I am using three files. utils.h, utils.cpp, and main.cpp. My program displays an array but it is not correct and I cannot figure out why despite all my research. Any help would be appreciated. This is a college assignment and I know that my professor wants main and utils.h left as is so the only thing I can change is utils.cpp. Thank you for your time.
#include "utils.h"
void fillTable(int table[ROW_COL_SIZE][ROW_COL_SIZE]) {
for(int i = 0; i < ROW_COL_SIZE; i++) {
for(int c = 0; c < ROW_COL_SIZE; c++) {
cout << rand() % table[i][c];
}
}
}
void findLargest(int table[ROW_COL_SIZE][ROW_COL_SIZE], int& largestRow,
int& largestCol) {
largestRow = 0;
largestCol = 0;
for ( int i = 0; i < ROW_COL_SIZE; i++) {
for ( int j = 0; j < ROW_COL_SIZE; j++) {
if(table[i][j] > table[largestRow][largestCol]) {
largestRow = i;
largestCol = j;
}
}
}
}
void displayTable(int table[ROW_COL_SIZE][ROW_COL_SIZE]) {
for (int i = 0; i < 10; i++) {
for ( int j = 0; j < 10; j++) {
cout << table[i][j];
}
}
}
This is my output I am getting.
55302337713078127332504421405961229072248303443307961481223132483391855019110600
92808812679236602328231529150663269913935376911094217591887215022974011255316512
71103276228950168692675422850260269511370054042617128509148242205517590190271332
93168530667935211606208729747118402681321223203422069312038223266476231187148148
05966618422064721159313592422312213211891498452701498229001417726265175102184575
4298481247015001631326472115171254718059341323252489617888241851323216308-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460-858993460-858993460-858993460-858993460-858993
460-858993460-858993460-858993460The largest value located at [0] [0] is: -85899
3460
Press any key to continue . . .
Should fillTable fill table? Currently it does not - it only prints to cout. Therefore, table appears to remain uninitialized.
So, in fillTable, instead of:
cout << rand() % table[i][c];
You probably want something like:
table[i][c] = rand();
In fillTable you should use something like:
table[i][c] = rand() % MAX_VALUE; // MAX_VALUE is the largest value +1 you want to generate
cout << table[i][c] << " ";
(Note the whitespace to separate numbers, you might also want to insert a cout << endl; after each row. But I'm not sure if fillTable should also print out the values?)
Also the displayTable function only prints the first ten lines/columns (but this might be intentional?)
You are just making the random number output and not inserting in it.
do it like this
table [i][c] = rand () % table [i][c] ;
PLus you are getting a garbage value when you find the largest value because there is no actual value stored in the array.