Checking if integer falls in range using only < operator - c++

I need to come up with some code that checks if a given integer falls within the bounds of a range. (The range is represented by a pair of integers.)
So, given a range r defined as an std::pair<int, int>, and a test integer n, I want to say:
if (n >= r.first && n <= r.second)
The catch is, I need to use a std::less<int> comparison functor to do this, which means I can only work with the less than operator.
I'm trying to come up with the equivalent expression. I'm pretty sure I have it correct, but I'm not entirely confident.
The expression I came up with is:
( !cmp(n, r.first) && !cmp(r.second, n) )
where cmp is an instance of std::less<int>
Did I do that correctly?

Polling others is not the best way to verify correctness. :)
Instead, consider your problem. Everything you are dealing with is an int, so all values involved can be represented as an int. No addition or subtraction is involved, so you needn't worry about leaving the representable range. So, we can fall back to standard math using standard integers, and leave the messiness of machine representations behind.
You are given a range closed at both ends [n, m] and a value p to test for membership in that range. You have one operator on integers that you can use, <. All the standard boolean operators are fair game.
Now, you can simply think about sets. You want to reject all p such that p < n or p > m. All other values of p are acceptable. Put another way, p is part of the desired set if
not ((p < n) or (m < p))
Using DeMorgan's laws, this is equivalent to
(not (p < n)) and (not (m < p))
Representing that using the standard C++ operators (rather than the alternative spellings provided by <iso646.h>), we get what you proposed, but using different names:
!<(p, n) && !<(m, p)
Renaming <() to cmp(), n to r.first, m to r.second, and p to n, we get precisely what you proposed:
!cmp(n, r.first) && !cmp(r.second, n)
So, yup, looks correct to me.

Yes, not of less-than is equivalent to greater than or equal to, in fact in many older programming languages <= is actually called ngt for not greater than and >= is nlt

Short answer:
if (num < max && !(num <= min)) { // stuff to do }
This will return true if "num" is between "min" and "max" but is not equal to either of them.
If you need it to include "min" and "max" in the range check, use:
if (num <= max && !(num < min)) { // stuff to do }
This works because...
!(A > B) == (A <= B) // If not greater than B, must be less than or equal to B
!(A >= B) == (A < B) // If not greater or equal to B, must be less than B
!(A < B) == (A >= B) // If not less than B, must be greater or equal to B
!(A <= B) == (A > B) // If not less than or equal to B, must be greater than B

Related

How is the order of occurence maintained by the given conditions

I came accross this GeeksForGeeks which read : Rearrange positive and negative numbers using inbuilt sort function such that all negative integers appear before all the positive integers and the order of appearance should be maintained.
The comparator function of sort() was modified to achieve this.
bool comp(int a, int b)
{
// This is to maintain order
if ((a >= 0 && b >= 0) || (a < 0 && b < 0))
return false;
// Swapping is must
if ((a >= 0) && (b < 0))
return false;
return true;
}
But how come the order is maintained by this block :
if ((a >= 0 && b >= 0) || (a < 0 && b < 0))
return false;
This appears to be the original article
https://www.geeksforgeeks.org/rearrange-positive-negative-numbers-using-inbuilt-sort-function/
How it (sort of) works: std::sort rearranges everything according to a comparitor. This comparitor is based on "all negative numbers are exactly equal to each other. All positive numbers are exactly equal to each other. Negative numbers are smaller than positive numbers."
If you sort according to those rules, you are going to get all the negative numbers then all the positive numbers. The comparitor itself does not mess with their order, beyond looking at whether they are greater or less than zero. (And the data set conveniently doesn't have any zeroes.)
What's wrong:
1) The comparison function does not correctly handle 0. It gives wrong answers, and even worse, it gives answers which violate strict weak ordering. (see below)
2) std::sort is not a stable sort. It is not guaranteed to preserve order. They got lucky on one data set. If they had used std::stable_sort, and a correct comparison function, it would have been a "built in function" which met the requirements. But the comparison function alone can't make an algorithm stable. See What is the difference between std::sort and std::stable_sort? or just look near the top of the docs on http://www.cplusplus.com/reference/algorithm/sort/
3) They do fancy tricks to come up with a solution of complexity O(n log n), for a trivially easy O(n) problem. So besides being wrong on multiple points, it is inefficient for no good reason.
Perhaps they should have considered https://en.cppreference.com/w/cpp/algorithm/stable_partition if we're allowed to just rule out zeroes in the data.
Here is a definition of strict weak ordering (also linked by Some Programmer Dude)
https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings
For all x in S, it is not the case that x < x (irreflexivity).
For all x, y in S, if x < y then it is not the case that y < x (asymmetry).
For all x, y, z in S, if x < y and y < z then x < z (transitivity).
For all x, y, z in S, if x is incomparable with y (neither x < y nor y < x hold), and y is incomparable with z, then x is incomparable with z (transitivity of incomparability).
Note that comp(0, anything) returns false, so 1 < 0 which makes it easy to break transitivity, in addition to being obviously wrong.
But how come the order is maintained by this block :
The order is not "maintained" in the comparator. The comparator can only tell that after sorting, two elements a and b should be end up
a before b
a after b
a together with b (before the same elements, after the same elements)
What happens to elements that are not ordered by the comparator is only a function of the algorithm. For insertion in a multiset, the added element would end up anywhere (except when insert with hint is used).
The comp function breaks strict weak ordering for
if ((a >= 0 && b >= 0) || (a < 0 && b < 0))
return false;
If a is 0 and b is +ve, then a is less than b, but false is returned, not true
Try
bool comp(int a, int b)
{
const int first = ((a < 0) ? -1 : (a == 0) ? 0 : 1);
const int second = ((b < 0) ? -1 : (b == 0) ? 0 : 1);
return (first < second);
}
and plug that into std::stable_sort

