Display Vector elements in a reverse order - c++

I have two questions but they are interlinked.:
part:a->
I have been trying to display the elements of vector in reverse order. But nothing is working. I have used iterotar like;
for (it=vec.end(); it!=vec.begin(); --it){
// it is iterator not reverse_iterator.
// do work
}
P.S I am not much familiar with iterators. I have used them for the first time today to
display elem in reverse order.
also tried;
for (int i=vec.size(); i!=0; i--){
//display
}
No matter what I do it always display the elem in same order as they are present i.e not in the reverse order.
part_b->
Is there any way that I can store the output of a recursive function direct into a vector. like the code is:
I know this does not work. I have tried but just giving you an idea
what I am upto.
#include <iostream>
using namespace std;
#include "vector"
int func(int num);
vector <int> vec;
int main() {
int num=34;
// I know this would not work. But is there any possibilitiy that
// I can store the output in a vector.
vec = binary(num);
// trying to display the vector.
for (int i=vec.size();i!=0;i--) {
cout<<vec[i]<<" ";
} // not working for reverse display.
} //main.
int func(int num) {
if (num==1) {
//vec.push_back(1);
return 1;
}
else if(num==0) {
//vec.push_back(0);
return 0;
}
else {
//vec.push_back(input%2);
return binary(input/2);
}
} //func.
I hope you do unnderstand the question. if I am able to do the part b the there is no need to reverse the elem of the vector.

The standard solution uses reverse iterators:
for (auto it = v.rbegin(); it != v.rend(); ++it)
{
if (it != v.rbegin()) { std::cout << ' '; }
std::cout << *it;
}
Alternatively, you can use indices, but keep the "reversal" idiom and increment the index:
for (std::size_t i = 0; i != v.size(); ++i)
{
if (i != 0) { std::cout << ' '; }
std::cout << v[v.size() - i - 1];
}
Note that reverse iterators are literally just doing something very similar to the explicit loop under the hood. In particular, the base() member function of a reverse iterator gives you the corresponding ordinary iterator offset by one, just as we have a - 1 in the index computation. (E.g. rbegin() is just end() under the hood, but decrements by one upon dereferencing.)

Use reverse iterators:
for (auto it = vec.crend(); it != vec.crbegin(); ++it) {
std::cout << *it << ' ';
}
std::cout << '\n';

Part A
Assuming you haven't got access to C++11:
vector<int>::const_reverse_iterator it;
for (it=vec.rbegin(); it!=vec.rend(); ++it)
{
// do work
}
Part B
It looks very much like you're trying to display a number in binary. Unfortunately the standard flags on ostream only allow hex, decimal or octal as far as I'm aware, but can I suggest a simpler way of doing this?
#include <bitset>
bitset< sizeof(int) << 3 > b(34);
cout << b << endl;
Which gives:
00000000000000000000000000100010
The rather ugly looking sizeof(int) << 3 is just a way of getting the size of an int in bits to avoid truncation.

I wrote little program which may help. Maybe your vector is empty?
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
vector<int> vec;
vec.insert(vec.begin(), 1, 1);
vec.insert(vec.begin(), 1, 2);
vec.insert(vec.begin(), 1, 3);
vector<int>::iterator i;
for (i = vec.end(); i != vec.begin(); --i)
{
cout << *i;
}
cout << *i;
return 0;
}

Related

Prevent memory allocation in recursive combination generation

