Cannot sort vector<pair<int, int>> - c++

I tried to sort a vector<pair<int, int>> by using STL sort with my own boolean function.
#include <bits/stdc++.h>
using namespace std;
bool comp(pair<int, int> u1, pair<int, int> u2){
if(u1.first != u2.first) return u1.first < u2.first;
return u2.second > u2.second;
}
int main(void){
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int univs, day, pay, max_income = 0, spent = 0;
vector<pair<int, int>> day_pay;
cin >> univs;
for(int u = 0; u < univs; u++){
cin >> pay >> day;
day_pay.push_back(make_pair(day, pay));
}
for(int i = 0; i < univs; i++) cout << day_pay[i].first << " " << day_pay[i].second << endl;
cout << endl;
sort(day_pay.begin(), day_pay.end(), comp);
for(int i = 0; i < univs; i++) cout << day_pay[i].first << " " << day_pay[i].second << endl;
for(int u = 0; u < univs; u++){
if(day_pay[u].first <= spent) continue;
max_income += day_pay[u].second;
spent++;
}
cout << max_income;
}
this is test case:
4
50 2
10 1
20 2
30 1
I want to sort this case as
30 1
10 1
50 2
20 2
What should I do for solving this problem?

The line
return u2.second > u2.second;
is suspicious. You most likely mean
return u1.second > u2.second;

Look at your comp function. The line after the if:
return u2.second > u2.second;
shuldn't that be:
return u1.second > u2.second

The actual fault was well pointed by Caleth in their answer. But I think that this much code is sufficient for sorting. You may modify it according to your question.
#include <iostream>
#include <utility>
#include <vector>
int main() {
std::size_t n;
std::cin >> n;
std::vector<std::pair<int, int>> v(n);
for (auto &&i : v) std::cin >> i.first >> i.second;
std::sort(v.begin(), v.end(),
[](std::pair<int, int> &a, std::pair<int, int> &b) {
return a.second != b.second ? a.second < b.second
: a.first > b.first;
});
for (auto &&i : v) std::cout << i.first << ' ' << i.second << '\n';
}
If you're using C++ 14 or higher, you can directly use auto in lambda params.
Sample Run:
Sample Input:
4
50 2
10 1
20 2
30 1
Corresponding Output:
30 1
10 1
50 2
20 2

Related

why isn't my vector pushbacking even and odd numbers

i tried to separate even and odd numbers using vectors from a array ==>
so i made a function that returns true is number is even and false for if number is odd
then i used an if else statement where if the function returns true then it pushbacks the value in a vector and if the function returns false then it pushbacks the value in another vector , finally i printed all the elements in the vector but the output does not show any element except it shows one in the odd vector.
#include <iostream>
#include <vector>
using namespace std;
bool sort(int arr[] , int i){
if(arr[i] %2 == 0){
return true;
}
return false;
}
int main(){
int n;
cin >> n;
int *arr = new int[n];
for(int i=1 ; i<=n ; i++){
arr[i-1] = i;
}
vector <int> even , odd;
int i=0 ;
if(sort(arr , i)){
even.push_back(arr[i]);
sort(arr , i+1);
}else{
odd.push_back(arr[i]);
sort(arr,i+1);
}
cout << "the even numbers are : " << endl;
for(auto element:even){
cout << element << " ";
}
cout << endl;
cout << "the odd numbers are : " << endl;
for(auto element:odd){
cout << element << " ";
}
}
As #TonyDelroy said, you have to make for loop around call to sort(arr, i). Also first loop should go up to i <= n instead of i < n.
Your fixed working code below (see also std::partition_copy variant afterwards):
Try it online!
#include <iostream>
#include <vector>
using namespace std;
bool sort(int arr[] , int i){
if(arr[i] %2 == 0){
return true;
}
return false;
}
int main(){
int n;
cin >> n;
int *arr = new int[n];
for(int i=1 ; i<=n ; i++){
arr[i-1] = i;
}
vector <int> even , odd;
for (int i = 0; i < n; ++i)
if (sort(arr, i))
even.push_back(arr[i]);
else
odd.push_back(arr[i]);
cout << "the even numbers are : " << endl;
for(auto element:even){
cout << element << " ";
}
cout << endl;
cout << "the odd numbers are : " << endl;
for(auto element:odd){
cout << element << " ";
}
}
Input:
10
Output:
the even numbers are :
2 4 6 8 10
the odd numbers are :
1 3 5 7 9
As #chris said you can also use std::partition_copy to implement your algorithm:
Try it online!
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
int n = 0;
std::cin >> n;
std::vector<int> arr(n), odd, even;
for (int i = 1; i <= n; ++i)
arr[i - 1] = i;
std::partition_copy(arr.cbegin(), arr.cend(),
std::back_insert_iterator(odd), std::back_insert_iterator(even),
[](auto const & x){ return (x & 1) == 1; });
std::cout << "the even numbers are : " << std::endl;
for (auto element: even)
std::cout << element << " ";
std::cout << std::endl << "the odd numbers are : " << std::endl;
for (auto element: odd)
std::cout << element << " ";
}
Input:
10
Output:
the even numbers are :
2 4 6 8 10
the odd numbers are :
1 3 5 7 9
You only push one element - the first.
Your partitioning code is equivalent to
if(sort(arr , 0)){
even.push_back(arr[0]);
sort(arr , 1);
}else{
odd.push_back(arr[0]);
sort(arr,1);
}
You need to loop over all the input numbers.
You can also simplify matters with a more generally useful evenness function that doesn't depend on an array:
bool is_even(int x) { return x % 2 == 0; }
and then there is no need to store all the inputs before processing them:
int main(){
vector <int> even , odd;
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
if (is_even(x)) {
even.push_back(x);
}
else {
odd.push_back(x);
}
}
cout << "the even numbers are : " << endl;
for (auto element:even){
cout << element << " ";
}
cout << endl;
cout << "the odd numbers are : " << endl;
for (auto element:odd){
cout << element << " ";
}
}

