vector array function question

came back with other question about vector array function I am writing. I need some hints on how to return the number next to the interesting number I am looking for??

cull's job is to call your interesting function to create and return an array
that consists of all the interesting elements of v together will all the
elements of v that are next to interesting numbers.
For example, if your interesting function returns true for numbers that are
multiples of 10, and v held {9, 5, 10, 20, 8, 47, 63, 1, 70},
then cull would return a vector that held {5, 10, 20, 8, 1, 70}
Your cull function should work properly for any interesting function,




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool interesting(unsigned n)
{
	return (n % 10 == 0);
}

vector<unsigned> cull(const vector<unsigned> & v)
{
	vector<unsigned> x;
	unsigned temp;
	for (unsigned i = 0; i < v.size(); i++)
	{
		if (interesting(v[i]))
			x.push_back(v[i]);
	}
	return x;
}


obviously this only output 10,20,70
do I need to use two loops or some other variables ??
Please any hints
For example, if your interesting function returns true for numbers that are
multiples of 10
then cull would return a vector that held {5, 10, 20, 8, 1, 70}


Is 8 a multiple of 10.??

To have a closer ouput, i looked at it as multiple OR factor of 10.
1
2
3
4
if(n >= 10)
   return(n%10 == 0)
else
   return (10%n == 0)


Even so, where does 8 belong??
Aside from v[i], you should check both if v[i+1] and v[i-1] are interesting.
Note that when your current index (i) is 0 you should not check v[i-1] and when it size()-1 you should not check v[i+1] (or you will have out of range access).
return an array
that consists of all the interesting elements of v together will all the
elements of v that are next to interesting numbers.


this is my main point
Last edited on
Oh sorry, i forgot that part. hihi..
This should do the job.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

vector<unsigned> cull(const vector<unsigned> & vec)
{
	vector<unsigned> x;
	for(size_t i = 0 ;i < vec.size(); i++)
	{
		if(interesting(vec.at(i)))
		{
			x.push_back(vec.at(i));
			if(i > 0 && i < vec.size() - 1)
			{
				if(intereting(vec.at(i-1)))
					x.push_back(vec.at(i -1));
				if(interesting(vec.at(i+1)))
					x.push_back(vec.at(i+1));
			}
		}
	}
	vector<unsigned>::iterator it;
	it = unique(x.begin(),x.end());
	x.resize(distance(x.begin(),it));
return x;
}

@shadowCODE, your code will fail on 1, 10, 3 array.
thanks @shadowCODE for your help but I am not used to write codes the way your.

anyway I understood the idea but the implementation kind of tricky
@MiiNippa
It works for your input. I realized i didnt need to check if(interesting()) for the elements besides the interesting ones.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <iterator>
#include <algorithm>
#include <ctime>
#include <vector>
using namespace std;

bool interesting(unsigned n)
{
	return (n % 10 == 0);
}

vector<unsigned> cull(const vector<unsigned> & vec)
{
	vector<unsigned> x;
	for(size_t i = 0 ;i < vec.size(); i++)
	{
		if(interesting(vec.at(i)))
		{
			x.push_back(vec.at(i));
			if(i > 0 && i < vec.size() - 1)
			{
					x.push_back(vec.at(i-1));
					x.push_back(vec.at(i+1));
			}
		}
	}
	vector<unsigned>::iterator it;
	it = unique(x.begin(),x.end());
	x.resize(distance(x.begin(),it));
return x;
}
int main()
{
	vector<unsigned> vec;
	vec.push_back(1);
	vec.push_back(10);
	vec.push_back(3);

	vector<unsigned> test;
	test = cull(vec);

	copy(test.begin(),test.end(),ostream_iterator<unsigned>(cout," "));
	cout<<endl;
	system("pause");
	return 0;
}

10 1 3 
Last edited on
1) It reorders elements.
2) On vector 3 10 3 20 it skips second 3