(Sorry about the title, it's not the best descriptive)
I am playing with graph theory, and generating all possible combinations of a given set of input numbers. Given the input set {2,3,4}, my possible combinations (of which there are 3!), are:
The following recursive solution works, but I don't like the fact that I have to "copy" the input vector in order to "remove" the element that represents the node I am following in order to prevent including it for output again. Elements I am going to output are stored in vecValues whereas the elements I can currently choose from are stored in vecInput:
void OutputCombos(vector<int>& vecInput, vector<int>& vecValues)
{
// When hit 0 input size, output.
if (vecInput.size() == 0)
{
for (int i : vecValues) cout << i << " ";
cout << endl;
}
size_t nSize = vecInput.size();
for (vector<int>::iterator iter = begin(vecInput); iter != end(vecInput); ++iter)
{
auto vecCopy = vecInput;
vecCopy.erase(find(begin(vecCopy), end(vecCopy), *iter));
vecValues.push_back(*iter);
OutputCombos(vecCopy, vecValues);
vecValues.pop_back();
}
}
void OutputCombos(vector<int>& vecInput)
{
vector<int> vecValues;
OutputCombos(vecInput, vecValues);
}
int main()
{
vector<int> vecInput{ 2,3,4 };
OutputCombos(vecInput);
return 0;
}
As expected from my state space tree, the output is
2 3 4
2 4 3
3 2 4
3 4 2
4 2 3
4 3 2
How can I get around this without having to make a copy of the vector for each recursive call please?
You could always just use std::next_permutation from <algorithm>
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> input {2, 3, 4};
do {
for (auto i : input) std::cout << i << " ";
std::cout << std::endl;
} while(std::next_permutation(input.begin(), input.end()));
return 0;
}
This gives you the same output. You might want to check out a possible implementation of next_permutation, which involves swaps within the vector rather than copying the vector several times.
I think this might be closer to what you're looking for. A version without std::next_permutation that doesn't involve copying any vectors, and allows the input to remain const. However, it does this at the cost of checking the output in each iteration to make sure it doesn't add the same number twice.
#include<vector>
#include<iostream>
#include<algorithm>
template<typename T>
void OutputCombinations(
const std::vector<T>& input,
std::vector<typename std::vector<T>::const_iterator >& output)
{
for(auto it = input.begin(); it != input.end(); ++it)
{
if (std::find(output.begin(), output.end(), it) == output.end())
{
output.push_back(it);
if (output.size() == input.size())
{
for(auto node : output) std::cout << *node << " ";
std::cout << std::endl;
}
else OutputCombinations(input, output);
output.pop_back();
}
}
}
int main()
{
std::vector<int> nodes{ 2, 3, 4, 2 };
std::vector<std::vector<int>::const_iterator> result{};
OutputCombinations(nodes, result);
return 0;
}
After much studying I found inspiration in this article which gave me the ultimate solution. The idea is that we keep a vector of Boolean values which indicates whether or not a particular value has been used in the combination; that way we don't need to remove the element that we have already used hence there is no memory allocation overhead.
So, when building the branch {2,4,3}, if we get to {2,4}, vecTaken will be {true, false, true} and nNumBoolsSet will be 2. So when we loop, we will only "use" the element at index 1 of vecInput since that is the only element that has not been used as dictated by vecTaken.
void OutputCombos(vector<int>& vecInput, vector<int>& vecValues, vector<bool>& vecTaken, int& nNumBoolsSet)
{
size_t nSize = vecInput.size();
if (nNumBoolsSet == nSize)
{
for (int i : vecValues) cout << i << " ";
cout << endl;
return;
}
for (vector<int>::size_type i = 0; i < nSize; ++i)
{
if (vecTaken[i] == false)
{
vecValues.push_back(vecInput[i]);
vecTaken[i] = true;
++nNumBoolsSet;
OutputCombos(vecInput, vecValues, vecTaken, nNumBoolsSet);
vecTaken[i] = false;
vecValues.pop_back();
--nNumBoolsSet;
}
}
}
void OutputCombos(vector<int>& vecInput)
{
vector<int> vecValues;
vector<bool> vecTaken(vecInput.size(), false);
int nNumBoolsSet = 0;
OutputCombos(vecInput, vecValues, vecTaken, nNumBoolsSet);
}
int main()
{
vector<int> vecInput{ 2,3,4 };
OutputCombos(vecInput);
}

How to delete specific elements in a vector using struct data type