How to discard extra inputs in a line c++

I am a novice in C++. I am trying to get input from the user for inserting in a multidimensional vector. The code works fine. But when I give extra inputs in the same line, my program does not disregard it and considers it in the next iteration.
For example when I give input in the following format:
m=3 n=4
1 2 3 4 5
1 3 5 5
1 345 65 567
the output is
1 2 3 4
5 1 3 5
5 1 345 65
But what the output I want is
1 2 3 4
1 3 5 5
1 345 67 567
int main() {
vector<vector<int>> vec;
int m, n, dat;
cout << "Enter dimensions of Vector";
cin >> m >> n;
// takes data n times into a subvector temp and inserts it into the vector vec m
// times
cout << "Enter elements one row at a time";
for(int i = 0; i < m; ++i) {
vector<int> temp;
for(int j = 0; j < n; ++j) {
cin >> dat;
temp.push_back(dat);
}
vec.push_back(temp);
}
for(int k = 0; k < vec.size(); ++k) {
for(int i = 0; i < vec[k].size(); ++i) {
cout << setw(4) << vec[k][i];
}
cout << endl;
}
}
Consider using std::getline to read a complete line. You can then use that to populate a std::istringstream that you then use to extract the exact number of elements you want. Also note:
Why is “using namespace std;” considered bad practice?
Example:
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main() {
std::vector<std::vector<int>> vec;
int m, n, dat;
std::cout << "Enter dimensions of Vector";
std::cin >> m >> n;
std::cin.ignore(); // skip newline
// takes data n times into a subvector temp and inserts it into the vector vec m
// times
std::cout << "Enter elements one row at a time\n";
for(int i = 0; i < m; ++i) {
std::string line;
std::vector<int> temp;
std::cout << " row " << (i + 1) << ": ";
std::getline(std::cin, line);
std::istringstream iss(line);
for(int j = 0; j < n; ++j) {
iss >> dat;
temp.push_back(dat);
}
vec.push_back(temp);
}
for(const auto& row : vec) {
for(int colval : row) {
std::cout << std::setw(4) << colval;
}
std::cout << "\n";
}
}

How to print elements of array of vectors of pairs?

