Determining if two vectors contain two adjacent items the same - c++

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;
}

Related

How to count the equal elements of 2 different vectors in c++?

I am trying to find a way to count how many elements are equal in 2 different vectors of the same size in c++. The vectors hold structs and i want to compare the equality by a double variable of the struct shown on the example.
And to make it clear. I do NOT want to check if the 2 vectors are equal but only to count how many of their elements are.
The following doesn't work. It gives addresses instead of values. Also If I try to access the dist variable like pointsA[j].dist I get an error.
vector<struct PointWithDistance*> pointsA, pointsB;
//the struct
struct PointWithDistance {
Point *p;
double dist;
};
for (int j = 0; j < k; j++){
if (pointsA[j] == pointsB[j])
equalCount++;
}
vector<struct PointWithDistance*> pointsA, pointsB;
Did you mean to use pointers? If so, you have to do *(points[A]) (and b) because your current comparison compares the pointers, not their content.
Also, does the struct Point have an operator == so comparison on the type can be performed??
Do you want to force same positions? say, a vector {1,2,3} and a vector {2,3,4} by your algorithm will have 0 items equal, do you want that? If not, loop the first vector and use std::find (or std::upper_bound if the vector is sorted) on each element to the second vector.
Some quick code:
template <typename T=int> struct Point
{
T x,y;
bool operator==(const T& t) { return (x == t.x && y == t.y); }
};
std::vector<Point<>> p1 = {1,2,3};
std::vector<Point<>> p2 = {2,3,4};
for(auto& p : p1)
{
if (std::find(p2.begin(),p2.end(),p) != p2.end())
{
// similar++;
}
}
// or
assert(p1.size() == p2.size());
for(size_t i1 = 0 ; i1 < p1.size() ; i1++)
{
if (p1[i1] == p2[i1])
{
// equal++;
}
}
A generic solution to count the number of duplicates in 2 containers could look like this. Using std::transform_reduce to add (std::plus<>{}) the boolean result if an element was found in the container. Note how it can accep two different types of containers as long as their contained type stays the same (e.g. std::vector<int> and std::set<int>). The length of the containers don't have to be equal. There are two SFINAE implementations to differenciate between the case where T is a pointer and where it isn't:
#include <algorithm> //std::find, std::find_if
#include <cstddef> //std::size_t
#include <functional> //std::plus,
#include <iterator> //std::cbegin, std::cend
#include <numeric> //std::transform_reduce
#include <type_traits> //std::enable_if_t, std::is_pointer_v
namespace {
//core implementation for duplicate_count
template<class C, class F>
std::size_t duplicate_count_impl(const C& container, F pred) {
return std::transform_reduce(std::cbegin(container), std::cend(container), std::size_t{}, std::plus<>{}, pred);
}
}
//returns the number of duplicates in two (different) containers.
//overload for containers where T is a pointer type.
template<typename T, template <typename...> class C1, template <typename...> class C2, std::enable_if_t<std::is_pointer_v<T>>* = nullptr>
std::size_t duplicate_count(const C1<T>& a, const C2<T> &b) {
return duplicate_count_impl(b, [&](T ptr_b) -> bool {
return std::find_if(std::cbegin(a), std::cend(a), [&](T ptr_a) -> bool {
return *ptr_a == *ptr_b;
}) != std::cend(a);
});
}
//returns the number of duplicates in two (different) containers.
//overload for containers where T is not a pointer type.
template<typename T, template <typename...> class C1, template <typename...> class C2, std::enable_if_t<!std::is_pointer_v<T>>* = nullptr>
std::size_t duplicate_count(const C1<T>& a, const C2<T> &b) {
return duplicate_count_impl(b, [&](T n) -> bool {
return std::find(std::cbegin(a), std::cend(a), n) != std::cend(a);
});
}
#include <iostream>
#include <vector>
#include <list>
//[duplicate_count implementations]
struct Point {
int a, b;
bool operator==(const Point& other) const {
return this->a == a && this->b == other.b;
}
};
int main() {
{
std::list<int> v = { 1, 2, 7, 7 };
std::list<int> u = { 0, 1, 2, 7 };
std::cout << "list<int>\t number of duplicates: " << duplicate_count(v, u) << '\n';
}
{
auto[a, b, c, d] = std::make_tuple(0, 1, 2, 3);
std::vector<int*> v = { &b, &c, &d, &d };
std::vector<int*> u = { &a, &b, &c, &d };
std::cout << "vector<int*>\t number of duplicates: " << duplicate_count(v, u) << '\n';
}
{
auto[a, b, c, d] = std::make_tuple(
Point{ 0, 0 },
Point{ 1, 1 },
Point{ 2, 2 },
Point{ 4, 4 });
std::vector<Point*> v = { &b, &c, &d, &d };
std::vector<Point*> u = { &a, &b, &c, &d };
std::cout << "vector<Point*>\t number of duplicates: " << duplicate_count(v, u) << '\n';
}
}
list<int> number of duplicates: 3
vector<int*> number of duplicates: 3
vector<Point*> number of duplicates: 3
Your shown solution is good, fast and efficient.
It has some minor problem that can easily be resolved. In your definition vector<struct PointWithDistance*> pointsA, pointsB;, variables pointsA and pointsB are vectors, containing pointer to structs.
With pointsA[n] you will get a pointer to the struct. But you want the struct by itself. So you simply need to dereference the gotten pointer. And since you want to access a member of a struct (usually done with variable.member), you can use (*(pointsA[j])).dist or pointsA[j]->dist.
If the size of your vectors are guaranteed the same, then you simply need to update your code to
vector<struct PointWithDistance*> pointsA, pointsB;
//the struct
struct PointWithDistance {
Point *p;
double dist;
};
for (int j = 0; j < k; j++){
if (pointsA[j]->dist == pointsB[j]->dist)
equalCount++;
}
That is the only thing you were missing.
You can use the std::inner_product algorithm:
#include <iostream>
#include <numeric>
#include <vector>
int main () {
const std::vector a{7, 7, 7, 7};
const std::vector b{7, 6, 7, 7};
const auto equalCount = std::inner_product(
a.begin(), a.end(), b.begin(), 0,
std::plus<>(), std::equal_to<>()
);
std::cout << equalCount << " of the elements are equal.\n";
}
outputs
3 of the elements are equal.
It is a generalization of the standard inner product,
using the functions + (plus) and == (equal_to),
instead of + and *.
Thus it computes
0 + (a[0] == b[0]) + (a[1] == b[1]) + ....
This uses the fact that false/true can be interpreted as 0/1.