Most efficient way to see if number is contained within an unsorted two-number interval?

So I know this question may be very trivial and not worth asking since the difference is so small, but I'm wondering anyway.
Let's consider three float, 'a', 'b' and 'number'. We want to know if 'number' is contained within an interval of boundaries 'a' and 'b';
'a' and 'b' are the limits of the interval, but they are unsorted : 'a' may be smaller than 'b' and vice-versa.
Which function would give the fastest results ?
1)
bool isNumberInInterval(float a, float b, float number)
{
if (a < b)
{
return ( (a <= number) && (number <= b) );
}
else
{
return ( (b <= number) && (number <= a) );
}
}
2)
bool isNumberInInterval(float a, float b, float number)
{
return ( ( (b <= number) && (number <= a) ) || ( (a <= number) && (number <= b) ) );
}
It's hard to say which is faster. It depends on a lot of things (distribution of numbers, branch prediction, compiler). You should benchmark it. On my PC, with GCC 6.3, with uniform distributed [0;1] numbers, their speed is the same.
This variant should be faster on current PCs (it is 25% faster than your variants on my PC):
bool isNumberInInterval(float a, float b, float number)
{
return (a-number)*(b-number)<=0;
}
This likely depends a lot on the machine and compiler. But you can argue that the first is faster.
The first version will perform at most 3 comparisons and 1 logical operation. But it could perform as few as 2 comparisons and 0 logical operations, if you can short-circuit the && when the first operand is false.
The second version's worst case is 4 comparisons and 3 logical operations. But it must perform at least 2 comparisons and 1 logical operation: you can't short-circuit both the && and the ||.

Extracting lowest complex number from a vector

