0

I am trying to find repeated points from a given 10 points, where each points has x and y values. I have written the below code but can not get correct results. The output should be {3,5},{4,2},{2,4},{7,8}

  #include <iostream>
#include<stdlib.h>
using namespace std;

struct point
{
int x;
int y;
};
void distinctPoints(point arr[], int size)
{
cout<<"Repeated Points"<<endl;
    cout<<"x, y"<<endl;
  for(int i = 0; i< size; i++)
    for(int j = i+1; j< size; j++)
        {
        if ((arr[i].x==arr[j].x) && (arr[i].y==arr[j].y))
            {
            cout<<arr[j].x <<", "<<arr[j].y<<endl;
            break;
            }
        }
}
int main()
{   int size=10;
    point points[size]={{3,5},{4,2},{2,4},{3,5},{7,8},{7,8},{4,2},{7,8},{3,5},{2,4}};
    distinctPoints(points, size);
    return 0;
}
mwater07
  • 131
  • 4
  • 14
  • Your algorithm complexity is n^2, plus you print identical points several times... One advice would be to sort your point list first and then check for successive repeats. – Picaud Vincent Sep 06 '17 at 21:16
  • Nearly same question here https://stackoverflow.com/questions/4003584/more-elegant-way-to-check-for-duplicates-in-c-array – Picaud Vincent Sep 06 '17 at 21:29
  • Put your code into a compiler, without making any change. Works perfectly fine, aside from the fact that of course points are written out multiple times. – Aziuth Sep 06 '17 at 21:34

3 Answers3

0

I have tweaked your distinctPoints method so that it doesn't print the duplicates multiple times even if the dups appear more than twice. See the following edits:

void distinctPoints(point arr[], int size)
{
  point dups[size];
  cout<<"Distinct Points"<<endl;
  cout<<"x, y"<<endl;
  for(int i = 0; i < size; i++)
    for(int j = 0; j < size; j++) {
        if ((arr[i].x==arr[j].x) && (arr[i].y==arr[j].y)) {
            if(j < i) {
                break;
            }
            else if( j == i) {
                continue;
            }
            else {
                cout<<arr[i].x <<", "<<arr[i].y<<endl;
                break;
            }
        }
    }

}
VHS
  • 9,534
  • 3
  • 19
  • 43
0

Your approach (once corrected, as VHS's answer did) could be fine for a small number of points, but, with a bigger set of data, an O(N2) algorithm could be too inefficient.

You can take advantage of the average costant time that takes inserting an element in a std::unordered_set, even if you are required to write a comparison function and an hash function for your class.

The algorithm presented below uses two unordered_set's:

  • uniques ends up storing all the elements that are present in the source container, without repetitions.
  • repeated stores a unique instance of only the elements that are present multiple times.

An element is copied to the output only if it's already present in uniques, but not in repeated.

#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <iterator>

struct point
{
    int x, y;

    bool operator== (point const& b) const
    {
        return x == b.x  &&  y == b.y;
    }
};

namespace std {

template<> struct hash<point>
{
    std::size_t operator() (point const& p) const
    {
        return (std::hash<int>{}(p.x) << 1) ^ std::hash<int>{}(p.y);
    }
};

}

std::ostream& operator<< (std::ostream& os, point const& pt)
{
    return os << '(' << pt.x << ", " << pt.y << ')';
}

template<class InputIt, class OutputIt>
OutputIt copy_repeated_values(InputIt first, InputIt last, OutputIt dest)
{
    using value_type = typename InputIt::value_type;

    std::unordered_set<value_type> uniques, repeated;

    return std::copy_if(
        first, last, dest, [&] (value_type const& value) {
            return
                not uniques.insert(value).second  &&
                repeated.insert(value).second;
        }
    );
}

int main()
{
    std::vector<point> points {
        {3,5}, {4,2}, {2,4}, {3,5}, {7,8}, {7,8}, {4,2}, {7,8}, {3,5}, {2,4}
    };

    copy_repeated_values(
        std::begin(points), std::end(points), 
        std::ostream_iterator<point>(std::cout, " ")
    );

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

The output is:

(3, 5) (7, 8) (4, 2) (2, 4) 
Bob__
  • 12,361
  • 3
  • 28
  • 42
-1

This should do what you are trying to achieve, I am making use of set and maps in c++ which takes care of unique entries.

The map keeps track of already visited points.

#include <iostream>
#include<stdlib.h>
#include <set>
#include <map>
using namespace std;

struct point
{
int x;
int y;
};

map<pair<int, int>, int> mapCountOfPoints;

set<pair<int, int> > disPoints;

void distinctPoints(point arr[], int size)
{
  for(int i=0; i<size; i++) {
    pair<int, int> temp = make_pair(arr[i].x, arr[i].y);
    if(mapCountOfPoints.find(temp) != mapCountOfPoints.end()) {
      disPoints.insert(temp);
    } else {
      mapCountOfPoints[temp] = 1;
    }
  }         

  // Now we will iterate over the set to get the distinct set of points
  for(set<pair<int, int>>::iterator it=disPoints.begin(); it!=disPoints.end(); it++) {
    cout<<it->first<<" "<<it->second<<endl;
  }

}
int main()
{   int size=10;
    point points[size]={{3,5},{4,2},{2,4},{3,5},{7,8},{7,8},{4,2},{7,8},{3,5},{2,4}};
    distinctPoints(points, size);
    return 0;
}

Hope this helps!

zenwraight
  • 2,002
  • 1
  • 10
  • 14
  • ohh ya my bad @PicaudVincent let me fix it – zenwraight Sep 06 '17 at 21:26
  • Updated my answer, this should fix it – zenwraight Sep 06 '17 at 21:30
  • 1
    Since you also improved the style of the code, might I suggest to rename the function into something that indicates what action happens? And that you get rid of the globals? – Aziuth Sep 06 '17 at 21:38
  • @Aziuth What do you think could be a good method name, I am thinking of findDistinctPointsAndPrint() – zenwraight Sep 06 '17 at 21:40
  • @zenwraight It's descriptive, but a little bit long. Also, having to functions in one is a sign that they should be separated, imho. I'd simply go with printDistinctPoints (By the way, "distinct"? Not "repeated"?). But what I'd really do is not having it print anything and going with a function `vector findDistinctPoints(const vector& input)` and a function `void print(const vector& input)`, calling those like print(findDistinctPoints(points));`. Haves the functionality clear and creates the clearly reusable print function. – Aziuth Sep 06 '17 at 21:45
  • valid point, I will try to make the changes just getting out of office, thanks a lot @Aziuth – zenwraight Sep 06 '17 at 21:46
  • Or else if you have enough reputation, please feel free to update my answer ..... I agree with you – zenwraight Sep 06 '17 at 21:47
  • Thank you all for your valuable comments. On the original post, I would like to stop inner loop after the condition true. Basically, I dont want to continue to check the rest of the elements in array. Currently the original code output those . (3, 5) (4, 2) (2, 4) (3, 5) (7, 8) (7, 8). But, i only would like to have (3, 5) (4, 2) (2, 4) (7, 8). – mwater07 Sep 07 '17 at 13:59