Minimum return value for range

I was wondering if there was a standard function that returns the minimum/maximum of the return values for a given range of elements. Something like this:
std::vector<int> list = { -2, -1, 6, 8, 10 };
auto it =
std::find_min_return_value(list.begin(), list.end(), std::abs, std::less<int>);
// it should be the iterator for -1
If there is no such, what is the best approach for a problem like this?
My list is long, I really don't want to copy it, and also don't want to call the function whose minimum return value I look for more than once per element. Thanks!
UPDATE:
Based on ForEveR's suggestion to use std::min_element, I made the following benchmarking tests:
std::vector<double> list = { -2, -1, 6, 8, 10 };
auto semi_expensive_test_function = [] (const double& a) { return asin(sin(a)); };
for(int i = 0; i < 10000000; ++i)
{
auto it = std::min_element(list.begin(), list.end(),
[&] (const double& a, const double& b) mutable
{
return(semi_expensive_test_function(a) < semi_expensive_test_function(b));
});
}
This worked just fine:
./a.out 11.52s user 0.00s system 99% cpu 11.521 total
After modifying the code to use a stateful lambda instead:
for(int i = 0; i < 10000000; ++i)
{
auto it = std::min_element(list.begin() + 1, list.end(),
[&, current_min_value = semi_expensive_test_function(*(list.begin()))] (const double& a, const double& b) mutable
{
double current_value = semi_expensive_test_function(b);
if(current_value < current_min_value)
{
current_min_value = std::move(current_value);
return true;
}
return false;
});
}
This resulted:
./a.out 6.34s user 0.00s system 99% cpu 6.337 total
Using stateful lambdas seems to be the way to go. The question is: is there a more code-compact way to achieve this?
With range-v3, it would be something like:
ranges::min(list, std::less<>{}, [](auto e) { return std::abs(e); });
Well, assuming Boost is like the standard library nowadays, you might use this:
#include <boost/range/adaptor/transformed.hpp>
#include <algorithm>
int main()
{
std::vector<int> list = { -2, -1, 6, 8, 10 };
auto abs_list = list | boost::adaptors::transformed(+[](int v) { return std::abs(v); });
// ^ - read http://stackoverflow.com/questions/11872558/using-boost-adaptors-with-c11-lambdas
auto it = std::min_element(abs_list.begin(), abs_list.end(), std::less<int>{});
std::cout << *it;
}
If it'll get reused, and to give you another option, you could write your own generic algorithm following std conventions.
template <typename T, typename ForwardIt, typename UnaryFunction, typename Comparator>
ForwardIt find_min_return_value(ForwardIt first, ForwardIt last, UnaryFunction op, Comparator compare)
{
if (first == last)
return last;
ForwardIt smallestItr = first;
T smallestValue = op(*first);
for (auto itr = first + 1; itr != last; ++itr)
{
T current = op(*itr);
if (compare(current, smallestValue))
{
smallestValue = current;
smallestItr = itr;
}
}
return smallestItr;
}
Usage is then quite code-compact, and the operation will only be performed once per element:
int main()
{
std::vector<int> list = { -2, -1, 6, 8, 10 };
auto it1 = find_min_return_value<int>(list.begin(), list.end(), [](int i){ return std::abs(i); }, std::less<int>());
std::vector<std::string> strings = { "Lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit" };
auto it3 = find_min_return_value<size_t>(strings.begin(), strings.end(), [](std::string s){ return s.length(); }, std::less<size_t>());
std::cout << *it1 << "\n"; // outputs -1
std::cout << *it3 << "\n"; // outputs sit
}
If you only suspect it may get reused one day it probably won't, and it's then overly complicated, and should then be just a simple function.

