-1

I have written my own compare function to sort a vector of pairs. My sort function should be like this. The point (i,j) will be ahead of point(x,y) if it is closer to (5,5), vice-versa. I am finding the distance and then comparing based on that. The code is

  #include<iostream>
  #include<stdlib.h>
  #include<cstdio>
  #include<vector>
  #include<algorithm>

  using namespace std;

  double distance(int a, int b,  int x, int y)
  {
     return sqrt(pow(a-x,2.0)+pow(b-y,2.0));
  }
  bool mycomp(const pair<int, int >&i, const pair<int, int >&j)
  {
    double dis=distance(i.first, i.second, 5,5);
    double dis2=distance(j.first, j.second, 5, 5);
    if(dis<dis2)
       return i.first< j.first;
    return i.first>j.first;
 }

 int main()
 {
    int n;
    cin>>n;
    vector<pair<int, int> > p;
    for(int i=0; i < n; i++)
    {
        int a,b;
        cin>>a >>b;
        p.push_back(make_pair(a,b));
    }
    sort(p.begin(),p.end(),mycomp);
    for(int i=0; i<n; i++)
        cout<<p[i].first<<" "<<p[i].second<<endl;
    return 0;
}
Konrad Krakowiak
  • 12,285
  • 11
  • 58
  • 45
  • If `a` is `(5,5)` and `b` is `(6,5)`, you'll have both `mycomp(a,b) == true` and `mycomp(b,a) == true`. This violates the conditions for `std::sort`. – molbdnilo Jan 15 '15 at 22:02

3 Answers3

0

You did not specify what you mean by “not working,” so I’ll take that as license to point out anything I like about your code.

Your mycomp routine does not do what you describe. In particular, always make sure that a comparison routine is antisymmetric.

bool mycomp(const pair<int, int >&i, const pair<int, int >&j)
{
  double dis=distance(i.first, i.second, 5, 5);
  double dis2=distance(j.first, j.second, 5, 5);
  if (dis < dis2) {
    return true;
  }
  if (dis2 > dis) {
    return false;
  }
  // tie break
  return std::less<decltype(i)>(i,j);
}

If that line with the decltype does not work, you may have to spell the tie break out yourself.

Christopher Creutzig
  • 8,656
  • 35
  • 45
0

The answer by @ChristopherCreutzig should solve your problem. I'm going to suggest something that will obviate the need for computing a square root.

   int square(int a)
   {
      return a*a;
   }

   int distanceSquared(int a, int b,  int x, int y)
   {
      return square(a-x) + square(b-y);
   }

   bool mycomp(const pair<int, int >&i, const pair<int, int >&j)
   {
     double dis1 = distanceSquared(i.first, i.second, 5, 5);
     double dis2 = distanceSquared(j.first, j.second, 5, 5);
     if ( dis1 != dis2 )
        return (dis1 < dis2);

     return (i.first < j.first);
  }
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thanks that worked. can you tell how you thought for this if ( dis1 != dis2 ) return (dis1 < dis2); –  Jan 15 '15 at 22:04
  • dis1 and dis2 has nothing to do with the pairs. those are just temp values. How if dis1< dis2 the respective pair in the vector is ahead of the other . thanks –  Jan 15 '15 at 22:05
  • @user3126404, since you were using distance from (5, 5) as a way to sort the vector, I thought you could use that logic. You could as easily have used `if ( i.first != j.first ) return (i.first < j.first);` – R Sahu Jan 15 '15 at 22:10
  • why will this not work ? if ( dis1 == dis2 ) return (i.first< j.first); else if (dis1 < dis2) return i.first < j.first; else return j.first < i.first; –  Jan 15 '15 at 22:20
  • That's because it's not symmetric w.r.t. `i` and `j`. – R Sahu Jan 15 '15 at 22:22
  • Can you post your sample data and how you wish the sorted data to be? – R Sahu Jan 15 '15 at 22:35
-1

This is not the right condition check. if(dis<dis2) return i.first< j.first return i.first>j.first;

Should suffice return dis < dis2;

  • This is not an answer. If you want to clarify something, add them as comments to the OP's question. – R Sahu Jan 15 '15 at 21:47
  • I don't want to clarify. I want to give a hint and an exercise for a beginner. No one will gain from a solution, with a hint one will. – Bartosz Bosowiec Jan 15 '15 at 21:55