And use more common and understood erase-remove idiom:
1
2
3
4
//vector<unsigned>::iterator it;
//it = unique(x.begin(),x.end());
//x.resize(distance(x.begin(),it));
x.erase(unique(x.begin(), x.end()), x.end());
@MiiNippa
is there a difference between,
1
2
3
vector<unsigned>::iterator it;
it = unique(x.begin(),x.end());
x.resize(distance(x.begin(),it));

AND
x.erase(unique(x.begin(), x.end()), x.end());
??

Also, the for loop goes through every element in the vector. I dont know why you say it skips the second 3 in
3 10 3 20 ..

Also made this change:
1
2
3
4
5
6
7
8
if(interesting(vec.at(i)))
{
    x.push_back(vec.at(i));
    if(i > 0)
        x.push_back(vec.at(i-1));
    if(i < vec.size() - 1)
	x.push_back(vec.at(i+1));
}
Last edited on
is there a difference between,
No, aside from that second one is more common form.

I dont know why you say it skips the second 3 in
Yeah, faulty vectors is not that predictable, but 3, 10, 3 still skips: http://ideone.com/mIfaT4

Also made this change
Good, now you need only one change and get rid of unique().
@MiiNipaa
I think i have fixed everything and gotten rid of unique
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
vector<unsigned> cull(const vector<unsigned> & vec)
{
	vector<unsigned> x;
	for(size_t i = 0 ;i < vec.size(); i++)
	{
		if(interesting(vec.at(i)))
		{
			if(i > 0)
				if(!binary_search(x.begin(),x.end(),vec.at(i-1)))
					x.push_back(vec.at(i-1));

			if(!binary_search(x.begin(),x.end(),vec.at(i)))
				x.push_back(vec.at(i));

			if(i < vec.size() - 1)
				x.push_back(vec.at(i+1));
		}
	}
	return x;
}


I thought i had solved this problem from the beginning. Thank you
Last edited on
1) binary search works only for sorted sequences.
2) The aim is to allow repeating variables and you are trying to explicitely prohibit this
3) if(i > 0) and if(i < vec.size() - 1) should not be nested
4) Do not use checked access if all indices are guaranteed to fall into vector.

Now you have duplicates and losses
http://ideone.com/Du6I6e

Just think, what conditions should be true for number to be pushed into resulting vector?
Last edited on
Thank you guys!

this what I am getting

10 5 20 20 10 8 70 1


10 and 20 duplicated

seems hard problem to me
It is not hard if you do it straigtforward way:

You need to save element if:
* It is interesting  
      or  
* Previous element is interesting  
      or  
* Next element is interesting  

So you can write:
1
2
3
4
5
6
bool save =
    interesting(in[ i ])
        ||
    interesting(in[i-1])
        ||
    interesting(in[i+1]);
We still need to deal with possible out of bound access. So this is a good place to use ternary operator: (i>0 ? interesting(in[i-1]):false) — if i == 0 then apparently previous value should not be counted as interesting

So our condition looks like:
1
2
3
bool save =    interesting(in[ i ])       ||
      (i>0   ? interesting(in[i-1]):false)||
      (i<sz-1? interesting(in[i+1]):false);

Alternative approach (without ternary operator):
1
2
3
4
5
bool save = interesting(in[ i ]);
if(i>0)
    save = save || interesting[i-1];
if(i<sz-1)
    save = save || interesting(in[i+1]);


Then you just need to do:
1
2
if(save)
    x.push_back(in[i]);
Last edited on
Thanks, I hope this will work even if the interesting function is dealing with different thing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
vector<unsigned> cull(const vector<unsigned> & v)
{
	vector<unsigned> x;
	bool save;
	
	for (unsigned i = 0; i < v.size(); i++)
	{
		 	

			save = interesting(v[i]);
			if (i>0)
				save = save || interesting(v[i - 1]);
			if (i<v.size() - 1)
				save = save || interesting(v[i + 1]);

		if (save)
			x.push_back(v[i]);
	}
	return x;
}
Topic archived. No new replies allowed.