Suppose I want to get the index of the lower_bound of a value in a set and if i type
cout<<set.lower_bound(number)-set.begin()<<endl;
It is showing an error: no match for ‘operator-’
The same goes for maps as well,
However for arrays and vectors if i use
lower_bound(begin,end,val)-begin
it is showing the index
Why is that?
Yes, this because the operator - is not defined for the iterators of std::sets (bidirectional iterators) while it's defined for the arrays iterators (random access iterators).
Instead, you can use std::distance(), as follows
int main()
{
std::set<int> set {1, 2, 4, 5, 6};
int number = 3;
std::cout<<std::distance(set.begin(), set.lower_bound(number))<<std::endl;
}
And note that your sets will be ordered. I don't know what u expect.
And as john said there might be a design flaw. maybe you choose the wrong container for your purpose.
I was experimenting with a toy sample program:
map<int, char> foo { { 1, 'a' }, { 2, 'b' }, { 3, 'c' } };
vector<pair<decltype(foo)::key_type, decltype(foo)::mapped_type>> bar(size(foo));
sample(begin(foo), end(foo), begin(bar), size(foo), mt19937{ random_device{}() });
Live Example
But bar always contains the contents of foo in order. Is this a gcc implementation problem, or am I just repeatedly getting unlucky?
std::sample selects elements from the range you pass. From cppreference (emphasize mine):
Selects n elements from the sequence [first; last) such that each
possible sample has equal probability of appearance, and writes those
selected elements into the output iterator out. Random numbers are
generated using the random number generator g.
If n is greater than the number of elements in the sequence, selects last-first elements.
I think the docs could be more clear, but returning only last-first in case the number of requested elements is greater, only makes sense if each element is selected at maximum once.
Try:
map<int, char> foo { { 1, 'a' }, { 2, 'b' }, { 3, 'c' } };
vector<pair<decltype(foo)::key_type, decltype(foo)::mapped_type>> bar(size(foo)-1);
sample(begin(foo), end(foo), begin(bar), bar.size(), mt19937{ random_device{}() });
to get two random samples out of foo.
Also note that
The algorithm is stable only if PopulationIterator meets the
requirements of ForwardIterator
ie it was not just out of luck that you always got the same result.
Sampling is about returning some subset of a larger population.
It is not intended to return elements in a random order, or any other order. It could, but that's not really what it's there for.
cppreference hints at ordering in this statement:
The algorithm is stable only if PopulationIterator meets the requirements of ForwardIterator
"Stable" here means it would return results in the same order as the input, thus the order is guaranteed to not be random with a ForwardIterator. Related: What is stability in sorting algorithms and why is it important?
This also makes sense, since, similar to what's been noted in the comments, to be efficient, you'll first need to figure out which elements to pick, and then go through the iterator and pick the elements, since you can only iterate from one direction to the other. Thus it should be trivial to keep the elements in the same order.
As for when you're not using a ForwardIterator, it makes no guarantee about the order one way or the other. So, even if it might appear to be randomly ordered, it would not be wise to rely on this, as the randomness of the ordering may be implementation-dependent and it may or may not have high entropy.
If you want a random order, you should shuffle it.
What is the fastest way to see if two vectors are equal in c++?
I'm trying to find the fastest way to see if any row is equal to any column of a matrix, so element by element comparison and exiting the loop when not equal is not good enough.
Do not reinvent the wheel. You can use std::equal from <algorithm>.
It has the following complexity:
No applications of the corresponding predicate if InputIterator1 and InputIterator2 meet the requirements of random access iterators and last1 - first1 != last2 - first2. Otherwise, at most min(last1 - first1, last2 - first2) applications of the corresponding predicate.
That's what you were looking for.
See the documentation for further details.
As mentioned in the comments, there is a subtle difference between operator== and std::equal: the former doesn't work if types are different (as an example, std::vector<int> and std::vector<double>), the latter does work instead.
I tried to give the most generic solution.
If types are the same, of course operator== works like a charm, as mentioned by #Jarod42.
Simply use operator == of vector:
std::vector<int> v1{1, 2, 3, 4}, v2{1, 2, 3, 4};
bool are_equal = (v1 == v2);
Equality operator ( == ) is overloaded in C++ Vector STL. So you can easily compare those directly like comparing two integers.
To compare row and column of a matrix as you said, use a loop and compare rows and columns directly by ==.
Working in C++ in a Linux environment, I have a situation where a number of integer ranges are defined, and integer inputs map to different arbitrary integers based on which range they fall into. None of the ranges overlap, and they aren't always contiguous.
The "simplest" way to solve this problem is with a bunch of if-statements for each range, but the number of ranges, their bounds, and the target values can all vary, so if-statements aren't maintainable.
For example, the ranges might be [0, 70], called r_a, [101, 150], call it r_b, and [201, 400], call it r_c. Inputs in r_a map to 1, in r_b map to 2, and r_c map to 3. Anything not in r_a, r_b, r_c maps to 0.
I can come up with a data structure & algorithm that stores tuples of (bounds, map target) and iterates through them, so finding the target value takes linear time in the number of bounds pairs. I can also imagine a scheme that keeps the pairs ordered and uses a binary sort-ish algorithm against all the lower bounds (or upper bounds), finds the closest to the input, then compares against the opposing bound.
Is there a better way to accomplish the mapping than a binary-search based algorithm? Even better, is there some C++ library out that does this already?
The best approach here is indeed a binary search, but any efficient order-based search will do perfectly well. You don't really have to implement the search and the data structure explicitly. You can use it indirectly by employing a standard associative container instead.
Since your ranges don't overlap, the solution is very simple. You can immediately use a std::map for this problem to solve it in just a few lines of code.
For example, this is one possible approach. Let's assume that we are mapping an [ int, int ] range to an int value. Let's represent our ranges as closed-open ranges, i.e. if the original range is [0, 70], let's consider a [0, 71) range instead. Also, let's use the value of 0 as a "reserved" value that means "no mapping" (as you requested in your question)
const int EMPTY = 0;
All you need to do is to declare a map from int to int:
typedef std::map<int, int> Map;
Map map;
and fill it with each end of your closed-open ranges. The left (closed) end should be mapped to the desired value the entire range is mapped to, while the right (open) end should be mapped to our EMPTY value. For your example, it will look as follows
map[0] = r_a;
map[71] = EMPTY;
map[101] = r_b;
map[251] = EMPTY;
map[260] = r_c; // 260 adjusted from 201
map[401] = EMPTY;
(I adjusted your last range, since in your original example it overlapped the previous range, and you said that your ranges don't overlap).
That's it for initialization.
Now, in order to determine where a given value of i maps to all you need to do is
Map::iterator it = map.upper_bound(i);
If it == map.begin(), then i is not in any range. Otherwise, do
--it;
If the it->second (for the decremented it) is EMPTY, then i is not in any range.
The combined "miss" check might look as follows
Map::iterator it = map.upper_bound(i);
if (it == map.begin() || (--it)->second == EMPTY)
/* Missed all ranges */;
Otherwise, it->second (for the decremented it) is your mapped value
int mapped_to = it->second;
Note that if the original ranges were "touching", as in [40, 60] and [61, 100], then the closed-open ranges will look as [40, 61) and [61, 101) meaning that the value of 61 will be mapped twice during map initialization. In this case it is important to make sure that the value of 61 is mapped to the proper destination value and not to the value of EMPTY. If you map the ranges as shown above in the left-to-right (i.e. increasing) order it will work correctly by itself.
Note, that only the endpoints of the ranges are inserted into the map, meaning that the memory consumption and the performance of the search depends only on the total number of ranges and completely independent of their total length.
If you wish, you can add a "guard" element to the map during the initialization
map[INT_MIN] = EMPTY;
(it corresponds to "negative infinity") and the "miss" check will become simpler
Map::iterator it = map.upper_bound(i);
assert(it != map.begin());
if ((--it)->second == EMPTY)
/* Missed all ranges */;
but that's just a matter of personal preference.
Of course, if you just want to return 0 for non-mapped values, you don't need to carry out any checking at all. Just take the it->second from the decremented iterator and you are done.
I would use a very simple thing: a std::map.
class Range
{
public:
explicit Range(int item); // [item,item]
Range(int low, int high); // [low,high]
bool operator<(const Range& rhs) const
{
if (mLow < rhs.mLow)
{
assert(mHigh < rhs.mLow); // sanity check
return true;
}
return false;
} // operator<
int low() const { return mLow; }
int high() const { return mHigh; }
private:
int mLow;
int mHigh;
}; // class Range
Then, let's have a map:
typedef std::map<Range, int> ranges_type;
And write a function that search in this map:
int find(int item, const ranges_type& ranges)
{
ranges_type::const_iterator it = ranges.lower_bound(Range(item));
if (it != ranges.end() && it->first.low() <= item)
return it->second;
else
return 0; // No mapping ?
}
Main benefits:
Will check that the ranges effectively don't overlap during insertion in the set (you can make it so that it's only in debug mode)
Supports edition of the Ranges on the fly
Finding is fast (binary search)
If the ranges are frozen (even if their values are not), you may wish to use Loki::AssocVector to reduce the memory overhead and improve performance a bit (basically, it's a sorted vector with the interface of a map).
Wouldn't a simple array be enough? You're not saying how many items you have, but by far the fastest data structure is a simple array.
If the ranges are:
0..9 --> 25
10..19 --> 42
Then the array would simply be like this:
[25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42]
You can have two sorted arrays: one for lower bounds, one for upper bounds. Use std::lower_bound(lower_bound_array, value) and std::upper_bound(upper_bound_array, value). If the index of both results is the same, return index + 1. Otherwise, return 0.
If the indices returned match, it means that the value is >= the lower bound and < the upper bound. If they don't, then you are in between ranges.
The ideal is an interval tree (specialized binary tree). Wikipedia describes the method completely. Better than I. You won't get much more optimal than this, without sacrificing space for performance.
Your example ranges overlap, but the question says they wont. I'll assume the range is a typo. You could, could, store the destinations in an array and use the indices as the ranges. It's pretty easy, but ugly and not very maintainable. You'd need to initialize the array to 0, then for each range, iterate over those indices and set each index to the destination value. Very ugly, but constant lookup time so maybe useful if the numbers don't get too high and the ranges don't change very often.
Record the limits into a set (or map). When you call insert you will have a return value which is a pair. An iterator and a boolean. If the boolean is true then a new element is created which you have to remove later. After that step one with the iterator and look at what you have found.
http://www.cplusplus.com/reference/stl/set/insert/ See Return value
It's 1-dimensional spatial index. Quadtree-style binary tree will do, for example - and there are several other widely used methods.
A simple Linked List containing the range entries should be quick enough, even for say 50-100 ranges. Moreover, you could implement a Skip List, on say the upper bounds, to speed up these range queries. Yet another possibility is an Interval Tree.
Ultimately I'd choose the simplest: binary search.
You may find Minimal Perfect Hashing Function useful, http://cmph.sourceforge.net/.
Good Day,
Assume that I am writing a Python-like range in C++. It provides all the characteristics of Random Access containers(Immutable of course). A question is raised in my mind about the following situation:
I have two different iterators, that point to different instances of the range container. The thing is that these two ranges are equal. i.e. they represent the same range. Would you allow the following situation:
fact: range1 == range2 e.g.
---------------------------
range range1(10, 20, 1), range2((10, 20, 1);
range::iterator i = range1.begin(), j = range2.begin();
assert(i == j); // would you allow this?
Sorry if I am missing a simple design rule in STL :)
By default, in the STL, two iterators from two different container are not comparable. This means, the behavior is unspecified. So you do whatever you want, nobody should even try.
edit
After looking carefully at the standard, section 24.1, paragraph 6 states:
An iterator j is called reachable from
an iterator i if and only if there is
a finite sequence of applications of
the expression ++i that makes i == j.
If j is reachable from i, they refer
to the same container.
Which means that if you allow i == j with i and j in two different container, you really consider both container as being the same. As they are immutable, this is perfectly fine. Just a question of semantic.
You might want to check boost::counting_iterator. Combined with boost::iterator_range you'll get something analogous to your range class (except that it will only allow a step-size of 1):
auto rng = boost::make_iterator_range(boost::make_counting_iterator(0),
boost::make_counting_iterator(10));
for(auto it = rng.begin(), e = rng.end(); it != e; ++it)
std::cout << it << " "; // Prints 0,1,2,3,...,9
For this class two iterators are considered equal provided that they contain the same number. But admittedly the situation is different than yours because here each iterator doesn't know to which range it belongs.
In STL the comparison rules are driven by the container's elements and not the container itself, so in my opinion you shouldn't be performing the dereference your self in your == operator overload.