The vector is taking points to a rectangle. I want to be able to take the lowest and highest complex number and assigne it to 2 different complex numbers. I've only tried for the lowest with the below but it doesnt seem to find the lowest and just return the 1st element.
vector < complex<double>* > xs;
typedef typename vector < complex<double>* >::iterator Iter;
xs.push_back(&pointa);
xs.push_back(&pointb);
xs.push_back(&pointc);
xs.push_back(&pointd);
for (Iter p = xs.begin(); p != xs.end(); ++p)
{
if((*p)->real()<(*p+1)->real() && (*p)->imag()<(*p+1)->imag())
{
double a = (*p)->real();
double b = (*p)->imag();
complex <double> botleft_1(a,b);
}
else
{
}
}
Any suggestions?
The immediate bug in your code is that *p+1 means (*p)+1.
The next bug after you fix that to *(p+1) will be that you go one element off the end of the vector. You should be comparing each value with the lowest/highest so far, not with the next value in the vector.
There is in any case no such thing as the "lowest" or "highest" complex number - the complex numbers are not an ordered field (theorem). You can define any comparison operator you like on complex numbers, but it will be pretty arbitrary, for example it won't necessarily have ordered field properties such as a < b && c < d => a+c < b+d. The comparison you have defined does have that property, but is not a strict weak order, so it might not behave the way you expect once you start doing comparisons among 3 or more values.
For example, consider the values complex<double> a(1,1), b(0,3), c(2,2);, and the comparison function lt(complex<double> lhs, complex<double> rhs) { return lhs.real() < rhs.real() && lhs.imag() < rhs.imag(); }.
Then lt(a,b) and lt(b,a) are both false. This means a and b are equivalent as far as the ordering is concerned.
Likewise, lt(b,c) and lt(c,b) are both false. This means b and c are equivalent as far as the ordering is concerned.
However, lt(a,c) is true. This means a and c are not equivalent as far as the ordering is concerned.
In the loop you do not compare with the lowest number, only with next number. Try something like this:
complex<double> *lowest = *xs.begin();
for (Iter p = xs.begin() + 1; p != xs.end(); ++p){
if ((*p)->real() < lowest->real() && (*p)->imag() < lowest->imag())
lowest = *p;
}
After the loop, the variable lowest will have be the one you want.
Also, in your version of the loop, you compare to p + 1 which will be xs.end() on the last item, and that will not be a valid pointer.
Use boost::minmax_element
std::pair< Iter > pairit = boost::minmax_element( xs.begin(), xs.end(),
[&]( complex<double>* pcomplexA, complex<double>* pcomplexB ) {
// Suitable comparison predicate (see Steve Jessop's answer)
return pcomplexA->abs() < pcomplexB->abs(); // |a| < |b|
});

find triangular triplet in an array [duplicate]

