Find the first two consecutive pairs in the vector with greatest equal second

Pages: 12
One last question regarding vector of pairs. Suppose we have a vector of pairs like the following:

V { (1,10) (4,20) (3,50) (6,40) (8,50) (10,30) (7,40) (12,50) };

after sorting the vector with the sort algorithm based on the second of pairs we have:

V { (1,10) (4,20) (10,30) (6,40) (7,40) (3,50) (8,50) (12,50) };

Now, the question is, if we would like to find the first two consecutive pairs in the vector with greatest equal second, namely here pairs (3,50) and (8,50), any ideas on how we handle this?

Thanks
Last edited on
Perhaps:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <vector>
#include <iostream>
#include <utility>
#include <algorithm>

using Pairs = std::pair<int, int>;

int main()
{
	const std::vector<Pairs> V { {1,10}, {4,20}, {10,30}, {6,40}, {7,40}, {3,50}, {8,50}, {12,50} };

	const auto greatest {V.back()};
	const auto first {std::partition_point(V.rbegin(), V.rend(), [&](const auto& v1) { return v1.second == greatest.second; }).base()};
	const auto sec {std::next(first)};

	std::cout << first->first << ' ' << first->second << '\n';

	if (sec != V.end())
		std::cout << sec->first << ' ' << sec->second << '\n';
}


which displays:


3 50
8 50

Seeplus thanks a lot. Today your help was extremely important! One last question regarding the above in conjuction with my previous thread. If instead of using the largest smallest, I choose to use this, the change will be something like this:

1
2
3
4
5
const auto greatest{ v.back() };
const auto first{ std::partition_point(v.rbegin(), v.rend(), [&](const auto& v1) { return v1.second == greatest.second; }).base() };
const auto sec{ std::next(prev) };
const auto K{ first - sec}; 
const double Div{ 1 / K.first };


Problem is that despite the fact that both now and before, I have two pairs (before largest and smallest) and (now prev and next), the code now does not compile as it considers K.first error. Any ideas why?
Last edited on
first/sec are iterators. So L10 should be:

 
const auto K {*first - *sec};

Many thanks seeplus. I didn't notice they were Iterators. The compiler throws error for the line 3 after that:

Error C2676 binary '-': 'Pairs' does not define this operator or a conversion to a type acceptable to the predefined operator
Last edited on
You'll need to have the operator-() Pairs overload function from previous code.

1
2
3
Pairs operator-(const Pairs& p1, const Pairs& p2) {
	return {p1.first - p2.first, p1.second - p2.second};
}

Last edited on
Well , that's the point! I have it and still throws that..
This compiles ok:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <vector>
#include <iostream>
#include <utility>
#include <algorithm>

using Pairs = std::pair<int, int>;

Pairs operator-(const Pairs& p1, const Pairs& p2) {
	return {p1.first - p2.first, p1.second - p2.second};
}

int main()
{
	const std::vector<Pairs> V {{1,10}, {4,20}, {10,30}, {6,40}, {7,40}, {3,50}, {8,50}, {12,50}};

	const auto greatest {V.back()};
	const auto first {std::partition_point(V.rbegin(), V.rend(), [&](const auto& v1) { return v1.second == greatest.second; }).base()};
	const auto sec {std::next(first)};

	if (sec != V.end()) {
		const auto K {*first - *sec};
		const double Div {1.0 / K.first};
	}
}


Note the change to L22 to make the division double and not int.
Last edited on
It throws a debug assertion failed runtime error

Expression:can't dereference out of range vector iterator

My code above compiles OK as debug build and runs OK without any runtime errors as VS2019.

Adding this line after L22:

 
std::cout << Div << '\n';


displays:


-0.2


If your code is different from mine above, please post your code.


The part of my code (altered to included the two greatest consecutive pairs instead of largsest - smallest) in which I needed help and discussed together in my posts so far is the following:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

  
            const string data {"data" }; 
            const string ex{ ".txt" };  
            const size_t lastFile{ 150 }; 
            map<string, double> mp;
            vector<Pairs> vec;
for (int i = 0; i <= lastFile; ++i) {
                stringstream ss;

                ss << data << setw(3) << setfill('0') << i << ex;

                ifstream fin(ss.str());

                if (!fin)
                    return (cout << "File open failed! " << ss.str() << '\n'), 1;

                Pairs p;
                fin >> p;
                vec.push_back(p);
                sort(vec.begin(), vec.end(), sortsec);
                const auto greatest{ vec.back() };
                const auto first{ std::partition_point(vec.rbegin(), vec.rend(), [&](const auto& V1) { return V1.second == greatest.second; }).base() };
                const auto sec{ std::next(first) };


               
                const auto K{ *sec - *first}; 
                const double Div{ 1.0 / K.first };	 


            }
}


Last edited on
Yep. It will! You haven't got my test for bad sec! What if v has only 1 entry - or several entries with different .second values? In these cases sec will be invalid.

See L20 of my code above.

PS. You do know you're only reading the first item from each file?
Last edited on
Reasonable since I didn't wrote the sec != V.end() . I am much more inattentive than I should be.. Thanks you very much again seeplus.

PS. I sent you a pm.
I am posting an enquiry regarding the code. I tried reading from files and store the data into a vector of pairs. However when I try to obtain the first two pairs with greatest second and then calculate K

1
2
3
4
5
const auto greatest {V.back()};
const auto first {std::partition_point(V.rbegin(), V.rend(), [&](const auto& v1) { return v1.second == greatest.second; }).base()};
const auto sec {std::next(first)};

if (sec != V.end()) const auto K {*first - *sec};


K always ends up being equal to zero. If some data in my file has a fractional part (i.e .5) I could understand that in case the pairs weren't of double type. Since I have define pairs as double, why do I get k equal to zero?
Last edited on
What's the data?

You really need to get to grips with code debugging and the debugger. If K.first is 0 then you should be able to trace why back to the data - or to a code issue.
Last edited on
I apologize. Data is from previously discussed code from 150 txt files to store it in a vector

Last edited on
No. I meant what is the actual read data. What's in v?

PS. Have you got an int left somewhere that should be double?

If you know that the data type might change, then you could do something like:

1
2
3
4
5
6
//using T = int;
using T = double;

...

T val {};


In the code use T as type instead of int or double. That way to change the type used for data, it only needs changing in 1 place.
PPS I don't know what these numbers are - but if they're close to several decimal places, then subtraction could result in a number that 'seems' to be 0. Also you shouldn't compare double numbers for equality - you should compare that their absolute difference is < a specified value.

If a and b are double then for equality:

1
2
3
4
5
const double epsilon {0.000001};  // Or what is required

if (abs(a - b) < epsilon) {
  // a and b are consider equal here
}

Many thanks Seeplus for everything!
Boost Math Toolkit on comparing floating-point values to see if they are tolerably close enough to each other:

. Absolute difference/error: the absolute difference between two values a and b is simply fabs(a-b). This is the only meaningful comparison to make if we know that the result may have cancellation error.

. The edit distance between the two values: i.e. how many (binary) floating-point values are between two values a and b? ... probably only useful when you know that the distance should be very small.

. The relative distance/error between two values. This is quick and easy to compute, and is generally the method of choice when checking that your results are "tolerably close" to one another. However, it is not as exact as the edit distance when dealing with small differences...

https://www.boost.org/doc/libs/1_76_0/libs/math/doc/html/math_toolkit/float_comparison.html

Note: The relative distance/error between a and b is defined as fabs( (a-b) / min(a,b) )
Last edited on
Pages: 12