i'm new to C++. My program is a quiz game which user can choose category and level for the questions. At first, i use the struct data type
struct QuestionInfo
{
string category;
string level;
string question;
string answer;
};
then
vector<QuestionInfo> vec;
The idea of this part is to store the info of the question include (category, level, question and answer) to each element.
Then after building menu and the output questions UI, i go to the filters
void category_filter()
{
for (unsigned int i = 0; i < vec.size(); i ++)
{
if (category_choice != vec[i].category)
vec.erase(vec.begin() + i );
}
}
Void level_filter()
{
for (unsigned int i = 0; i < vec.size(); i ++)
{
if (level_choice != vec[i].level)
vec.erase(vec.begin() + i );
}
}
So the idea of the filters is to delete the elements which not contain the matched category and level. But the output questions did not match with the category and the level i had choose before. I'm not sure what I'm doing wrong.
Let me explain you the problem with my example. Suppose you have a vector of 10 elements, valid indexes are 0 till 9 elements. You have to erase 5th element i == 4. You erase it, then 6th element with index 5 moves to place of 5th elements with index 4. After that you increase i in for, it becomes 5. Thus you skip previous 6th element, that is now 5th with index 4.
You may fix your code like below, moving i ++ to the condition.
for (unsigned int i = 0; i < vec.size(); ) {
if (category_choice != vec[i].category)
vec.erase(vec.begin() + i );
else
i ++;
}
The preferable solution in C++ way is demonstrated by #Jonathan.
You're getting tripped up by not accounting for the indexing shift that occurs when you erase an element. I personally would rely on remove_if and erase with a lambda to accomplish this:
vec.erase(remove_if(begin(vec), end(vec), [&](const auto& i) { return category_choice != i.category; }, end(vec));
vec.erase(remove_if(begin(vec), end(vec), [&](const auto& i) { return level_choice != i.level; }, end(vec));
Alternatively you might consider combining them for a bit of speed improvement:
vec.erase(remove_if(begin(vec), end(vec), [&](const auto& i) { return category_choice != i.category || level_choice != i.level; }, end(vec));
You might want to remove_if + erase:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
struct QuestionInfo
{
std::string category;
std::string level;
std::string question;
std::string answer;
QuestionInfo(std::string category, std::string level, std::string question, std::string answer) :
category(category), level(level), question(question), answer(answer) {}
};
std::vector<QuestionInfo> vec;
std::string category_choice = "cat1";
std::string level_choice = "lev1";
vec.push_back(QuestionInfo("cat1", "lev1", "q1", "a1"));
vec.push_back(QuestionInfo("cat1", "lev2", "q2", "a2"));
vec.push_back(QuestionInfo("cat2", "lev1", "q3", "a3"));
vec.push_back(QuestionInfo("cat2", "lev2", "q4", "a4"));
std::cout << "\nNot filered" << std::endl;
for (auto const &info : vec)
std::cout << "Category:" << info.category << " Level:" << info.level << std::endl;
auto filter_category = std::remove_if(vec.begin(), vec.end(), [&](auto const &info) {return category_choice != info.category; });
vec.erase(filter_category, vec.end());
std::cout << "\nFilered by category" << std::endl;
for (auto const &info : vec)
std::cout << "Category:" << info.category << " Level:" << info.level << std::endl;
auto filter_level = std::remove_if(vec.begin(), vec.end(), [&](auto const &info) {return level_choice != info.level; });
vec.erase(filter_level, vec.end());
std::cout << "\nFiltered by level" << std::endl;
for (auto const &info : vec)
std::cout << "Category:" << info.category << " Level:" << info.level << std::endl;
system("pause");
return 0;
}
As mentioned by others, the remove_if + erase is a standard and expressive way to achieve what you want. But you may also consider non-destructive filtering with a copy_if into a new container, or even without using any additional storage with Boost.Range adaptor boost::adaptors::filtered or boost::filter_iterator. Look here for examples.

How to get indices of a Mat with specific value?

I want to find indices of an array that equal with specific value. so i've Written this code:
vector<int> _classes = { 2,2,1,1,3,3,3,3,5,5,4,4,5,6,6 };
vector<int> labelVec = {1,2,3,4,5,6};
vector<int> index;
for (int i = 0; i < labelVec.size(); i++)
{
compare(_classes, labelVec[i], index, CMP_EQ);
std::vector<int>::iterator nn = find(index.begin(), index.end(), 255);
}
but i have this error : Unhandled exception at 0x760B5608 in compareFuncTest.exe: Microsoft C++ exception: cv::Exception at memory location 0x004DDC44. if i define index as Mat, this problem will be resolved. but if i define index as Mat, i can't use from find(). also in this documentation states: output array (in my code as index) that has the same size and type as the input arrays. PLZ help me to fix this code.
I still do not get what is the point of this test, I guess this will be in some other algorithm... So, I give you two possible solutions.
1) Without OpenCV
First, you must know that
std::vector<int>::iterator nn = find(index.begin(), index.end(), 255);
Will only give you the first occurrance. Knowing this, here is a way you could check if the label is inside the _classes vector.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> _classes = { 2,2,1,1,3,3,3,3,5,5,4,4,5,6,6 };
std::vector<int> labelVec = {1,2,3,4,5,6,7};
for (const auto& label: labelVec)
{
std::vector<int>::iterator nn = find(_classes.begin(), _classes.end(), label);
if (nn != _classes.end())
{
std::cout << "I got the value from _classes: " << *nn << std::endl;
} else
{
std::cout << "I couldn't find the value with label:" << label << std::endl;
}
}
}
Here I iterate over all the labels (as you did) and then use the find directly in the classes, but with the label variable. Then I check if I found the label or not, if not, it will give you a value equal to _classes.end() which will give error if you try to use it (look at the extra label 7 which is not found).
This example can be tested here online.
2) With OpenCV
no oline test here. But this one is also easy to do. If you have a Mat in index you will only need to change the iterators to be templated. Like this:
auto nn = find(index.begin<int>(), index.end<int>(), 255);
If you a cv::Mat of classes you can also do it as in the method before and skip the comparison part (this would be faster)
Update
Since you want is the indices and all of them, then you have to iterate over it :/ if you wanted the values you could have used copy_if. You can create a lambda function to easily do the job.
like this:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
auto getIndices = [](const std::vector<int>& vec, const int value){
std::vector<int> result;
for (size_t t = 0; t < vec.size(); t++)
{
if (vec[t] == value)
{
result.push_back(static_cast<int>(t));
}
}
return result;
};
std::vector<int> _classes = { 2,2,1,1,3,3,3,3,5,5,4,4,5,6,6 };
std::vector<int> labelVec = {1,2,3,4,5,6,7};
for (const auto& label: labelVec)
{
std::vector<int> nn = getIndices(_classes, label);
std::cout << "I got the following indices for value"<< label<< ": [ ";
for (const auto& n : nn)
{
std::cout << n << ",";
}
std::cout << " ]" << std::endl;
}
}

