I have the following vector with pair values:
first 3 second 2
first 1 second 2
first 1 second 1
first 2 second 2
I would like to sort my vector such that the result would be
==========================
first 1 second 2
first 1 second 1
first 2 second 2
first 3 second 2
That means:
sort with respect to the first element.
in case of equality sort with respect to the second element
My code looks like:
#include <utility> // std::pair
#include <iostream> // std::cout
#include <vector>
typedef std::pair<double, double> my_pair;
struct sort_pred
{
bool operator () (const my_pair& left, const my_pair& right)
{
return (left.first < right.first) && (left.second > right.second);
}
};
int main () {
std::vector<my_pair> data;
data.push_back(my_pair(3,2) );
data.push_back(my_pair(1,2) );
data.push_back(my_pair(1,1) );
data.push_back(my_pair(2,2) );
for(auto a: data)
std::cout << "first "<< a.first << " second " << a.second << std::endl;
std::cout << "==========================\n";
std::sort(data.begin(), data.end(), sort_pred());
for(auto a: data)
std::cout << "first "<< a.first << " second " << a.second << std::endl;
return 0;
}
The condition in the sort_pred expressed what I would like to do, but is not correct. I get wrong values.
Any idea how this can be easily solved?
Your comparator isn't quite right, since you want it to return true if either the first check succeeds OR the first are equal and the second check succeeds. You only want to check the seconds if the firsts are equal. So something like this:
struct sort_pred
{
bool operator()(const my_pair& left, const my_pair& right) const
{
if (left.first != right.first) {
return left.first < right.first;
}
return left.second > right.second;
}
};
This can be simplified using the fact that tuples are lexicographically comparable:
struct sort_pred
{
bool operator()(const my_pair& left, const my_pair& right) const
{
return std::tie(left.first, right.second) <
std::tie(right.first, left.second);
}
};
This is possible with a bit of tweaking to your predicate:
struct sort_pred
{
bool operator () (const my_pair& lhs, const my_pair& rhs)
{
return lhs.first<rhs.first ||
(!(rhs.first<lhs.first) && lhs.second>rhs.second);
}
};
Live demo
Your use of && doesn't really make sense. It goes on to evaluate the second element if left.first > right.first, but really you want that to only happen if left.first == right.first.
This should work:
bool operator () (const my_pair& left, const my_pair& right)
{
if (left.first != right.first)
return left.first < right.first;
else
return left.second > right.second;
}
You have to distinguish more cases:
bool operator () (const my_pair& left, const my_pair& right)
{
if (left.first < right.first)
return true;
if (left.first != right.first)
return false;
// when primary criterion is equal:
if (left.second > right.second)
// you want this to sort descending, right?
return true;
// .... other criteria
return false;
}
I think your predicate is wrong ?
If I understand correctly, you want precedence on the first element, and only in case of equality on the second element?
so maybe something like:
struct sort_pred
{
bool operator () (const my_pair& left, const my_pair& right)
{
return (left.first == right.first) ?
(left.second > right.second) :
(left.first < right.first);
}
};
Here you are
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
typedef std::pair<double, double> my_pair;
struct sort_pred
{
bool operator ()( const my_pair &left, const my_pair &right ) const
{
return ( left.first < right.first ) ||
( !( right.first < left.first ) && ( right.second < left.second ) );
}
};
int main()
{
std::vector<my_pair> data;
data.push_back( my_pair( 3, 2 ) );
data.push_back( my_pair( 1, 2 ) );
data.push_back( my_pair( 1, 1 ) );
data.push_back( my_pair( 2, 2 ) );
std::stable_sort( data.begin(), data.end(), sort_pred() );
for ( const auto &p : data ) std::cout << p.first << ' ' << p.second << std::endl;
}
The program output is
1 2
1 1
2 2
3 2
You want A to be before B if
A first is less than B first, or
If A first and B first are equal and B second is less than A second
In code that is
(a.first < b.first) or
((a.first == b.first) and
(b.second < a.second))
But this is suboptimal, from a programming point of view: Now you need an additional operator== implemented.
But since a value can only be less, equal or greater than another, you can rewrite that to
(a.first < b.first) or
(not (b.first > a.first) and
(b.second < a.second))
I have a problem that concerns determining if two vectors contain two elements the same. The elements may be anywhere in the vector, but they must be adjacent.
EDITED FOR MORE EXAMPLES
For example the following two vectors, when compared, would return false.
Vector 1 = [ 0, 1, 2, 3, 4, 6 ]
Vector 2 = [ 1, 4, 2, 0, 5, 3 ]
But the following two would return true:
Vector 1 = [ 0, 1, 2, 3, 4, 5 ]
Vector 2 = [ 4, 2, 1, 5, 0, 3 ]
because the 1,2 in the first vector would correspond to the 2,1 in the second vector.
True:
Vector 1 = [ 0, 1, 2, 3, 4, 5 ]
Vector 2 = [ 1, 4, 2, 0, 5, 3 ]
{5,0} is a pair, despite looping around the vector (I originally said this was false, thanks for spotting that 'Vlad from Moscow').
True:
Vector 1 = [ 0, 1, 2, 3, 4, 5 ]
Vector 2 = [ 4, 8, 6, 2, 1, 5, 0, 3 ]
{2,1} is still a pair, even though they are not in the same position
The actual application is that I have a polygon (face) with N points stored in a vector. To determine if a set of polygons completely enclose a 3D volume, I test each face to ensure that each edge is shared by another face (where an edge is defined by two adjacent points).
Thus, Face contains a vector of pointers to Points...
std::vector<Point*> points_;
and to check if a Face is surrounded, Face contains a member function...
bool isSurrounded(std::vector<Face*> * neighbours)
{
int count = 0;
for(auto&& i : *neighbours) // for each potential face
if (i != this) // that is not this face
for (int j = 0; j < nPoints(); j++) // and for each point in this face
for (int k = 0; k < i->nPoints(); k++ ) // check if the neighbour has a shared point, and that the next point (backwards or forwards) is also shared
if ( ( this->at(j) == i->at(k) ) // Points are the same, check the next and previous point too to make a pair
&& ( ( this->at((j+1)%nPoints()) == i->at((k+1)%(i->nPoints())) )
|| ( this->at((j+1)%nPoints()) == i->at((k+i->nPoints()-1)%(i->nPoints())) )))
{ count++; }
if (count > nPoints() - 1) // number of egdes = nPoints -1
return true;
else
return false;
}
Now, obviously this code is horrible. If I come back to this in 2 weeks, I probably won't understand it. So faced with the original problem, how would you neatly check the two vectors?
Note that if you are trying to decipher the provided code. at(int) returns the Point in a face and nPoints() returns the number of points in a face.
Many thanks.
Here is way if your element are same set of elements then assign index for each. (Didnt mention corner cases in pseudo ) :-
for(int i=0;i<vect1.size;i++) {
adj[vect1[i]][0] = vect1[i-1];
adj[vect2[i]][1] = vect2[i+1];
}
for(int j=0;j<vect2.size();j++) {
if(arr[vect2[i]][0]==(vect2[j-1] or vect[j+1]))
return true
if(arr[vect2[i]][1]==(vect2[j-1] or vect[j+1]))
return true
}
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;
class AdjacentSort
{
public:
AdjacentSort(const vector<int>& ref);
~AdjacentSort();
bool operator()(int e1,int e2) const;
private:
const vector<int>& ref_;
};
AdjacentSort::AdjacentSort(const vector<int>& ref):
ref_(ref)
{
}
bool AdjacentSort::operator()(int e1, int e2) const
{
auto it1 = find(ref_.begin(),ref_.end(),e1);
auto it2 = find(ref_.begin(),ref_.end(),e2);
return distance(it1,it2) == 1;
}
AdjacentSort::~AdjacentSort()
{
}
int main()
{
vector<int> vec {1,2,3,4,5};
vector<int> vec2 {1,3,5,4,2};
AdjacentSort func(vec);
auto it = adjacent_find(vec2.begin(),vec2.end(),func);
cout << *it << endl;
return 0;
}
It returns the first element where two adjacent numbers are found, else it returns the end iterator.
Not efficient but following is a possibility.
bool comparePair ( pair<int,int> p1, pair<int,int> p2 ) {
return ( p1.first == p2.first && p1.second == p2.second )
|| ( p1.second == p2.first && p1.first == p2.second );
}
//....
vector< pair<int,int> > s1;
vector< pair<int,int> > s1;
vector< pair<int,int> > intersect( vec1.size() + vec2.size() );
for ( int i = 0; i < vec1.size()-1; i++ ) {
pair<int, int> newPair;
newPair.first = vec1[i];
newPair.first = vec1[i+1];
s1.push_back( newPair );
}
for ( int i = 0; i < vec2.size()-1; i++ ) {
pair<int, int> newPair;
newPair.first = vec2[i];
newPair.first = vec2[i+1];
s2.push_back( newPair );
}
auto it = std::set_intersection ( s1.begin(), s1.end(), s2.begin(), s2.end(),
intersect.begin(), comparePair );
return ( it != intersect.begin() ); // not sure about this.
If I have understood correctly these two vectors
std::vector<int> v1 = { 0, 1, 2, 3, 4, 5 };
std::vector<int> v2 = { 3, 5, 2, 1, 4, 0 };
contain adjacent equal elements. They are pair {1, 2 } in the first vector and pair { 2, 1 } in the second vector though positions of the pairs are different in the vectors.
In fact you already named the appropriate standard algorithm that can be used in this task. It is std::adjacent_find. For example
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v1 = { 0, 1, 2, 3, 4, 5 };
std::vector<int> v2 = { 3, 5, 2, 1, 4, 0 };
bool result =
std::adjacent_find( v1.begin(), v1.end(),
[&v2]( int x1, int y1 )
{
return std::adjacent_find( v2.begin(), v2.end(),
[=]( int x2, int y2 )
{
return ( x1 == x2 && y1 == y2 || x1 == y2 && y1 == x2 );
} ) != v2.end();
} ) != v1.end();
std::cout << "result = " << std::boolalpha << result << std::endl;
return 0;
}
Here's my attempt at this problem. Quite simply, iterate through a, find the same element in b and then compare the next element in a with the elements before and after our position in b.
If it's a little wordier than it needed to be it was so that this function can be called with any containers. The only requirement is that the containers' iterators have to bidirectional.
#include <vector>
#include <iostream>
#include <algorithm>
#include <list>
using namespace std;
template <class Iter>
pair<Iter, Iter> get_neighbors(Iter begin, Iter current, Iter end)
{
auto p = make_pair(end, next(current));
if(current != begin)
p.first = prev(current);
return p;
}
template <class Iter1, class Iter2>
bool compare_if_valid(Iter1 p1, Iter1 end1, Iter2 p2)
{
return p1 != end1 && *p1 == *p2;
}
template <class C1, class C2>
auto neighbors_match(const C1 & a, const C2 & b) ->
decltype(make_pair(begin(a), begin(b)))
{
for(auto i = begin(a); i != end(a) && next(i) != end(a); ++i)
{
auto pos_in_b = find(begin(b), end(b), *i);
if(pos_in_b != end(b))
{
auto b_neighbors = get_neighbors(begin(b), pos_in_b, end(b));
if(compare_if_valid(b_neighbors.first, end(b), next(i)))
return {i, b_neighbors.first};
else if(compare_if_valid(b_neighbors.second, end(b), next(i)))
return {i, pos_in_b};
}
}
return {end(a), end(b)};
}
int main()
{
vector<int> a = {0, 1, 2, 3, 4, 5};
vector<int> b = {1, 4, 2, 0, 5, 3};
cout << boolalpha << (neighbors_match(a, b).first != a.end()) << endl;
vector<int> a2 = {0, 1, 2, 3, 4, 5};
list<int> b2 = {4, 2, 1, 5, 0, 3};
auto match = neighbors_match(a2, b2);
cout << boolalpha << distance(a2.cbegin(), match.first)
<< ' ' << distance(b2.cbegin(), match.second) << endl;
return 0;
}
First, write a make_paired_range_view which takes a range and returns a range whose iterators return std::tie( *it, *std::next(it) ). boost can help here, as their iterator writing code makes this far less annoying.
Next, unordered_equal takes two pairs and compares them ignoring order (so they are equal if the first both equal and the second both equal, or if the first equals the other second and vice versa).
Now we look for each of the left hand side's pairs in the right hand side using unordered_equal.
This has the advantage of taking 0 extra memory, but the disadvantage of O(n^2) time.
If we care more about time than memory, we can instead shove the pairs above into an unordered_set after sorting the pair to be in a canonical order. We then to through the second container, testing each pair (after sorting) to see if it is in the unordered_set. This takes O(n) extra memory, but runs in O(n) time. It can also be done without fancy dancy vector and range writing.
If the elements are more expensive than int, you can write a custom pseudo_pair that holds pointers and whose hash and equality is based on the content of the pointers.
An interesting "how would you do it..." problem... :-) It got me to take a 15 minute break from slapping edit boxes and combo boxes on forms and do a bit of programming for a change... LOL
So, here's how I think I'd do it...
First I'd define a concept of an edge as a pair of values (pair of ints - following your original example). I realize your example is just a simplification and you're actually using vectors of your own classes (Point* rather than int?) but it should be trivial to template-ize this code and use any type you want...
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <set>
#include <vector>
using namespace std;
typedef pair<int, int> edge;
Then I would create a set class that will keep its elements (edges) ordered in the way we need (by comparing edges in the order insensitive manner - i.e. if e1.first==e2.first and e1.second==e2.second then edges e1 and e2 are the same, but they are also same if e1.first==e2.second and e1.second==e2.first). For this, we could create a functional:
struct order_insensitive_pair_less
{
bool operator() (const edge& e1, const edge& e2) const
{
if(min(e1.first,e1.second)<min(e2.first,e2.second)) return true;
else if(min(e1.first,e1.second)>min(e2.first,e2.second)) return false;
else return(max(e1.first,e1.second)<max(e2.first,e2.second));
}
};
Finally, our helper class (call it edge_set) would be a simple derivative of a set ordered using the above functional with a couple of convenience methods added - a constructor that populates the set from a vector (or your Face class in practice) and a tester function (bool shares_edge(const vector&v)) that tells us whether or not the set shares an edge with another. So:
struct edge_set : public set<edge, order_insensitive_pair_less>
{
edge_set(const vector<int>&v);
bool shares_edge(const vector<int>&v);
};
Implemented as:
edge_set::edge_set(const std::vector<int>&v) : set<edge, order_insensitive_pair_less>()
{
if(v.size()<2) return; // assume there must be at least 2 elements in the vector since it is supposed to be a list of edges...
for (std::vector<int>::const_iterator it = v.begin()+1; it != v.end(); it++)
insert(edge(*(it-1), *it));
}
bool edge_set::shares_edge(const std::vector<int>& v)
{
edge_set es(v);
for(iterator es_it = begin(); es_it != end(); es_it++)
if(es.count(*es_it))
return true;
return false;
}
The usage then becomes trivial (and reasonably elegant). Assuming you have the two vectors you gave as examples in the abstract of your problem in variables v1 and v2, to test whether they share an edge you would just write:
if(edge_set(v1).shares_edge(v2))
// Yup, they share an edge, do something about it...
else
// Nope, not these two... Do something different...
The only assumption about the number of elements in this approach is that each vector will have at least 2 (since you cannot have an "edge" without at least to vertices). However, even if this is not the case (one of the vectors is empty or has just one element) - this will result in an empty edge_set so you'll just get an answer that they have no shared edges (since one of the sets is empty). No big deal... In my opinion, doing it this way would certainly pass the "two week test" since you would have a dedicated class where you could have a couple of comment lines to say what it's doing and the actual comparison is pretty readable (edge_set(v1).shares_edge(v2))...
If I understand your question:
std::vector<int> a, b;
std::vector<int>::iterator itB = b.begin();
std::vector<int>::iterator itA;
std::vector<std::vector<int>::iterator> nears;
std::vector<int>::iterator near;
for(;itB!=b.end() ; ++itB) {
itA = std::find(a.begin(), a.end(), *itB);
if(nears.empty()) {
nears.push_back(itA);
} else {
/* there's already one it, check the second */
if(*(++nears[0])==*itA && itA != a.end() {
nears.push_back(itA);
} else {
nears.clear();
itB--;
}
}
if(nears.size() == 2) {
return true;
}
}
return false;
I think this is the most concise i can come up with.
bool check_for_pairs(std::vector<int> A, std::vector<int> B) {
auto lastA = A.back();
for (auto a : A) {
auto lastB = B.back();
for (auto b : B) {
if ((b == a && lastB == lastA) || (b == lastA && lastB == a)) return true;
lastB = b;
}
lastA = a;
}
return false;
}
Are more time efficient approach would be to use a set
bool check_for_pairs2(std::vector<int> A, std::vector<int> B) {
using pair = std::pair<int,int>;
std::unordered_set< pair, boost::hash<pair> > lookup;
auto last = A.back();
for (auto a : A) {
lookup.insert(a < last ? std::make_pair(a,last) : std::make_pair(last,a));
last = a;
}
last = B.back();
for (auto b : B) {
if (lookup.count(b < last ? std::make_pair(b,last) : std::make_pair(last,b)))
return true;
last = b;
}
return false;
}
If you implement a hash function that hashes (a,b) and (b,a) to the same, you could remove the check for which value is smallest
What you are essentially asking for is whether the edge sets of two faces (let's call them a and b) are disjoint or not. This can be decomposed into the problem of whether any of the edges in b are in a, which is just a membership test. The issue then, is that vectors are not great at membership tests.
My solution, is to convert one of the vectors into an unordered_set< pair<int, int> >.
an unordered_set is just a hash table, and the pairs represent the edges.
In representing edges, I've gone for a normalising scheme where the indices of the vertices are in increasing order (so [2,1] and [1,2] both get stored as [1,2] in my edge set). This makes equality testing that little bit easier (in that it is just the equality of the pair)
So here is my solution:
#include <iostream>
#include <utility>
#include <functional>
#include <vector>
#include <unordered_set>
using namespace std;
using uint = unsigned int;
using pii = pair<int,int>;
// Simple hashing for pairs of integers
struct pii_hash {
inline size_t
operator()(const pii & p) const
{
return p.first ^ p.second;
}
};
// Order pairs of integers so the smallest number is first
pii ord_pii(int x, int y) { return x < y ? pii(x, y) : pii(y, x); }
bool
shares_edge(vector<int> a, vector<int> b)
{
unordered_set<pii, pii_hash> edge_set {};
// Create unordered set of pairs (the Edge Set)
for(uint i = 0; i < a.size() - 1; ++i)
edge_set.emplace( ord_pii(a[i], a[i+1]) );
// Check if any edges in B are in the Edge Set of A
for(uint i = 0; i < b.size() - i; ++i)
{
pii edge( ord_pii(b[i], b[i+1]) );
if( edge_set.find(edge) != edge_set.end() )
return true;
}
return false;
}
int main() {
vector<int>
a {0, 1, 2, 3, 4, 5},
b {1, 4, 2, 0, 5, 3},
c {4, 2, 1, 0, 5, 3};
shares_edge(a, b); // false
shares_edge(a, c); // true
return 0;
}
In your particular case, you may want to make shares_edge a member function of your Face class. It may also be beneficial to precompute the edge set and store it as an instance variable of Face as well, but that depends on how often the edge data changes vs how often this calculation occurs.
EDIT Extra Solution
EDIT 2 Fixed for question change: edge set now wraps around point list.
Here's what it would look like if you added the edge set, precomputed at initialisation to some sort of Face class. The private nested Edge class can be thought of as decorating your current representation of an edge (i.e. two adjacent positions in the point list), with an actual class, so that collections like sets can treat the index into the point list as an actual edge:
#include <cassert>
#include <iostream>
#include <utility>
#include <functional>
#include <vector>
#include <unordered_set>
using uint = unsigned int;
class Face {
struct Edge {
int _index;
const std::vector<int> *_vertList;
Edge(int index, const std::vector<int> *vertList)
: _index {index}
, _vertList {vertList}
{};
bool
operator==(const Edge & other) const
{
return
( elem() == other.elem() && next() == other.next() ) ||
( elem() == other.next() && next() == other.elem() );
}
struct hash {
inline size_t
operator()(const Edge & e) const
{
return e.elem() ^ e.next();
}
};
private:
inline int elem() const { return _vertList->at(_index); }
inline int
next() const
{
return _vertList->at( (_index + 1) % _vertList->size() );
}
};
std::vector<int> _vertList;
std::unordered_set<Edge, Edge::hash> _edgeSet;
public:
Face(std::initializer_list<int> verts)
: _vertList {verts}
, _edgeSet {}
{
for(uint i = 0; i < _vertList.size(); ++i)
_edgeSet.emplace( Edge(i, &_vertList) );
}
bool
shares_edge(const Face & that) const
{
for(const Edge & e : that._edgeSet)
if( _edgeSet.find(e) != _edgeSet.end() )
return true;
return false;
}
};
int main() {
Face
a {0, 1, 2, 3, 4, 5},
b {1, 4, 2, 0, 5, 3},
c {4, 2, 1, 0, 5, 3},
d {0, 1, 2, 3, 4, 6},
e {4, 8, 6, 2, 1, 5, 0, 3};
assert( !d.shares_edge(b) );
assert( a.shares_edge(b) );
assert( a.shares_edge(c) );
assert( a.shares_edge(e) );
return 0;
}
As you can see, this added abstraction makes for a quite pleasing implementation of shares_edge(), but that is because the real trick is in the definition of the Edge class (or to be more specific the relationship that e1 == e2 <=> Edge::hash(e1) == Edge::hash(e2)).
I know I'm a little late with this, but here's my take at it:
Not in-situ:
#include <algorithm>
#include <iostream>
#include <tuple>
#include <vector>
template<typename Pair>
class pair_generator {
public:
explicit pair_generator(std::vector<Pair>& cont)
: cont_(cont)
{ }
template<typename T>
bool operator()(T l, T r) {
cont_.emplace_back(r, l);
return true;
}
private:
std::vector<Pair>& cont_;
};
template<typename Pair>
struct position_independant_compare {
explicit position_independant_compare(const Pair& pair)
: pair_(pair)
{ }
bool operator()(const Pair & p) const {
return (p.first == pair_.first && p.second == pair_.second) || (p.first == pair_.second && p.second == pair_.first);
}
private:
const Pair& pair_;
};
template<typename T>
using pair_of = std::pair<T, T>;
template<typename T>
std::ostream & operator <<(std::ostream & stream, const pair_of<T>& pair) {
return stream << '[' << pair.first << ", " << pair.second << ']';
}
int main() {
std::vector<int>
v1 {0 ,1, 2, 3, 4, 5},
v2 {4, 8, 6, 2, 1, 5, 0, 3};
std::vector<pair_of<int> >
p1 { },
p2 { };
// generate our pairs
std::sort(v1.begin(), v1.end(), pair_generator<pair_of<int>>{ p1 });
std::sort(v2.begin(), v2.end(), pair_generator<pair_of<int>>{ p2 });
// account for the fact that the first and last element are a pair too
p1.emplace_back(p1.front().first, p1.back().second);
p2.emplace_back(p2.front().first, p2.back().second);
std::cout << "pairs for vector 1" << std::endl;
for(const auto & p : p1) { std::cout << p << std::endl; }
std::cout << std::endl << "pairs for vector 2" << std::endl;
for(const auto & p : p2) { std::cout << p << std::endl; }
std::cout << std::endl << "pairs shared between vector 1 and vector 2" << std::endl;
for(const auto & p : p1) {
const auto pos = std::find_if(p2.begin(), p2.end(), position_independant_compare<pair_of<int>>{ p });
if(pos != p2.end()) {
std::cout << p << std::endl;
}
}
}
Example output on ideone
In-situ:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <tuple>
#include <vector>
template<typename T>
struct in_situ_pair
: std::iterator<std::forward_iterator_tag, T> {
using pair = std::pair<T, T>;
in_situ_pair(std::vector<T>& cont, std::size_t idx)
: cont_(cont), index_{ idx }
{ }
pair operator*() const {
return { cont_[index_], cont_[(index_ + 1) % cont_.size()] };
}
in_situ_pair& operator++() {
++index_;
return *this;
}
bool operator==(const pair& r) const {
const pair l = operator*();
return (l.first == r.first && l.second == r.second)
|| (l.first == r.second && l.second == r.first);
}
bool operator==(const in_situ_pair& o) const {
return (index_ == o.index_);
}
bool operator!=(const in_situ_pair& o) const {
return !(*this == o);
}
public:
friend bool operator==(const pair& l, const in_situ_pair& r) {
return (r == l);
}
private:
std::vector<T>& cont_;
std::size_t index_;
};
template<typename T>
using pair_of = std::pair<T, T>;
template<typename T>
std::ostream & operator <<(std::ostream & stream, const pair_of<T>& pair) {
return stream << '[' << pair.first << ", " << pair.second << ']';
}
namespace in_situ {
template<typename T>
in_situ_pair<T> begin(std::vector<T>& cont) { return { cont, 0 }; }
template<typename T>
in_situ_pair<T> end(std::vector<T>& cont) { return { cont, cont.size() }; }
template<typename T>
in_situ_pair<T> at(std::vector<T>& cont, std::size_t i) { return { cont, i }; }
}
int main() {
std::vector<int>
v1 {0 ,1, 2, 3, 4, 5},
v2 {4, 8, 6, 2, 1, 5, 0, 3};
for(std::size_t i = 0; i < v1.size(); ++i) {
auto pos = std::find(in_situ::begin(v2), in_situ::end(v2), in_situ::at(v1, i));
if(pos != in_situ::end(v2)) {
std::cout << "common: " << *pos << std::endl;
}
}
}
Example output on ideone
There have been a lot of great answers, and I'm sure people searching for the general problem of looking for adjacent pairs of equal elements in two vectors will find them enlightening. I have decided to answer my own question because I think a neater version of my original attempt is the best answer for me.
Since there doesn't seem to be a combination of std algorithms that make the methodology simpler, I believe looping and querying each element to be the most concise and understandable.
Here is the algorithm for the general case:
std::vector<int> vec1 = { 1, 2, 3, 4, 5, 6 };
std::vector<int> vec2 = { 3, 1, 4, 2, 6, 5 };
// Loop over the elements in the first vector, looking for an equal element in the 2nd vector
for(int i = 0; i < vec1.size(); i++) for(int j = 0; j < vec2.size(); j++)
if ( vec1[i] == vec2[j] &&
// ... Found equal elements, now check if the next element matches the next or previous element in the other vector
( vec1[(i+1) % vec1.size()] == vec2[(j+1) % vec2.size()]
||vec1[(i+1) % vec1.size()] == vec2[(j-1+vec2.size()) % vec2.size()] ) )
return true;
return false;
Or in my specific case, where I am actually checking a vector of vectors, and where the elements are no longer ints, but pointers to a class.
(The operator[] of the Face class returns an element of a vector belonging to the face).
bool isSurrounded(std::vector<Face*> * neighbours)
{
// We can check if each edge aligns with an edge in a nearby face,
// ... if each edge aligns, then the face is surrounded
// ... an edge is defined by two adjacent points in the points_ vector
// ... so we check for two consecutive points to be equal...
int count = 0;
// for each potential face that is not this face
for(auto&& i : *neighbours) if (i != this)
// ... loop over both vectors looking for an equal point
for (int j = 0; j < nPoints(); j++) for (int k = 0; k < i->nPoints(); k++ )
if ( (*this)[j] == (*i)[k] &&
// ... equal points have been found, check if the next or previous points also match
( (*this)[(j+1) % nPoints()] == (*i)[(k+1) % i->nPoints()]
|| (*this)[(j+1) % nPoints()] == (*i)[(k-1+i->nPoints()) % i->nPoints()] ) )
// ... an edge is shared
{ count++; }
// number of egdes = nPoints -1
if (count > nPoints() - 1)
return true;
else
return false;
}
I'm trying to implement a container in C++ that uses a flat array to store the data but iterates over that data in pairs. Now I could easily change the implementation such that the container holds a vector of std::pair however I want to iterate through pairs starting at element 0 or at element 1.
To illustrate what I want to achieve, if my underlying array looks like:
1,2,3,4,5,6,7,8
I want to define two iterators, one which returns the pairs:
(1,2), (3,4), (5,6), (7,8)
and the second iterator to return the pairs:
(2,3), (4,5), (6,7)
is this possible to do while still allowing the elements of the iterator to be references of the underlying array?
It is possible to write your own iterator, which iterates over the elements. The following question shows some explanations on how that is done:
Custom Iterator in C++.
You can then return the desired values as std::pair and iterate to the next element-pair (by incrementing the counter by 2).
Boost library has got Iterator Adaptor that allows you to wrap other iterator types and change or adapt their functionality. Here's how you could use it for your purpose:
#include <boost/iterator/iterator_adaptor.hpp>
#include <vector>
struct iterator :
public boost::iterator_adaptor<
iterator, // the name of our class, see docs for details
std::vector<int>::iterator, // underlying base iterator
std::pair<int&, int&>, // our value type
boost::forward_traversal_tag // the category you wish to give it
>
{
// need this to convert from vector::iterator to ours
explicit iterator(std::vector<int>::iterator i)
: iterator::iterator_adaptor_(i) {}
value_type operator*()
{
return value_type(
*base_reference(),
*(base_reference()+1)
);
}
};
Example of usage:
std::vector<int> v {1,2,3,4};
iterator it(v.begin());
++it;
(*it).first = 0; // TODO: operator->
(*it).second = 0;
for (int i : v) std::cout << i << ' '; // prints 1 0 0 4
You'll also need to override comparison to properly handle end condition, etc. Hope that helps.
Just thought I'd put in what I actually used in my code. I didn't want to use boost as suggested by #jrok but the type std::pair<int&, int&> in their answer gave me a hint of what was required.
Below is the class that I constructed which uses two iterators. A RepeatIterator that returns pairs starting on even indexes in the underlying data, and a SpacerIterator that returns pairs starting on odd indexes.
class RepeatArray {
typedef std::vector<int> storage_t;
public:
class RepeatIterator {
public:
typedef RepeatIterator self_t;
typedef int value_t;
typedef int& reference_t;
typedef int* pointer_t;
typedef std::pair<reference_t, reference_t> return_t;
RepeatIterator(storage_t::iterator input) : current_pos(input){}
return_t operator *() {
return return_t(*(current_pos), *(current_pos + 1 ));
}
self_t operator++() { self_t i = *this; current_pos += 2; return i; }
self_t operator++(int junk) { current_pos+=2; return *this; }
bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }
private:
storage_t::iterator current_pos;
};
class SpacerIterator {
public:
typedef SpacerIterator self_t;
typedef int value_t;
typedef int& reference_t;
typedef int* pointer_t;
typedef std::pair<reference_t, reference_t> return_t;
SpacerIterator(storage_t::iterator input) : current_pos(input){}
return_t operator *() {
return return_t(*(current_pos), *(current_pos + 1 ));
}
self_t operator++() { self_t i = *this; current_pos += 2; return i; }
self_t operator++(int junk) { current_pos+=2; return *this; }
bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }
private:
storage_t::iterator current_pos;
};
void add(int start, int end) {
positions.push_back(start);
positions.push_back(end);
}
void dump() {
for (auto i : positions) {
std::cout <<i<<",";
}
std::cout <<std::endl;
}
RepeatIterator repeatBegin(){return RepeatIterator(positions.begin());}
RepeatIterator repeatEnd(){return RepeatIterator(positions.end());}
SpacerIterator spacerBegin(){return SpacerIterator(positions.begin() + 1);}
SpacerIterator spacerEnd(){return SpacerIterator(positions.end() - 1);}
protected:
storage_t positions;
};
And then the tesing program compiled using clang++ -std=c++0x -o testRepeatArray RepeatArray.cpp
int main() {
RepeatArray r = RepeatArray();
r.add(1,3);
r.add(7,12);
std::cout<<"original:"<<std::endl;
r.dump();
std::cout << "Testing Repeat iterator:"<<std::endl;
for (RepeatArray::RepeatIterator it2 = r.repeatBegin(); it2 != r.repeatEnd(); ++it2) {
std::cout << (*it2).first <<","<< (*it2).second << std::endl;
}
std::cout << "Testing Spacer iterator:"<<std::endl;
for (RepeatArray::SpacerIterator it3 = r.spacerBegin(); it3 != r.spacerEnd(); ++it3) {
std::cout << (*it3).first <<","<< (*it3).second << std::endl;
}
std::cout<<"Testing modification:"<<std::endl;
RepeatArray::RepeatIterator it = r.repeatBegin();
(*it).first = 0;
(*it).second = 123;
r.dump();
return 0;
}