A better way to sort this char pair?

Hello once again :)

So currently I'm trying to sort a pair that takes a int and a char.
And after it takes those values it runs a "strange type of bubblesort" to make sure the char 'R' comes before the char 'G' and the char 'G' comes before 'B' essentialy RGB. It works as intended if i input the values :

1
2
3
4
5
6
5
1 B
3 R
4 B
6 G
9 R


It comes out as i want it to be :
1
2
3
4
5
3 R
9 R	
6 G
1 B
4 B


Although this is valid, i feel like my solution is very very complicated and it can be done a better way, but i'm not sure what exactly that would be and in some cases its a bit slow.
Also if you try to insert for example '2 B' it would not sort the number as :
1
2
3
1 B
2 B
4 B


But instead you will get
1
2
3
1 B
4 B
2 B


I kind of found a way to also fix that with the current sorting, but it seems very complicated and unlogical.
So i really hope you guys can advice me a better way to make this work better as it is kind of obvious it might be a bad method.

Thank once again, if there is something i explained poorly i'm looking forward to explain it in more details.

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <string>
#define MAXN 1000000
using namespace std;

pair<int, char> rgb[MAXN];
int n;
void charSort()
{
    int i, j;
    char ourChar;
    int h;
    for(i=n-2; i>=0; i--){
    for(j=0; j<=i; j++)
    {
        if(rgb[j].second !='R' && rgb[j+1].second == 'R')
        {
            ourChar=rgb[j].second; rgb[j].second= rgb[j+1].second;
            h = rgb[j].first; rgb[j].first=rgb[j+1].first;
            rgb[j+1].second= ourChar;
            rgb[j+1].first=h;
        }
        else if(rgb[j].second !='G' && rgb[j+1].second == 'G' && rgb[j].second !='R')
        {
            ourChar=rgb[j].second; rgb[j].second= rgb[j+1].second;
            h = rgb[j].first; rgb[j].first=rgb[j+1].first;
            rgb[j+1].second= ourChar;
            rgb[j+1].first=h;
        }
    }
 }
}

int main() {

    int i,j;
    scanf("%d", &n);
    for(i = 0 ; i < n; i++)
    {
        int a;
        char b;
        cin >> a >> b;
        rgb[i] = make_pair(a, b);
    }

    charSort();
    for(i = 0; i < n; i++)
    {
       cout << rgb[i].first << " " << rgb[i].second << "\n";

    }

    return 0;
}
You want to sort first by the char, descending, and then by the int, ascending?

The pair's default ordering is first by int, ascending, and then by char, ascending.
http://www.cplusplus.com/reference/utility/pair/operators/
1
2
3
4
5
template <class T1, class T2>
  bool operator<  (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{
  return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second);
}


You'll need something like:
1
2
3
4
5
template <class T1, class T2>
  bool myorder(const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
{
  return lhs.second>rhs.second || (!(rhs.second>lhs.second) && lhs.first<rhs.first);
}

Then std::sort could do the ordering: std::sort( std::begin(rgb), std::end(rgb), myorder );
@keskiverto

I tried something similar, but in such case it would not accept the third argument in this example "myorder" to sort it by that.

 
rgb2.cpp|35|note:   candidate expects 2 arguments, 3 provided|
Last edited on
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
#include <iostream>
#include <utility>
#include <algorithm>
#include <iterator>

enum colour_t { RED = 1, GREEN = 2, BLUE = 4 };

inline std::pair< colour_t, int > translate( std::pair< int, char > icpair )
{
    if( icpair.second == 'G' || icpair.second == 'g' ) return { GREEN, icpair.first } ;
    else if( icpair.second == 'B' || icpair.second == 'b' ) return { BLUE, icpair.first } ;
    else return { RED, icpair.first } ;
}

int main()
{
    std::pair< int, char > rgb[] { {5,'B'}, {8,'R'}, {1,'G'}, {2,'B'}, {2,'G'}, {7,'R'},
                                   {5,'R'}, {8,'B'}, {8,'G'}, {6,'B'}, {7,'G'}, {9,'R'} } ;


    std::sort( std::begin(rgb), std::end(rgb),
               []( const auto& icpa, const auto& icpb ) { return translate(icpa) < translate(icpb) ; } ) ;

    for( const auto& icp : rgb ) std::cout << icp.first << ' ' << icp.second << '\n' ;
}

http://coliru.stacked-crooked.com/a/052d4d67a1b5cc7d
Thanks for both your imputs guys.

I actually managed to make @keskiverto example also work perfectly.
I should read more the documentation next time ! :)

Thank you also @JLBorges also very nice interesting solution.
Topic archived. No new replies allowed.