How do I use two consecutive elements of a deque at once in a for loop?

I have to process element from a deque (first to last), but at each iteraton I need to use one element and the next too. So I'm trying to write a for loop that starts with mydeque.begin() and finishes at mydeque[mydeque.size()-1]. Also; I would like to know if my iterator deque::iterator it has a next method (it->next()), to make operations like *it - *it->next(). Thank you very much.
Here's how:
#include <deque>
#include <iostream>
int main() {
std::deque<int> test = {1,2,3,4,5,6,7,8};
for(auto i = test.begin(); i != test.end(); i++) {
auto next = std::next(i);
std::cout << *i << *next << std::endl;
if(next==test.end())
{
//Do something. This is the last element.
break;
}
}
}
EDIT: Watch out for deques with only one element. Do this by performing a check such as if(test.begin()==test.end()).
EDIT: My initial solution was indeed a bit error prone and unprecise.
This can easily be done using iterators, see this little example:
#include <deque>
#include <iostream>
int main() {
std::deque<int> test = {1,2,3,4,5,6,7};
for(auto i = test.begin(); i != test.end(); ++i) {
auto next = std::next(i);
if(next != test.end()) {
std::cout << *i << " " << *next << std::endl;
}
}
}
You can simply increment the iterator by 2 and use std::next to also pick the following item (since the offset of std::next defaults to 1).

Algorithm to merge (fuse two items together, replace them with the fusion) items in std::list (i.e. destructive clustering)

