struct method partly changes the values of it's member array cpp - c++

Some information about the overall project:
I have to find if specific nodes remain connected if i start removing the lowest width edges from a graph. I have a struct solve, which has a member array called connected. In a method of this struct , FindConnections I go over some of the edges, from the Kth till the last and see which nodes are connected. The way I keep track of the connected nodes is to have an array that for each node points to the lowest id node it is connected, with the lowest pointing to itself
for example
if nodes 2 5 6 12 are directly connected
connected[2] =connected[5] =connected[6] =connected[12] = 2
so now if 12 and 23 are connected (and 12 is the lowest connection of 23)
connected [23] = 12 and connected[connected[23]] = 2 so i can reach 2 from 23 with recursion
My problem is that after finishing modifying the connected array inside FindConnections, some of the changes are preserved while other not
Here is the code:
void FindConnections(int index)
{
for (int temp, i = index; i < NumberOfPortals; i++)
{
temp = min(first[i], second[i]); // the nodes which edge i connects
connected[first[i]] = temp;
connected[second[i]] = temp;
}
}
which is called by
void seeAllConnections() // this function is for visualization it will not be included
{
for (int i = NumberOfPortals - 1; i >= 0; --i)
{
printf("Only using %d Portals:\n", NumberOfPortals - i);
FindConnections(i);
seeconnected(); // prints connected array
for (int i = 0; i < NumberOfUniverses; i++) //resets connected array
{
connected[i] = i;
}
}
}
In the two first iterations of the for loop in seeAllConnections, everything is good, the edges that are examined are
first second width(irrelevant for now)
6 7 255
26 2 111
11 7 36
in the beginning everyone is connected with himself
in the first one we get the output
(I am placing ** around the values that are changed and !! around the one that was supposed to change but didn't , just so you can see it better, the program prints just the numbers)
Only using 1 Portals:
connected are:
0 1 2 3 4 5 6 7 8 9 10 *7* 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
and we can see that connected[11] = 7 just like we wanted to
in the second one
Only using 2 Portals:
connected are:
0 1 2 3 4 5 6 7 8 9 10 *7* 12 13 14 15 16 17 18 19 20 21 22 23 24 25 *2* 27 28 29
connected[11] =7 just like before
connected[26] = 2 just like we wanted
in the third one
Only using 3 Portals:
connected are:
0 1 2 3 4 5 6 !7! 8 9 10 *7* 12 13 14 15 16 17 18 19 20 21 22 23 24 25 *2* 27 28 29
connected [7] = 7 , not 6
moreover, when i use gdb, inside the FindConnections loop, connected[7] = 6 like we wanted
(gdb) print first[i]
$10 = 6
(gdb) print second[i]
$11 = 7
(gdb) print connected[first[i]]
$12 = 6
(gdb) print connected[second[i]]
$13 = 6
but when it exits the function and returns to seeAllConnected
connected[7] = 7
What Am I doing wrong? how can the first two changes be preserved form the same function in the same struct in the same loop, while the second one isn't?
Also after every time I call FindConnections I reset the array to it's original values, so the changes couldn't have been preserved from before
Thank you in advance

I found out what was wrong, as it was a reverse iteration connected[7] got overwritten.

Related

C++ : For loop not iterating designated number of times (1 iteration less) [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 6 years ago.
Improve this question
I have a for loop and a variable C.
The loop begins at 0 and is expected to run C times but actually it runs C-1 times.
Here is my code :
vector<int> v(1000) //Allocated globally
int M, S, C;
cin>>M>>S>>C;
//cout<<M<<" "<<S<<" "<<C;
int fi=0, la=0;
for(int i=0; i<C; i++)
{
int f;
cin>>f;
if(i==0l){ fi = f;}
v[f] = f;
cout<<i<<" "<<f<<" "<<v[f]<<endl;
if(i==C-1){ la = f;}
}
This is my test case -
3 27 16
2
3
5
6
8
9
10
13
14
15
16
19
20
21
22
27
Output by Xcode :
0 2 2
1 3 3
2 5 5
3 6 6
4 8 8
5 9 9
6 10 10
7 13 13
8 14 14
9 15 15
10 16 16
11 19 19
12 20 20
13 21 21
14 22 22
I use Xcode on Mac if it makes a difference.
The variables fi and la are to find the first and the last element of the list.
I want to know what is wrong in my code for the for loop and why is it not iterating C times.
Thanks
Your loop is iterating C times. This is the classic Zero-Based Numbering issue.
Let me explain using your example where C is 16 and a numbered list:
2
3
5
6
8
9
10
13
14
15
16
19
20
21
22
27
So you see your lopp did iterate 16 times. To go from 0 to 16 would have actually been iterating one more time, so 17 times.

Print matrix spirally from any point and using given direction

How can we print given matrix spirally from any point and specified direction?
for example
if given matrix is
21 22 23 24 25
20 7 8 9 10
19 6 1 2 11
18 5 4 3 12
17 16 15 14 13
let current position be pointing to 1 and required direction is clockwise
correct output should be 1 2 3 4 5 6 .... upto 25.
I am looking for logic and code in C or C++

adjusting the distance between numbers on console

I've made a program to create the pascal's triangle. the program takes number of rows as input and displays the triangle on the console. I've used the setw() function to set the distance between numbers. it's of for unit single digits but when the numbers get greater than 10,the width is not being adjusted properly,right now I've :
if(P<10){
std::cout << P ;
std::cout <<std::setw(2);
}
if(P>=10){
std::cout<<std::setw(3) << P ;
std::cout<<std::setw(2);
}
here's the ouput from the console:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84126126 84 36 9 110
I want it to appear like a proper triangle,Could someone help me out please???
If you read e.g. this reference of std::setw you will see
The width property of the stream will be reset to zero (meaning "unspecified") if any of the following functions are called
And then goes on to list basically all output operators.
This means that when you do
std::cout <<std::setw(2);
the width will only be set for the next output operation. If you do any kind of output after that the width will be reset to zero.

Pickuping the Common 1d sequence in 1d array's?

How to pick the best uniformed 1d array from the 2d arrays ?
I have two 2d array of : 11 x 10
Example :
4 8 12 12 12 14 16 18 4 1 0
5 7 11 12 13 11 15 18 3 2 1
8 3 12 14 18 19 20 21 8 5 4 ,
8 2 11 12 17 17 19 20 7 4 3 ,
4 7 11 11 11 15 17 19 5 1 1 ,
3 8 11 13 11 15 14 17 4 1 0 ,
4 7 12 13 13 14 16 19 3 1 1 ,
5 9 11 12 13 15 17 19 5 0 1 ,
9 7 25 22 24 18 23 17 3 3 3 ,
4 8 13 13 13 15 17 17 5 2 0 ,
here we have 2d arrays of size 11x10 - Need to analysis and have to find out the common 1d array which has common like.
find the best closing number and its difference- and keep doing for all the corresponding columns in an array .
below answer should be like - finding the corresponding very column and comparing with the next row column - if it has some difference below ( 5 ) take the both column of two rows are same and process for next column of the same row..process untill finding the 1 row where it has at least nearby matches of 5
4 8 11 12 13 13 15 18 4 1 0
why don't you do something like this
int[] count(int[][] array)
int result[11];
for(int x = o; x<= 11;x++)
{
int temp[10];
for(int y = o; y<= 10;y++)
{
temp[y] = array[y][x];
}
result[x] = getHighest(temp);
}
return result;
}
int getHighest(int[] array)
{
int size = array.length;
int[size][1] temp;
for(int x; x<= size;x++)
{
int z = array[x];
temp[z][0]++;
}
int highest = -1;
for(int z; z<= size;z++)
{
int z = array[x];
int h = temp[z][0];
if(h > highest)
{
highest = h;
}
}
return highest;
}
Something like this, but my C++ has gotten a bit of rusty so sorry if there are any mistakes.

problem with updating a map by removing some keys and also some elements

I have a map. lets say map<int, vector<int> > mymap1.
I want to update mymap1 by deleting some “keys” and also removing unwanted “elements” from the vector part of the selected keys. The “key’ or the “element” going to be deleted is given from another vector, known as “mylabel”. Actually, What I need to remain in my map is the values whose label is equal to 1. (At the end, keys must have the elements whose label are 1 only.)
I have implemented this (see code below), but got some compiler errors.
map<int, vector<int> > mymap1;
map<int, vector<int> >::iterator map1;
for (map1=mymap1.begin();map1!=mymap1.end();map1++){
int key = map1->first;
if (mylabel[key].Label() != 1){ mymap1.erase(key);
}
else{
vector<int> &myvec = map1->second;
for (vector<int>::iterator rn=myvec.begin(); rn!=myvec.end(); rn++){
if (mylabel[*rn].Label() != 1) myvec.erase(myvec.begin()+(*rn));
}
}
}
for you to get an idea, i am showing some example of my map.
0 1 2 6 10
1 0 2 4 3 6
2 0 1 3 5 8
3 1 2 4 5 7
4 1 3 6 7
5 2 3 8 7 9
6 1 0 7 4
7 6 4 3 5 9 11 10 13 12
8 2 5 9 11 18 15 19 20 22
9 5 7 11 8
10 0 7 14 16
11 9 7 8 13
12 7 13 14
13 7 12 11 14 15
14 12 10 16 13 15 17
15 13 14 8 17 19
16 14 10 17 21
17 14 16 15 21 18
18 8 20 19 17 26 27
19 8 15 18
20 8 18
21 16 17 23 24
22 8
23 25 21 24 26
24 23 21
25 23 26
26 23 25 18
27 18 28
28 27
if i show you my mylabel, it is as follows.
for(int c=0;c<mylabel.size();c++){
cout<<c<<" : "<<"label "<<mylabel[c].Label()<<endl;
}
0 : label 0
1 : label 0
2 : label 0
3 : label 0
4 : label 0
5 : label 1
6 : label 0
7 : label 1
8 : label 0
9 : label 1
10 : label 0
11 : label 1
12 : label 0
13 : label 0
14 : label 1
15 : label 1
16 : label 1
17 : label 1
18 : label 0
19 : label 0
20 : label 0
21 : label 1
22 : label 0
23 : label 0
24 : label 0
25 : label 1
26 : label 1
27 : label 0
28 : label 0
When I am deactivating the else part and running above code I got an output. But, I want to say you that it is a wrong result. I am getting extra keys that should be deleted. I can’t figure out why I got this fault result.
if i show the list of keys what i got,
5
7
9
11
14
15
16
17
20 - wrong
21
24 - wrong
25
26
could you please help me to rectify my code in order to get my modified map. thanks in advance.
Your erasing logic is wrong, and you end up using invalid iterators. (You're literally pulling the rug out from under your feet if you erase an iterator and then keep using that iterator.)
For node-based containers (list, map, set, unordered), you typically erase as follows:
for (auto it = c.begin(); it != c.end(); )
{
if (must_delete(*it)) // or it->first
{
c.erase(it++); // advance first, then erase previous
}
else
{
++it;
}
}
(This patterns is my favourite justification for the post-fix increment operator.)
For contiguous containers (vector, deque), erasing one element at a time is inefficient, because it incurs repeated moves. The preferred idiom here is "remove/erase", but it requires that you supply a suitable predicate if you don't just want to remove straight by element value. Here's an example with lambdas, for brevity:
std::vector<int> v;
v.erase(std::remove_if(v.begin(), v.end(),
[](int n)->bool{return some_criterion(n);}),
v.end());
In your situation, you could write the lambda as [mylabel&](n)->bool{ return mylabel[n].Label() != 1; }; or write a traditional predicate object if you don't have lambdas:
struct LabelFinder
{
LabelFinder(const LabelVector & lv) : label(lv) { }
inline bool operator()(int n) const
{
return label[n].Label() != 1;
}
private:
const LabelVector & label;
};
Now use:
v.erase(std::remove_if(v.begin(), v.end(), LabelFinder(mylabel)), v.end());
The problem is in the for loop. std::vector<T>::erase() returns iterator to the new position followed by the erased item. So the loop should be written as:
for (vector<int>::iterator rn=myvec.begin(); rn!=myvec.end();)
{
if (mylabel[*rn].Label() != 1)
rn = myvec.erase(rn);
else
++rn;
}
Read the doc:
vector::erase()
By the way, I doubt on this:
rn = myvec.erase(myvec.begin()+(*rn));
Vs
rn = myvec.erase(rn);
Are you sure you want the first one?
An idiomatic way to erase elements which are not equal to one is this:
//Define this function
bool isNotOne(int n) { return n != 1; }
//then do this instead of writing manual loop
myvec.erase( remove_if(myvec.begin(), myvec.end(), isNotOne), myvec.end() );
It's called :
Erase-Remove Idiom