How to count equal, adjacent elements in a vector?

Lets say I have a vector<int> { 1, 1, 2, 3, 3, 3, 1, 1 } and I'd like to convert this into a vector<std::pair<int, int>> { {1, 2}, {2, 1}, {3, 3}, {1, 2} } of 'adjacent element counts':
I'd probably iterate over the vector with a flag indicating the start of a new 'adjacency set' and a counter which counts the number of consecutive elements. I was just wondering if there isn't already a more abstract and elegant solution in the STL as this seems like a very common use-case. Algorithms like unique, adjacent_find or equal_range seem pretty close to what I'm looking for but just not quite the right thing and probably no gain to implementing it from scratch myself.
From an algorithmic point of view the closest thing is run-length encoding I would say. I don't think there is a ready made algorithm to do that, but the code should be trivial:
std::vector<std::pair<int, int>> out;
for (int i: in)
{
if (out.empty() || out.back().first != i)
{
out.emplace_back(i, 1);
}
else
{
++out.back().second;
}
}
Live-example.
Eric Niebler's range library, which, AFAIU is in the process of becoming part of the standard library, has a group_by which is very similar to Python's itertools.groupby, and groups consecutive equivalent elements, just as you need.
To group your vector, you'd start with
const vector<int> l{ 1, 1, 2, 3, 3, 3, 1, 1 };
auto x = l | view::group_by(std::equal_to<int>());
which means that x is a view where adjacent integers belong to a group, if the integers are equal.
Now to iterate, and say, print each consecutive group and its size, you could do the following (I'm sure you can do it better than the following, but this is the limit of my use of this library):
for (auto i = x.begin();i != x.end(); ++i)
cout << *((*i).begin()) << " " << to_vector(*i).size() << endl;
Example
#include <vector>
#include <iostream>
#include <range/v3/all.hpp>
int main(int argc, char **argv) {
const std::vector<int> l{ 1, 1, 2, 3, 3, 3, 1, 1 };
auto x = l | ranges::view::group_by(std::equal_to<int>());
for (auto i = x.begin();i != x.end(); ++i)
std::cout << *((*i).begin()) << " " << ranges::to_vector(*i).size() << std::endl;
}
This prints out
$ ./a.out
1 2
2 1
3 3
1 2
As far as I know there is no such C++ library that will automatically do what you are asking.
Anyway, it is very simple to implement this though. Here is one way:
#include <iostream>
#include <vector>
using namespace std;
void count_equal_elements(vector<int>& vec, vector<pair<int,int> >& result){
if (vec.empty())
return;
int curr = vec[0];
int count = 1;
for (vector<int>::iterator it = vec.begin()+1; it != vec.end(); ++it){
if (curr == *it){
count++;
}
else{
result.push_back(make_pair(curr,count));
curr = *it;
count = 1;
}
}
result.push_back(make_pair(curr,count));
}
See it in ideone.
With std, you may do:
template <typename T>
std::vector<std::pair<T, std::size_t>>
adjacent_count(const std::vector<T>& v)
{
std::vector<std::pair<T, std::size_t>> res;
for (auto it = v.begin(), e = v.end(); it != e; /*Empty*/) {
auto it2 = std::adjacent_find(it, e, std::not_equal_to<>{});
if (it2 != e) {
++it2;
}
res.emplace_back(*it, std::distance(it, it2));
it = it2;
}
return res;
}
Demo
or
template <typename T>
std::vector<std::pair<T, std::size_t>>
adjacent_count(const std::vector<T>& v)
{
std::vector<std::pair<T, std::size_t>> res;
for (auto it = v.begin(), e = v.end(); it != e; /*Empty*/) {
const auto it2 = std::find_if(it, e, [&](const auto&x) { return x != *it; });
res.emplace_back(*it, std::distance(it, it2));
it = it2;
}
return res;
}
Demo

remove arbitrary list of items from std::vector<std::vector<T> >

I have a vector of vectors, representing an array. I would like to remove rows efficiently, ie with minimal complexity and allocations
I have thought about building a new vector of vectors, copying only non-deleted rows, using move semantics, like this:
//std::vector<std::vector<T> > values is the array to remove rows from
//std::vector<bool> toBeDeleted contains "marked for deletion" flags for each row
//Count the new number of remaining rows
unsigned int newNumRows = 0;
for(unsigned int i=0;i<numRows();i++)
{
if(!toBeDeleted[i])
{
newNumRows++;
}
}
//Create a new array already sized in rows
std::vector<std::vector<T> > newValues(newNumRows);
//Move rows
for(unsigned int i=0;i<numRows();i++)
{
if(!toBeDeleted[i])
{
newValues[i] = std::move(values[i]);
}
}
//Set the new array and clear the old one efficiently
values = std::move(newValues);
Is this the most effective way?
Edit : I just figured that I could avoid allocating a new array by moving rows down iteratively, this could be slightly more efficient and code is much more simple:
unsigned int newIndex = 0;
for(unsigned int oldIndex=0;oldIndex<values.size();oldIndex++)
{
if(!toBeDeleted[oldIndex])
{
if(oldIndex!=newIndex)
{
values[newIndex] = std::move(values[oldIndex]);
}
newIndex++;
}
}
values.resize(newIndex);
Thanks!
This can be solved using a variation on the usual erase-remove idiom, with a lambda inside the std::remove_if that looks up the index of the current row inside an iterator range of to be removed indices:
#include <algorithm> // find, remove_if
#include <iostream>
#include <vector>
template<class T>
using M = std::vector<std::vector<T>>; // matrix
template<class T>
std::ostream& operator<<(std::ostream& os, M<T> const& m)
{
for (auto const& row : m) {
for (auto const& elem : row)
os << elem << " ";
os << "\n";
}
return os;
}
template<class T, class IdxIt>
void erase_rows(M<T>& m, IdxIt first, IdxIt last)
{
m.erase(
std::remove_if(
begin(m), end(m), [&](auto& row) {
auto const row_idx = &row - &m[0];
return std::find(first, last, row_idx) != last;
}),
end(m)
);
}
int main()
{
auto m = M<int> { { 0, 1, 2, 3 }, { 3, 4, 5, 6 }, { 6, 7, 8, 9 }, { 1, 0, 1, 0 } };
std::cout << m << "\n";
auto drop = { 1, 3 };
erase_rows(m, begin(drop), end(drop));
std::cout << m << "\n";
}
Live Example.
Note: because from C++11 onwards, std::vector has move semantics, shuffling rows around in your std::vector<std::vector<T>> is done using simple pointer manipulations, regardless of your type T (it would be quite different if you want column-deletion, though!).

Structure to hold value by ranged key

I need a structure to hold a value based on a key that has a range.
My implementation is C++, so any STL or Boost would be excellent.
I have as range-key, which are doubles, and value
[0,2) -> value1
[2,5) -> value2
[5,10) -> value3
etc
Such that a search of 1.23 should return value1, and so on.
Right now I am using a vector containing all three parts, key1/key2/value, with custom searching, but it feels like there should be a cleaner structure.
Edit: Thanks all. Given the ranges in this case are supposed to be contiguous and non-overlapping, the use of upper_bound will work just fine. Thanks for the class Range solutions as well, they are filed away for future reference.
class Range
{
public:
Range( double a, double b ):
a_(a), b_(b){}
bool operator < ( const Range& rhs ) const
{
return a_ < rhs.a_ && b_ < rhs.b_;
}
private:
double a_;
double b_;
};
int main()
{
typedef std::map<Range, double> Ranges;
Ranges r;
r[ Range(0, 2) ] = 1;
r[ Range(2, 5) ] = 2;
r[ Range(5, 10) ] = 3;
Ranges::const_iterator it1 = r.find( Range( 2, 2 ) );
std::cout << it1->second;
Ranges::const_iterator it2 = r.find( Range( 2, 3 ) );
std::cout << it2->second;
Ranges::const_iterator it3 = r.find( Range( 6, 6 ) );
std::cout << it3->second;
return 0;
}
If your ranges are contiguous and non-overlapping, you should use std::map and the upper_bound member function. Or, you could use a sorted vector with the upper_bound algorithm. Either way, you only need to record the lowest value of the range, with the upper part of the range being defined by the next higher value.
Edit: I phrased that confusingly, so I decided to provide an example. In coding the example, I realized you need upper_bound instead of lower_bound. I always get those two confused.
typedef std::map<double, double> MyMap;
MyMap lookup;
lookup.insert(std::make_pair(0.0, dummy_value));
lookup.insert(std::make_pair(2.0, value1));
lookup.insert(std::make_pair(5.0, value2));
lookup.insert(std::make_pair(10.0, value3));
MyMap::iterator p = lookup.upper_bound(1.23);
if (p == lookup.begin() || p == lookup.end())
...; // out of bounds
assert(p->second == value1);
How about something along these lines:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <sstream>
class Range
{
public:
Range(double lower, double upper) : lower_(lower), upper_(upper) {};
Range(const Range& rhs) : lower_(rhs.lower_), upper_(rhs.upper_) {};
explicit Range(const double & point) : lower_(point), upper_(point) {};
Range& operator=(const Range& rhs)
{
lower_ = rhs.lower_;
upper_ = rhs.upper_;
return * this;
}
bool operator < (const Range& rhs) const
{
return upper_ <= rhs.lower_;
}
double lower_, upper_;
};
typedef std::string Thing;
typedef std::map<Range, Thing> Things;
std::string dump(const std::pair<Range,Thing> & p)
{
stringstream ss;
ss << "[" << p.first.lower_ << ", " << p.first.upper_ << ") = '" << p.second << "'" << endl;
return ss.str();
}
int main()
{
Things things;
things.insert( std::make_pair(Range(0.0, 5.0), "First") );
things.insert( std::make_pair(Range(5.0, 10.0), "Second") );
things.insert( std::make_pair(Range(10.0, 15.0), "Third") );
transform( things.begin(), things.end(), ostream_iterator<string> (cout,""), dump );
cout << "--------------------------------------" << endl;
things[Range(1.5)] = "Revised First";
transform( things.begin(), things.end(), ostream_iterator<string> (cout,""), dump );
return 0;
}
... program output:
[0, 5) = 'First'
[5, 10) = 'Second'
[10, 15) = 'Third'
--------------------------------------
[0, 5) = 'Revised First'
[5, 10) = 'Second'
[10, 15) = 'Third'