zero-indexed array A consisting of N integers is given. A triplet (P, Q, R) is triangular if and
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
For example, consider array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
Triplet (0, 2, 4) is triangular.
Write a function
int triangle(const vector<int> &A);
that, given a zero-indexed array A consisting of N integers, returns 1 if there exists a triangular triplet for this array and returns 0 otherwise.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range [-2,147,483,648..2,147,483,647].
For example, given array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
the function should return 1, as explained above. Given array A such that
A[0] = 10 A[1] = 50 A[2] = 5
A[3] = 1
the function should return 0.
Expected worst-case time complexity:
Expected worst-case space complexity: O(1)
First claim
First of all there is no point to take into account non-positive number. There's no chance you may achieve the triangle inequalities if at least one of the numbers is negative or zero. This is obvious, nevertheless here is the proof:
Assume A, B, C obey the triangle inequality, whereas C <= 0. Then you have
A + C > B. Hence A > B.
B + C > A. Hence B > A.
(contradiction).
Second claim
Suppose A, B, C obey the triangle inequalities, whereas C is the largest among A,B,C. Then for each A2 and B2 between A,B respectively and C - they will also obey triangle inequality.
In other words:
A,B,C obey triangle inequalities.
C >= A
C >= B
C >= A2 >= A
C >= B2 >= B
Then A2,B2,C also obey triangle inequalities.
The proof is trivial, enough to write the inequalities explicitly.
The consequence of this is that if C is the largest number for which you want to find the triangle inequality - you should check only two largest numbers from the set not exceeding C, and check if A + B > C.
Third claim
If 0 < A <= B <= C don't obey triangle inequalities, then C >= A*2.
The proof is trivial as well: A + B <= C, hence A + A <= C, hence C >= A*2
The algorithm
Pick 2 largest numbers B and C (B <= C).
Pick the largest number A not exceeding B, such that
A <= B <= C.
Make sure it's not the same element as B,C
Take into account only positive integers.
If unable to pick such a number - done. (No triangulars).
Check if A,B,C obey the triangle inequality. Test if A + B > C. (done if they do).
Discard the largest number C. Substitute C = B, then B = A.
Go to step 2.
Fourth claim
The above algorithm is logarithmic in the maximum integer size. In other words, its linear in the data type bitness. It's worst-case complexity is independent on the input length. Hence - it's O(1) in the input length.
Proof:
At every iteration (that does not find the solution) we have A <= C/2. After two such iterations A becomes the new C. This means that after every two iterations the largest number becomes at least 2 times smaller.
Obviously this gives us the upper bound of the number of the iterations. Gives our integers are limited by 31 bit (we ignore negatives), whereas the minimum interesting largest C is 1, this gives us no more that 2 * (31 - 1) = 60 iterations.
If O(N³) is acceptable time complexity then the Pseudocode below should work. If you have stricter time complexity requirements then you'll have to specify them.
for (P in A){
for (Q in A){
for (R in A){
if(A[P] > 0 && A[Q] > 0 && A[R] > 0){
if(A[P] > A[R] - A[Q] && A[Q] > A[P] - A[R] && A[R] > A[Q] - A[P]){
return 1;
}
}
}
}
}
return 0;
The reasoning behind the if statements is this:
Since the ints can be anything up to max int you have to deal with overflow. Adding them together could cause a weird error if there are two very large ints in the array. So instead we test if they are positive and then rewrite the formulae to do the same checks, but with subtraction. We don't need to do anything if any of the values are negative or 0, since:
Assume x <= 0
Assume x+y > z
Assume x+z > y
Then y > z and z > y which is a contradiction
So no negative or zero valued ints will be a part of a triple
Sorting would be very cool, but const vector and O(1) space requirements doesn't allow it.
(because this is homework) Some hint: triangular numbers are close to each other.
A hint: if you pick just two members of the array then what are the limits on the possible value of the third member of a triangular triplet? Any number outside those limits can be rejected immediately.
There are many in-place sorts; use one of them to sort the array - say comb sort for smaller ones (time complexity O(N^2)) or heap sort (complexity O(N log(N)).
Once you have sorted array, problem should be whether there is a set of 3 numbers where A[X] > (A[X-1] + A[X+1]) / 2 i.e. middle number is greater than average of preceding & succeeding numbers (sadly this is a guess, I don't have a real basis - if its incorrect I hope someone corrects me, but there should be some good way to redefine the 'triangle' requirement to be more easily checked).
Now you just have an O(1) iteration over the sorted array to check whether the condition is true, hence overall complexity will be that of the sorting algorithm (best case N logN)

finding triangulars from array

zero-indexed array A consisting of N integers is given. A triplet (P, Q, R) is triangular if and
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
For example, consider array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
Triplet (0, 2, 4) is triangular.
Write a function
int triangle(const vector<int> &A);
that, given a zero-indexed array A consisting of N integers, returns 1 if there exists a triangular triplet for this array and returns 0 otherwise.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range [-2,147,483,648..2,147,483,647].
For example, given array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
the function should return 1, as explained above. Given array A such that
A[0] = 10 A[1] = 50 A[2] = 5
A[3] = 1
the function should return 0.
Expected worst-case time complexity:
Expected worst-case space complexity: O(1)
First claim
First of all there is no point to take into account non-positive number. There's no chance you may achieve the triangle inequalities if at least one of the numbers is negative or zero. This is obvious, nevertheless here is the proof:
Assume A, B, C obey the triangle inequality, whereas C <= 0. Then you have
A + C > B. Hence A > B.
B + C > A. Hence B > A.
(contradiction).
Second claim
Suppose A, B, C obey the triangle inequalities, whereas C is the largest among A,B,C. Then for each A2 and B2 between A,B respectively and C - they will also obey triangle inequality.
In other words:
A,B,C obey triangle inequalities.
C >= A
C >= B
C >= A2 >= A
C >= B2 >= B
Then A2,B2,C also obey triangle inequalities.
The proof is trivial, enough to write the inequalities explicitly.
The consequence of this is that if C is the largest number for which you want to find the triangle inequality - you should check only two largest numbers from the set not exceeding C, and check if A + B > C.
Third claim
If 0 < A <= B <= C don't obey triangle inequalities, then C >= A*2.
The proof is trivial as well: A + B <= C, hence A + A <= C, hence C >= A*2
The algorithm
Pick 2 largest numbers B and C (B <= C).
Pick the largest number A not exceeding B, such that
A <= B <= C.
Make sure it's not the same element as B,C
Take into account only positive integers.
If unable to pick such a number - done. (No triangulars).
Check if A,B,C obey the triangle inequality. Test if A + B > C. (done if they do).
Discard the largest number C. Substitute C = B, then B = A.
Go to step 2.
Fourth claim
The above algorithm is logarithmic in the maximum integer size. In other words, its linear in the data type bitness. It's worst-case complexity is independent on the input length. Hence - it's O(1) in the input length.
Proof:
At every iteration (that does not find the solution) we have A <= C/2. After two such iterations A becomes the new C. This means that after every two iterations the largest number becomes at least 2 times smaller.
Obviously this gives us the upper bound of the number of the iterations. Gives our integers are limited by 31 bit (we ignore negatives), whereas the minimum interesting largest C is 1, this gives us no more that 2 * (31 - 1) = 60 iterations.
If O(N³) is acceptable time complexity then the Pseudocode below should work. If you have stricter time complexity requirements then you'll have to specify them.
for (P in A){
for (Q in A){
for (R in A){
if(A[P] > 0 && A[Q] > 0 && A[R] > 0){
if(A[P] > A[R] - A[Q] && A[Q] > A[P] - A[R] && A[R] > A[Q] - A[P]){
return 1;
}
}
}
}
}
return 0;
The reasoning behind the if statements is this:
Since the ints can be anything up to max int you have to deal with overflow. Adding them together could cause a weird error if there are two very large ints in the array. So instead we test if they are positive and then rewrite the formulae to do the same checks, but with subtraction. We don't need to do anything if any of the values are negative or 0, since:
Assume x <= 0
Assume x+y > z
Assume x+z > y
Then y > z and z > y which is a contradiction
So no negative or zero valued ints will be a part of a triple
Sorting would be very cool, but const vector and O(1) space requirements doesn't allow it.
(because this is homework) Some hint: triangular numbers are close to each other.
A hint: if you pick just two members of the array then what are the limits on the possible value of the third member of a triangular triplet? Any number outside those limits can be rejected immediately.
There are many in-place sorts; use one of them to sort the array - say comb sort for smaller ones (time complexity O(N^2)) or heap sort (complexity O(N log(N)).
Once you have sorted array, problem should be whether there is a set of 3 numbers where A[X] > (A[X-1] + A[X+1]) / 2 i.e. middle number is greater than average of preceding & succeeding numbers (sadly this is a guess, I don't have a real basis - if its incorrect I hope someone corrects me, but there should be some good way to redefine the 'triangle' requirement to be more easily checked).
Now you just have an O(1) iteration over the sorted array to check whether the condition is true, hence overall complexity will be that of the sorting algorithm (best case N logN)