I have an array of vector of pairs
vector <pair<int,int> > a[4]
.I have added elements to it using push_back.But I dont know how to print the elements.if i use an iteretor and print it like a[i].first or a[i].second it throws me error .Any other ways of doing it.Thanks in advance.
vector <pair<int,int> > a[4];
for(int i = 0;i < e;++i)
{
int x,y;
cin >> x >> y >> w;
a[x].push_back({w, y});
a[y].push_back({w, x});
}
This is how I push elements.But how to print them.
for(i=a[i].begin();i!=a[i].end();i++)
{
cout<<a[i].second<<" ";
}
I am getting the following error.I dnt know how to print them.
error: no match for 'operator[]' (operand types are 'std::vector<std::pair<int, int> >*' and 'std::vector<std::pair<int, int> >::iterator {aka __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int> > >}')
for(i=g[i].begin();i!=g[i].end();i++)
You did not provide any code so that we could be able to know what's going wrong at your machine.
But here is a working example on how to access a vector of pairs:
#include <utility>
#include <iostream>
#include <vector>
#include <string>
typedef std::pair<int, std::string> pairIntString;
int main()
{
std::vector<pairIntString> pairVec;
pairVec.push_back(std::make_pair(1, "One"));
pairVec.push_back(std::make_pair(2, "Two"));
pairVec.push_back(std::make_pair(3, "Three"));
for (std::vector<pairIntString>::const_iterator iter = pairVec.begin();
iter != pairVec.end();
++iter)
{
std::cout << "First: " << iter->first
<< ", Second: " << iter->second <<std::endl;
}
return 0;
}
Output, see here:
First: 1, Second: One
First: 2, Second: Two
First: 3, Second: Three
Edit #1:
Now you provide code, but you are actually using an array of vectors of pairs: vector <pair<int,int> > a[4];. Further you put an iterator from the begin() method into the [] operator. It seems that you mixed a lot of things e.g. here i=a[i].begin() (one i is iterator and another is an index) and don't understand what they really are for. Please look at my example and read about arrays and vectors and how to access them properly. Also read about the difference of indexed and iterator based access.
Edit #2:
This loop:
for(i=a[i].begin();i!=a[i].end();i++)
{
cout<<a[i].second<<" ";
}
should probably be:
/* loop through the fixed size array */
for(size_t idx = 0; idx < 4; ++i)
{
cout << "Array element idx: " << idx << endl;
/* get the iterator of the specific array element */
for (vector <pair<int,int> >::const_iterator iter = a[idx].begin();
iter != a[idx].end();
++iter)
{
cout << "First: " << iter->first
<< ", Second: " << iter->second << endl;
}
}
as you're having an array of vector of pairs you have two loop over the array and the vector. Because the array has a fixed size of 4 I used it as maximum.
vector <pair<int,int>> vec[5];
vector <pair<int,int>> :: iterator it;
for(int i=0;i<5;i++){
for(it=vec[i].begin(); it!=vec[i].end();it++) cout << it->first << " " << it->second << " -> ";
cout << "\n";
}
vector<pair<int,int>> v;
int n , in1 , in2;
cin >> n;
for(int i = 0 ; i < n ; i++)
{
cin >> in1 >> in2;
v.push_back(make_pair(in1,in2));
}
for(int i = 0 ; i < n ; i++)
cout << v[i].first << " " << v[i].second << endl;
return 0;
I used this concept in a question and you can check out the code which do the same what you wanted
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define loop(i, k, n) for(int i = k; k < n ? i < n : i >= n; k < n ? i+=1 : i-=1)
#define pll pair<ll, ll>
#define pb push_back
#define po pop_back
#define mp make_pair
#define F first
#define S second
#define endl "\n"
int main()
{
ll n, k;
cin >> n >> k;
ll arr[n];
ll ansArr[n] = {0};
vector <pair<ll, ll>> v[n];
loop(i, 0, n) cin >> arr[i];
loop(i, 0, n) {
if(arr[i] < 0) {
for(int j = i+1; j <= i+k && j < n; j++) {
if(arr[j] > 0) v[j].pb(mp(arr[i], i)); // Taking input in pairs
}
for(int j = i-1; j >= i-k && j >= 0; j--) {
if(arr[j] > 0) v[j].pb(mp(arr[i], i)); // Taking input in pairs
}
}
}
// Printing the result
loop(i, 0, n) {
for(auto it : v[i]) cout << it.F << " ";
cout << endl;
for(auto it : v[i]) cout << it.S << " ";
cout << endl;
}
return 0;
}

keeping track of vector pair indices upon sorting

Similar things have been asked before but I am having trouble applying the concept. I would like to to keep track of the indices of the pairs in my vector of pairs then, once sorted, std::cout the input order.
e.g.
cin >> 5 6 1 5 1 2 1 2 3 5
cout << 1 2 1 2 1 5 3 5 5 6
cout >> 3 4 2 5 1 //and this is where I am having trouble.
I was thinking of converting to triples, where one of the elements is the index but I couldn't get that to conform to my needs.
Any help would be appreciated. Thank you.
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
using namespace std;
bool compare(const pair<int,int>&A, const pair<int,int>&B);
int main()
{
vector<pair<int,int>> v;
pair<int,int> tok;
while(cin >> tok.first>>tok.second){v.push_back(tok);}
sort(v.begin(),v.end(), compare);
for(int i = (signed int)v.size()-1; i >= 0 ; i--)
{
cout << v.at(i).first << " ";
cout << v.at(i).second << " ";
}
cout << endl;
return 0;
}
bool compare(const pair<int,int>&A, const pair<int,int>&B)
{
return A.first > B.first;
}
Here's one way to do it. Long time since I did someone's homework for them ;-)
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
const string input_data = "5 6 1 5 1 2 1 2 3 5";
typedef pair<int, int> integer_pair;
typedef pair<int, integer_pair> integer_pair_with_input_order;
bool less_by_integer_pair(const integer_pair_with_input_order& l,
const integer_pair_with_input_order& r)
{
return l.second < r.second;
}
int main()
{
// note - I did this to avoid having to type numbers in.
std::istringstream simulate_cin(input_data);
vector<integer_pair_with_input_order> v;
integer_pair tok;
int input_order = 0;
while(simulate_cin >> tok.first >> tok.second) {
v.push_back(make_pair(++input_order, tok));
}
sort(v.begin(),v.end(), less_by_integer_pair);
for (int i = 0 ; i < v.size() ; ++i)
{
const integer_pair_with_input_order& elem = v[i];
cout << "input order : " << elem.first
<< " { " << elem.second.first
<< ", " << elem.second.second << " }\n";
}
return 0;
}

