I am having trouble searching for and printing out pairs of elements in a vector that are separated by 2 from left to right. I need to collect the pairs
The example data that I am operating on is:
std::vector<int> myvector = { 1, 3, 3, 5, 7, 9, 13, 10, 12 };
Given that the std::adjacent_find predicate is:
static const auto gAdjacentPred = [](
const int& lhs, const int& rhs) {
std::cout
<< "(" << lhs << ":" << rhs << ")?"
<< std::string((rhs == lhs+2)? "true" : "false")
<< std::endl;
return (rhs == lhs+2);
};
I was expecting to get the following result (with multiple calls to the predicate along the way):
{1,3}, {3,5}, {5,7}, {7,9} & {10,12}
Ideally thought (and I have no idea how to do this) I would like to merge the values that satisfy the predicate in the middle of the input data ... 3, 5, 7, 9 ... as a single result {3, 9}.
The problem is that I do not really understand how to properly loop over the collection. I did see that std::next(iter) is a trick that I can use to peek ahead at the right most value satisfying the lambda, however this can sometimes point to the end of the collection.
I was expecting that the way I was looping over the data would show multiple calls to the predicate as it iterated over the collection - as it turns out it only calls the predicate function one time (when I assign to the adjIter. Also, in the results I see that the pair 13 & 10 seems to satisfy the predicate. Could someone explain what is going on here as I need to find pairs from left to right that differ by some value - in my case here 2 (with the left side less than the right (I am searching for increasing values from left to right).
(1:3)?true
{1,3}
{3,5}
{7,9}
{13,10}
The problem is that the last pair is also considered
static const auto gAdjacentPred = [](
const int& lhs, const int& rhs) {
std::cout
<< "(" << lhs << ":" << rhs << ")?"
<< std::string((rhs == lhs+2)? "true" : "false")
<< std::endl;
return (rhs == lhs+2);
};
std::vector<int> myvector = { 1, 3, 3, 5, 7, 9, 13, 10, 12 };
auto adjIter = std::adjacent_find (
myvector.begin(), myvector.end(),
gAdjacentPred);
while (adjIter != myvector.cend()) {
auto second = std::next(adjIter);
// print both sides
if (second != myvector.cend()) {
std::cout << "{" << *adjIter << "," << *second << "}" << std::endl;
adjIter +=2;
} else {
adjIter++;
}
}
Related
I was playing around with std::list. Similarly to other containers, std::list::end refers to the past-the-end element of a std::list (ref).
So, we would expect the below code to print 1, 2, 3, 4, 5 (which it does):
std::list<int> l { 1, 2, 3, 4, 5 };
for (auto it = l.begin(); it != l.end(); ++it)
{
std::cout << *it << ", ";
}
std::cout << std::endl;
However, the second line of the second code snippet should not print 5, but it does:
std::cout << *l.begin() << std::endl;
std::cout << *l.end() << std::endl;
Output: 1 and 5.
Why? I'm using GCC 11 and C++11 (same for C++20 btw).
You can see the reason if you build in debug mode, with the -D_GLIBCXX_DEBUG command line flag:
/usr/include/c++/8/debug/safe_iterator.h:270:
Error: attempt to dereference a past-the-end iterator.
Objects involved in the operation:
iterator "this" # 0x0x7fff50ac8670 {
type = __gnu_debug::_Safe_iterator<std::__cxx1998::_List_iterator<int>, std::__debug::list<int, std::allocator<int> > > (mutable iterator);
state = past-the-end;
references sequence with type 'std::__debug::list<int, std::allocator<int> >' # 0x0x7fff50ac85d0
}
Aborted
As with other containers, dereferencing the end() iterator is undefined. It only happens to work by accident in non-debug mode.
This question already has answers here:
Range based loop: get item by value or reference to const?
(5 answers)
Closed 6 years ago.
When we need to use " &" and when not to?
for example in below, both for loops produce identical result.
std::vector< Product* > itemByColor = pF.by_color( vecProds, Color::Red );
for( auto i : itemByColor )
{
std::cout << " product name <<" << i->name<< std::endl;
}
AND
for( auto& i : itemByColor )
{
std::cout << " product name <<" << i->name<< std::endl;
}
More or less the same as whether you would decide to type std::string or (const) std::string&. That is, whether you want to copy the object or to take a reference to it.
std::vector<int> my_vector{ 1, 2, 3, 4, 5 };
int copy = my_vector[ 0 ];
int& reference = my_vector[ 0 ];
++copy;
std::cerr << my_vector[ 0 ] << '\n'; // Outputs '1', since the copy was incremented, not the original object itself
++reference;
std::cerr << my_vector[ 0 ] << '\n'; // Outputs '2', since a reference to the original object was incremented
// For each 'n' in 'my_vector', taken as a copy
for( auto n : my_vector )
{
// The copy ('n') is modified, but the original remains unaffected
n = 123;
}
// For each 'n' in 'my_vector', taken as a reference
for( auto& n : my_vector )
{
// The original is incremented by 42, since 'n' is a reference to it
n += 42;
}
// At this point, 'my_vector' contains '{ 44, 44, 45, 46, 47 }'
Suppose I have an unsorted integer array {3, -1, 4, 5, -3, 2, 5}, and I want to find the maximum non-repeating number (4 in this case) (5 being invalid as it is repeated). How can I achieve this?
Use an unordered map to count the frequencies of each element. (As an optimization, keep track of largest element encountered and skip elements lower than that.) Then, scan the map to find out the largest element with frequency exactly equal to 1.
template <typename T> // numeric T
pair<T, bool> FindMaxNonRepeating(vector<T> const& vec) {
unordered_map<T, int> elem2freq;
for (auto const& elem : vec) {
elem2freq[elem] += 1;
}
T largest_non_repetitive = std::numeric_limits<T>::min();
bool found = false;
for (auto const& item : elem2freq) {
if (item.first > largest_non_repetitive && item.second == 1) {
largest_non_repetitive = item.first;
found = true;
}
}
return {largest_non_repetitive, found};
}
This runs in time complexity O(n) and requires space complexity O(n).
Sort the array in descending order.
Begin from top element and store it a variable, say max.
Check next element with max, if they are the same, repeat until
you find the next max, otherwise, you found the max non-repeated
number.
Time complexity: O(nlogn)
c++ implementation, based on my Sort (C++):
#include <algorithm>
#include <iostream>
#include <vector>
#include <limits>
#include <cstddef>
using namespace std;
void printVector(vector<int>& v)
{
for(vector<int>::iterator it = v.begin() ; it != v.end() ; it++)
cout << *it << ' ';
cout << endl;
}
bool compar(const int& a, const int& b)
{
return (a > b) ? true : false;
}
int main()
{
vector<int> v = {3, -1, 4, 5, -3, 2, 5};
cout << "Before sorting : " << endl;
printVector(v);
sort(v.begin(), v.end(), compar);
cout << endl << "After sorting : " << endl;
printVector(v);
int max_non_repeat = numeric_limits<int>::min();
for(unsigned int i = 0; i < v.size(); ++i)
{
if(max_non_repeat == v[i])
max_non_repeat = numeric_limits<int>::min();
else if(v[i] > max_non_repeat)
max_non_repeat = v[i];
}
cout << "Max non-repeated element: " << max_non_repeat << endl;
return 0;
}
Output:
C02QT2UBFVH6-lm:~ gsamaras$ g++ -Wall -std=c++0x main.cpp
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
Before sorting :
3 -1 4 5 -3 2 5
After sorting :
5 5 4 3 2 -1 -3
Max non-repeated element: 4
For maximum pleasure, do base your (a different) approach on How to find max. and min. in array using minimum comparisons? and modify it accordingly.
I have tried to fill a smaller vector of a vector of pairs with some contents from a bigger vector of a vector of pairs without success. Below is the relevant code with couts and their output. Hopefully this is detailed enough.
/*******************Problems Occur*****************/
int iFirst=problemsStartAt;//first index to copy
int iLast=problemsEndAt-1;//last index -1, 11th stays
int iLen=iLast-iFirst;//10-8=2
//if(problemsStartAt!=0)//I.a
if(problemsStartAt!=0&&problemsEndAt!=0)//I.b
{
v_problem_temp=allPathCoordinates[problemsStartAt];
cout<<"266:"<<v_problem_temp.size()<<endl;
cout<<"267:"<<allPathCoordinates.at(1).size()<<endl;
for(vector<pair<int,int>>::iterator it2=v_problem_temp.begin();
it2!=v_problem_temp.end();
++it2)
{
apair=*it2;
point[apair.first][apair.second]=Yellow;
cout<<apair.first<<","<<apair.second<<endl;
}
problemsPathCoordinate.resize(iLen);
cout<<"iLen*sizeof(problemsPathCoordinate):" <<iLen*sizeof(problemsPathCoordinate)<<endl;
memcpy(&problemsPathCoordinate[0],&allPathCoordinates[iFirst],iLen*sizeof(problemsPathCoordinate));
cout<<"279:problemsPathCoordinate.size():"<<problemsPathCoordinate.size()<<endl;
problemsPathCoordinate.resize(iLen);
memcpy(&problemsPathCoordinate[0],&allPathCoordinates[iFirst],iLen*sizeof(problemsPathCoordinate));
cout<<"283:problemsPathCoordinate.size():"<<problemsPathCoordinate[0].size()<<endl;
cout<<"284:problemsPathCoordinate.size():"<<problemsPathCoordinate[1].size()<<endl;
cout<<"286:allPathCoordinates.size():"<<allPathCoordinates.size()<<endl;
cout<<"287:allPathCoordinates.size():"<<allPathCoordinates.size()<<endl;
//from http://stackoverflow.com/questions/35265577/c-reverse-a-smaller-range-in-a-vector
}
Output:
759: path NOT full-filled, number: 8
755: Problems START here at:8
759: path NOT full-filled, number: 9
700: Problems END here at: 11
266:0
267:0
iLen*sizeof(problemsPathCoordinate):72
279:problemsPathCoordinate.size():3
283:problemsPathCoordinate.size():0
284:problemsPathCoordinate.size():0
286:allPathCoordinates.size():79512
287:allPathCoordinates.size():79512
time:39 seconds
Why are the three problemsPathCoordinate elements empty. How to fix it?
Bo
for (vector< vector > >::iterator it = allPathCoordinates.begin(); it != allPathCoordinates.end(); ++it)
{
allPathCoordinates.erase(allPathCoordinates.begin()+5,allPathCoordinates.end()-2);
v_temp = *it;
//cout<<"v_temp.size():"<
for (vector<pair<int,int> >::iterator it2 = v_temp.begin(); it2 != v_temp.end(); ++it2) {
//v_temp.erase(v_temp.begin()+2);
apair = *it2;
//cout << "(" << apair.first << "," << apair.second << ") ; ";
openPoints[apair.first][apair.second]=0;
closedPoints[apair.first][apair.second]=1;
allObstacles[apair.first][apair.second]=Wall;
point[apair.first][apair.second]=Yellow;
}
/
Is there a single one-liner to find the largest element smaller than some element x in a sorted container? I'm essentially interested in any code that will give me an iterator pointing to the largest element smaller than x.
I know how to code this up myself, but would hope that there is a library function for it...
EDIT: Maybe I should make myself clear here, that the version I have in mind that I would code myself is based on binary search and thus runs in O(log n) time. I need to compute this for lists with up to a few million elements.
Since your container is sorted, you can use std::max_element on a range ending with the first element greater than your max, use std::find_if with a lambda, or std::lower_bound to get this range :
int main()
{
std::set<int> s{ 3, 1, -14, 1, 5, 9 };
std::set<int>::iterator result;
int max_value = 6;
result = std::max_element(std::begin(s), std::find_if(std::begin(s), std::end(s), [&](int i) { return i >= max_value; } ) );
std::cout << "max element is: " << *result;
}
Output :
max element is: 5
Live Demo
Or with std::lower_bound :
int main()
{
std::set<int> s{ 3, 1, -14, 1, 5, 9 };
std::set<int>::iterator result;
int max_value = 6;
result = std::max_element(std::begin(s), std::lower_bound(std::begin(s), std::end(s), max_value)) ;
std::cout << "max element is: " << *result;
}
Live Demo
You can just use
lower_bound(container.begin(), container.end(), currentElement);
Now if that is different than container.begin() then there is an element that is smaller than your current one, just substract one and you get it. If you are sure there is always such an element just do
lower_bound(container.begin(), container.end(), currentElement) - 1;
EDIT: Of course I assume that your iterator is bidirectional.
Use prev() in combination with lower_bound()
mycontainer.lower_bound(int_val) returns an iterator to the number that's equal to or greater than int_val
*prev(mycontainer.lower_bound(int_val)) returns the value just before int_val in the container
As a defensive check, first validate that it's not at the beginning of the container:
int result = -1, target = 15;
set<int> _container;
auto _iterator = _container.lower_bound(target);
if(_iterator != _container.begin())
result = *std::prev(_iterator);
Assuming that you have your data in a set s of integers, you can find the largest element smaller than x as follows:
auto it = s.lower_bound( x ); // s.lower_bound has a complexity of O(logn)
if( it == s.begin() )
{
std::cout << "No element found" << "\n";
}
else
{
--it;
std::cout << *it << "\n";
}
lower_bound essentially returns you an iterator it pointing to the smallest element which is >= x. Therefore, it's just previous pointer --it would point to the largest element which is < x. Complexity of this approach is O(log n).