Apologies if this is obvious, I'm new to C++. There seem to be related answers on stackoverflow, just not those I understand enough to apply in my case.
I have a list of class instances that represent visual patches.
When the distance between features is below a threshold I would like to merge those items, replacing parents with the merged output.
Something like this:
Loop through all items using a nested for loop (to compare each item to every other item)
When a match is found (that is not the same instance):
Construct a new (child) instance from the matching pair, append to new list.
erase both (parent) items from the list
Continue iterating through the list finding other matches
Append the new list to the original list.
I know how to erase items from the list in a single for loop using iterators, but its unclear to me how it would work in a nested loop due to erase() incrementing to the next item.
I may also need to make this function recursive as eventually the merging should reduce the list to a set of representative instances by merging merges.
Suggestions would be appreciated.
Following is my attempt, which does not work (the nested loops interfere with one and other). What is the proper way to do this kind of pairwise comparison of elements in a list?
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> mylist;
list<int>::iterator mylistiterOutter;
list<int>::iterator mylistiterInner;
for(int i=0; i<10; i++) {
mylist.push_back(i);
cout << i << endl;
}
for(int i=0; i<10; i++) {
mylist.push_back(i);
cout << i << endl;
}
int counter =0;
for(mylistiterOutter = mylist.begin(); mylistiterOutter != mylist.end();) {
cout << "Size of mylist: " << mylist.size() << endl;
for(mylistiterInner = mylist.begin(); mylistiterInner != mylist.end();) {
cout << "mylistiterInner: " << *mylistiterInner << endl;
cout << "mylistiterOutter: " << *mylistiterOutter << endl;
//if (mylistiterOutter == mylistiterInner) {// match!
if (false) {
//mylistiterOutter = mylist.erase(mylistiterOutter);
//mylistiterInner = mylist.erase(mylistiterInner);
} else {
mylistiterOutter++;
mylistiterInner++;
}
counter++;
}
}
cout << endl << "Size of mylist: " << mylist.size() << endl << "NumIterations: " << counter << endl;
return(0);
}
Thanks #lalitm. I tried your approach first because it is closer to what I had originally envisioned, but J.N.'s proposal is more elegant so I'll try that also. Unfortunately I was unable to make #lalitm's approach work. (leads to segmentation fault). Following is slightly more complex code that includes sample class, and merging code, using #lalitm's approach:
#include <iostream>
#include <list>
#include <cmath>
using namespace std;
class percepUnit {
public:
int cx, cy; // location of percept in frame
bool remove; // used to delete percepts
// constructor method
percepUnit(int ix, int iy) {
cx = ix;
cy = iy;
remove = false;
}
};
bool canMerge(percepUnit unitA, percepUnit unitB) {
double dist = sqrt(pow(abs(unitA.cx-unitB.cx),2)+ pow(abs(unitA.cy-unitB.cy),2));
return (dist < 3);
}
percepUnit merge(percepUnit unitA, percepUnit unitB) {
int x,y;
x = unitA.cx+unitB.cx/2;
y = unitA.cy+unitB.cy/2;
return (percepUnit(x,y));
}
int main() {
list<percepUnit> mylist;
list<percepUnit> mergedlist;
list<percepUnit>::iterator mylistiterOutter;
list<percepUnit>::iterator mylistiterInner;
bool mylistiterOutterChanged;
mylist.push_back(percepUnit(0,0));
mylist.push_back(percepUnit(2,2));
mylist.push_back(percepUnit(5,5));
mylist.push_back(percepUnit(7,7));
//cout << "merge front/back? " << canMerge(mylist.front(),mylist.back()) << endl;
//percepUnit test = merge(mylist.front(),mylist.back());
//cout << "merged front/back (x,y): " << test.cx << "," << test.cy << endl;
for(mylistiterOutter = mylist.begin(); mylistiterOutter != mylist.end();) {
cout << "Size of mylist: " << mylist.size() << endl;
mylistiterInner = mylistiterOutter;
mylistiterOutterChanged = false;
for (++mylistiterInner; mylistiterInner != mylist.end();) {
if (canMerge(*mylistiterOutter, *mylistiterInner )) {
mergedlist.push_back(merge(*mylistiterOutter, *mylistiterInner));
mylistiterOutter = mylist.erase(mylistiterOutter);
mylistiterInner = mylist.erase(mylistiterInner);
mylistiterOutterChanged = true;
} else {
++mylistiterInner;
}
}
if (!mylistiterOutterChanged) {
++mylistiterOutter;
}
}
mylist.splice(mylist.end(), mergedlist);
return(0);
}
Here is my gdb info:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b31d97 in std::_List_node_base::unhook() ()
from /usr/lib/libstdc++.so.6
(gdb) bt
#0 0x00007ffff7b31d97 in std::_List_node_base::unhook() ()
from /usr/lib/libstdc++.so.6
#1 0x0000000000401786 in std::list<percepUnit, std::allocator<percepUnit> >::_M_erase (this=0x7fffffffe4d0, __position=...)
at /usr/include/c++/4.4/bits/stl_list.h:1424
#2 0x000000000040153d in std::list<percepUnit, std::allocator<percepUnit> >::erase (this=0x7fffffffe4d0, __position=...)
at /usr/include/c++/4.4/bits/list.tcc:111
#3 0x0000000000401130 in main () at debug.cpp:61
Still no luck. I think the problem could be that the code above does not test if the two iterators are pointing at the same item in the list, and therefore that messes up the iterators (incrementing or not when they should not be).
How can I test if both iterators point at the same item? (without the brute force of comparing all the class members?, but then two copies of the same instance are not the same instance.)
void mergeObjects(std::list<T>& list)
{
std::list<T> new_list;
typedef std::list<T>::iterator Itr;
for (Itr i=list.begin(); i != list.end();)
{
Itr j=i;
bool is_merged = false;
for (++j; j != list.end();)
{
if (isMergeable(*i, *j))
{
T merged = mergeObj(*i, *j);
new_list.push_back(merged);
list.erase(j);
is_merged = true;
break;
}
else
{
++j;
}
}
if (is_merged)
{
i = list.erase(i);
}
else
{
++i;
}
}
list.splice(list.end(), new_list);
}
This should work since inserting and deleting elements does not invalidate any pointers, references and iterator to any other elements. [Ref: The C++ STL Tutorial and Reference, Nikolai Josuttis]
You didn't provide much insight yet, but here is a nice way of doing it:
#include <algorithm>
#include <set>
std::list<int> myList = {5,6,7,7,8,5};
std::set<int> uniques; // a set can only contain unique elements
// copying the list in the set will overwrite the same elements when duplicates are found
std::copy(myList.begin(), myList.end(), std::inserter(uniques, uniques.begin()));
// clear the existing list
myList.clear();
// copy back the unique elements.
std::copy(uniques.begin(), uniques.end(), std::back_inserter(myList));
for (int i: myList)
cout << i << endl;
EDIT : performance wise it should be comparable to your solution or faster because I the searching in the set is done using a 0(log(N)) algorithm, while you have two loops.
EDIT2 : you need something that's a bit more complex than what I thought. One starting piece of advice though: you can't loop with iterators and modify the container you are iterating on at the same time. You'll need to use integer indexes.
EDIT3 : The solution below provides a way using unordered_set. You need to be able to discrimate the objects belonging to the same "groups".
#include <unordered_set>
// That's the objects we are going to "fuse"
// In this example I suppose that all Points that have the same X must be fused
struct Point
{
double x;
double y;
// We need a way to say that which points are equals
bool operator==(const Point& other) const
{
return other.x == x;
}
};
// Then we need a unique identifier to place the points in a set
namespace std {
template <> struct hash<Point> {
double operator()(const Point& point) const {
return point.x;
}
};
}
// We will use an unordered_set to put our elements in
unordered_set<Point> uniques;
// Then we can proceed as before
std::copy(myList.begin(), myList.end(), std::inserter(uniques, uniques.begin()));
myList.clear();
std::copy(uniques.begin(), uniques.end(), std::back_inserter(myList));
I think that modifying (erasing) the list inside nested loop is a bad idea. The outer loop iterator (mylistiterOutter from your example code) will not work properly.
You should make two separate loops. The first one should search for the items to be merged and somehow remember them (without erasing). The second loop would then erase the remembered items and create the new ones.
Following is what I ended up with.
It's ragged: pairs are not compared twice (0,1 and 1,0)
instances are not compared to themselves (0,0)
#include <iostream>
#include <list>
#include <cmath>
#include <algorithm>
using namespace std;
class percepUnit {
public:
int cx, cy; // location of percept in frame
bool remove; // used to delete percepts
// constructor method
percepUnit(int ix, int iy) {
cx = ix;
cy = iy;
remove = false;
}
};
bool canMerge(percepUnit unitA, percepUnit unitB) {
double dist = sqrt(pow(abs(unitA.cx-unitB.cx),2)+ pow(abs(unitA.cy-unitB.cy),2));
return (dist < 3);
}
percepUnit merge(percepUnit unitA, percepUnit unitB) {
int x,y;
x = unitA.cx+unitB.cx/2;
y = unitA.cy+unitB.cy/2;
return (percepUnit(x,y));
}
// Predicate to use remove_if to delete merge inputs.
bool removePercepsMarkedForRemoval(const percepUnit &unit) {
return unit.remove;
}
int main() {
list<percepUnit> mylist;
list<percepUnit> mergedlist;
list<percepUnit>::iterator mylistiterOutter;
list<percepUnit>::iterator mylistiterInner;
mylist.push_back(percepUnit(0,0));
mylist.push_back(percepUnit(2,2));
mylist.push_back(percepUnit(5,5));
mylist.push_back(percepUnit(7,7));
mylist.push_back(percepUnit(15,15));
for(mylistiterOutter = mylist.begin(); mylistiterOutter != mylist.end(); mylistiterOutter++) {
mylistiterInner = mylistiterOutter; // bypass the same pair twice
while (mylistiterInner != mylist.end()) {
if (canMerge(*mylistiterOutter, *mylistiterInner) and mylistiterOutter != mylistiterInner) { // bypass the same instance
mergedlist.push_back(merge(*mylistiterOutter, *mylistiterInner));
mylistiterOutter->remove = true;
mylistiterInner->remove = true;
}
mylistiterInner++;
}
}
mylist.erase(remove_if(mylist.begin(), mylist.end(), removePercepsMarkedForRemoval), mylist.end());
mylist.splice(mylist.end(), mergedlist);
return(0);
}