Printing vector in reverse order using range-based for loop

I have this code that convert a decimal number into a binary one:
#include <iostream>
#include <windows.h>
#include <vector>
#include <algorithm>
using namespace std;
void space(){ cout << endl << endl << endl; }
int main(int argc, char const *argv[]){
system("color 1F");
unsigned long int n, copy_n;
vector<int> v;
cout << "# Decimal: "; cin >> n; cout << endl; copy_n = n;
while (n != 0){
if (n % 2 == 0){ v.push_back(0); }else{ v.push_back(1); }
n = int(n / 2);}
cout << endl << "# Binary: ";
reverse(v.begin(), v.end());
for (size_t i = 0; i < v.size(); i++){cout << v.at(i);}
space(); system("Pause"); return 0;
}
... and this ...
#include <iostream>
#include <windows.h>
using namespace std;
void space(){ cout << endl << endl << endl; }
int main(int argc, char const *argv[]){
system("color 1F");
unsigned long int n, copy_n, nr = 0 ;
cout << "# Decimal: "; cin >> n; copy_n = n; cout << endl;
while (copy_n != 0){ nr++; copy_n = int(copy_n / 2); }
int* v = new int[nr];
for (int i = 0; i < nr; i++){if (n % 2 == 0){ v[i] = 0; }else{ v[i] = 1; }n = int(n / 2);}
cout << endl << "# Binary: ";
for (int i = nr-1; i >= 0;i--){cout << v[i] << "";}
space(); system("Pause"); return 0;}
... and this ...
#include <iostream>
#include <windows.h>
#include <bitset>
using namespace std;
void space(){ cout << endl << endl << endl; }
int main(int argc, char const *argv[]){
system("color 1F");
unsigned int n;
cout << "# Decimal: "; cin >> n; cout << endl;
bitset<16>binary(n);
cout << endl << "# Binary: " << binary << endl;
space(); system("Pause"); return 0;
}
But my question is:
How can I use reverse() function from algorithm and print the vector with range-based for loop
Ex: Decimal = 2
with
reverse(v.begin(), v.end());
for (size_t i = 0; i < v.size(); i++){cout << v.at(i);}
program prints 10
with
reverse(v.begin(), v.end());
for(auto i : v){cout<<v.at(i);}
program pritns 01
Why? And how can I fix this?
This for statement
reverse(v.begin(), v.end());
for(auto i : v){cout<<v.at(i);}
is simply wrong.
The valid code will look like
reverse(v.begin(), v.end());
for(auto i : v){ cout << i;}
Also if you are paid for the number of symbols entered in the source code then this statement
if (n % 2 == 0){ v.push_back(0); }else{ v.push_back(1); }
looks very good because it contains many symbols. Otherwise it would be better to write
v.push_back( n % 2 );
Also in one of your programs you allocate dynamically an array
int* v = new int[nr];
but not free it. In this case it would be better to use smart pointer std::unique_ptr.
You could also try to write a recursive function. For example
#include <iostream>
#include <vector>
std::vector<unsigned int> & dec_to_bin( std::vector<unsigned int> &v,
unsigned int x )
{
const unsigned int Base = 2;
static size_t n;
unsigned int digit = x % Base;
++n;
if ( x /= Base )
{
dec_to_bin( v, x );
}
else
{
v.reserve( n );
n = 0;
}
v.push_back( digit );
return v;
}
int main()
{
while ( true )
{
std::cout << "Enter a non-negative number (0-exit): ";
unsigned int x = 0;
std::cin >> x;
if ( !x ) break;
std::vector<unsigned int> v;
dec_to_bin( v, x );
for ( auto digit : v ) std::cout << digit;
std::cout << std::endl;
}
return 0;
}
If to enter sequentially
15
7
3
1
0
then the program output will be
Enter a non-negative number (0-exit): 15
1111
Enter a non-negative number (0-exit): 7
111
Enter a non-negative number (0-exit): 3
11
Enter a non-negative number (0-exit): 1
1
Enter a non-negative number (0-exit): 0