-5

So the question statement is:

Given an int n, follows by n pairs of numbers which are the coordinates of points. You must print out the point in the ordered entered, then print them in the order sorted by the distance from the origin.

You will need to a < operator to the Point class for this to work

Write your solution in C++

Example input

5 8 9 6 5 3 4 3 5 2 6

Example output 2

(8,9) (6,5) (3,4) (3,5) (2,6) 
(3,4) (3,5) (2,6) (6,5) (8,9)

So, I tried to design separate functions of a class Point that stores the pairs. Here's the cpp for my Point class:

//Compare
bool Point::operator==(const Point& point) const { 
    return ((x == point.x) && (y == point.y)); 
} 

//Distance
// d=√((x2 – x1)² + (y2 – y1)²)
double Point::operator-(const Point& point) const { 
    return (sqrt(pow(point.x-x,2) + pow(point.y-y,2))); 
} 

// Less then (add this)
bool Point::operator<(const Point& point) const { 
   return (((point.x) < (x))&& (point.y)<(y));
} 

//Constructor acts as a mutator
//to get values

Point::Point(double new_x, double new_y)
{
    x = new_x;
    y = new_y;
}

//MUTATOR FUNCTIONS
void Point::SetX(double new_x)
{
    x = new_x;
}

void Point::SetY(double new_y)
{
    y = new_y;
}

I don't know how to write a display function for main() that will sort the pairs and return them according to distance. How do I make the sort work?

void displayPoints(vector<Point> &points) {
  // Finish
  for (int i=0; i<points.size(); i++) {
    cout << points[i] << " ";
  }
  cout << endl;
}

And in the main, I need to call sort(points.begin(),points.end()) and then displayPoints(points) and it should come out sorted

  • Hi sturggler. Welcome to stackoverflow. Do you have a specific question about this problem? You can't just ask someone to provide a complete solution for you here. – digby280 Mar 02 '23 at 21:23
  • Why did you choose to implement the distance algorithm in `operator-` instead of in `operator<`, like the instructions asked for? For instance, if you put the coordinates into a container like `std::vector` and then sort it with `std::sort()`, it will use `operator<` to sort the items. Also, where is the origin point? `(0,0)`? Your `operator` is comparing the distance from one `Point` to another `Point`, not comparing 2 `Point`s to an origin and returning which one is closer, like the instructions asked for. – Remy Lebeau Mar 02 '23 at 21:28
  • So, the operator - function was already built by the instructor. The only places I am supposed to insert code is the operator< and in the displaypoints function. – sturggler Mar 02 '23 at 21:34
  • @sturggler "*the `operator -` function was already built by the instructor*" - then you were given bad code, because the code shown is not how subtraction of coordinate points should be implemented. – Remy Lebeau Mar 02 '23 at 21:35
  • i'm not surprised honestly because he's not a great teacher but i need to do something to make it work for a midterm – sturggler Mar 02 '23 at 21:38

2 Answers2

3

Your implementation of operator< only returns true if this->x < point.x and this->y < point.y, which is clearly not comparing the distances to origo:

constexpr bool Point::operator<(const Point& point) const { // made it constexpr
   return (((point.x) < (x))&& (point.y)<(y));
} 

constexpr Point a{1., 0.}, b{0., 2.};
static_assert(a < b); // should pass, but your `operator<` says `not(a < b)`

What you need to compare if this is closer to origo is to compare their distances to origo - but, do you really need the distance? No, comparing the squared distances will produce exactly the same result.

bool Point::operator<(const Point& point) const { 
   return x * x + y * y < point.x * point.x + point.y * point.y;
} 

To do the printing you require, you could add an overload for operator<<. While at it, you can add an operator>> overload to read a Point too:

// a function to read `Point` values from an `istream`:
friend std::istream& operator>>(std::istream& is, Point& p) {
    return is >> p.x >> p.y;
}

// a function to print a `Point` to an `ostream`:
friend std::ostream& operator<<(std::ostream& os, const Point& p) {
    return os << '(' << p.x << ',' << p.y << ')';
}

With that, you can read and print the Points like so:

if(int n; std::cin >> n && n > 0) {
    // create `n` `Point`s:
    std::vector<Point> pnts(n);

    // fill in the values by reading from `std::cin`:
    for(auto& pnt : pnts) std::cin >> pnt;

    // print the `Point`s in the original order:
    for(const auto& pnt : pnts) std::cout << pnt << ' ';
    std::cout << '\n';

    // sort according to `Point::operator<`:
    std::sort(pnts.begin(), pnts.end());

    // display the `Point`s sorted according to distances to origo:
    for(const auto& pnt : pnts) std::cout << pnt << ' ';
    std::cout << '\n';
}

Demo

If you want a separate displayPoints function, make it take the vector by const&:

void displayPoints(const std::vector<Point>& points) {
    for (size_t i = 0; i < points.size(); ++i) {
        std::cout << points[i] << ' ';
    }   
    std::cout << '\n';
}

or simpler, using a range based for-loop:

void displayPoints(const std::vector<Point>& points) {
    for (const auto& pnt : points) {
        std::cout << pnt << ' ';
    }
    std::cout << '\n';
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
1

You already have the algorithm for calculating the distance between 2 points. You just need to apply that algorithm to your operator< (ie, it doesn't belong in operator-). Your operator< should return true if this (the left-hand Point being compared) is closer to the origin then the input point (the right-hand Point being compared), otherwise return false.

For example, try something like this (assuming the origin is (0,0)):

//Distance
// d=√((x2 – x1)² + (y2 – y1)²)
bool Point::operator<(const Point& point) const { 
    const Point origin{0, 0};
    double distance1 = sqrt(pow(x - origin.x, 2) + pow(y - origin.y, 2));
    double distance2 = sqrt(pow(point.x - origin.x, 2) + pow(point.y - origin.y, 2));
    return distance1 < distance2;

    /* which can be simplified to:
    return (pow(x,2) + pow(y,2)) < (pow(point.x,2) + pow(point.y,2));
    or:
    return ((x*x) + (y*y)) < ((point.x * point.x) + (point.y * point.y));
    */
} 

You might consider adding a DistanceFrom() type of method to your Point class, eg:

double Point::DistanceFrom(const Point &point) const {
    return sqrt(pow(x - point.x, 2) + pow(y - point.y, 2));
    /* alternatively:
    double xd = x - point.x;
    double yd = y - point.y;
    return sqrt((xd * xd) + (yd * yd));
    */
}

And then you can use that in your operator<, eg:

bool Point::operator<(const Point& point) const { 
    const Point origin{0, 0};
    return DistanceFrom(origin) < point.DistanceFrom(origin);
}

Either way, you can then implement the actual sort using the standard std::sort() algorithm, which uses operator< to sort items, eg:

#include <iostream>
#include <vector>
#include <algorithm>

void display(const std::vector<Point>& points) {
    for(const auto &point: points) {
        std::cout << '(' << point.x << ',' << point.y << ") ";
    }
    std::cout << std::endl;
}

...

std::vector<Point> points;
int count;

std::cin >> count;
for(int i = 0; i < count; ++i)
{
    double x, y;
    std::cin >> x >> y;
    points.emplace_back(x, y);
}

display(points);
std::sort(points.begin(), points.end());
display(points);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770