0

I have a vector vector<Points>list_of_points; that contains the points A B C D A. I want to find all the possible combinations of the vector keeping the outer two elements in the same place. For example, A B C D A -- A B D C A -- A C B D A -- A C D B A -- A D B C A -- A D C B A. Any advice on how I can do this?

I am doing this because each point has an x,y coordinate. I am trying to find the shortest distance to go to all the elements and return back to the original element. I am thinking to set the minimum distance equal to the first combination A B C D A, and compare all other combinations

//pseudocode
min distance = distance of A B C D A

while(there are still combinations){
   find another combinations of the vector.
   if that distance is smaller than min distance, make it the new min distance 
   save the path in a vector
}

If needed here is my implementation

#include <cmath>
#include <string>
#include <vector>
#include <iostream>

using namespace std;

class Point
{
  private:
    int m_x;
    int m_y;
    string m_name;

  public:
    Point(int x, int y, string name)
      : m_x(x), m_y(y), m_name(name)
    {}
    
    Point(){};
    
    int getX() const {return m_x;}
    void setX(int x) {m_x=x;}

    int getY() const {return m_y;}
    void setY(int y) {m_y=y;}

    string getName() const {return m_name;}
    
    
    float getDistance(Point &other);

    string toString() const;

    void printPoint() const;

    // used for printing Point using << operator. For example:
    // Point p(1,2,"A");
    // cout << p << endl;
    friend ostream& operator<<(ostream &os, const Point &p);

};

class ListOfPoints
{ 
  private:
    int elements;
    
  public:
    vector<Point>sorted_list;
    vector<Point>unsorted_list;
    
    void Unsorted_add(Point &newPt);
    void Sorted_add(Point &newPt);
    void Create_unsorted();
    void Sort_list();
    
    void set_elements(int n);
    int get_elements();
    
    
    ListOfPoints();

    // adds a new point to the end of the list
    void addPoint(Point &newPt);
    
    // prints the list of points
    void printList() const;
    
    // draws the points
    void draw() const;

};

string Point::toString() const{
  // examples how to create string from small parts
  string str(m_name);
  str += " = (";
  str += std::to_string(m_x);
  str.append(",").append(std::to_string(m_y)).append(")");
  return str;
} 

float Point::getDistance(Point &other){
  float x1 = float(this->getX());
        cout << "this->x = "<< this->getX() <<endl;
        cout << "this->y = "<<this->getY() <<endl;
        float y1 = float(this->getY());
        float x2 = float(other.getX());
        float y2 = float(other.getY());
        //cout << "x = " << x2 << endl;
        //cout << "y = " << y2 << endl;
        float dist = sqrt( pow(x2-x1,2) + pow(y2-y1,2) );
        cout << "dist = " << dist << endl;
        return dist;
}
void Point::printPoint() const{
  cout << toString() << endl;
}

// used for printing Point using << operator.
// For example, the following code will work
// Point origin(0,0,'O');
// cout << origin;
ostream& operator<<(ostream &os, const Point &p) {
  return os << p.toString();
}

ListOfPoints::ListOfPoints() {

}


void ListOfPoints::Sorted_add(Point &newPt)  {
  sorted_list.push_back(newPt);
}

void ListOfPoints::Unsorted_add(Point &newPt)  {
  unsorted_list.push_back(newPt);
}


void ListOfPoints::set_elements(int n){
  elements = n;
}

int ListOfPoints::get_elements(){
  return this->elements;
}

void ListOfPoints::Create_unsorted(){
  int x;
  int y;
  string name;
  
  cout << "Enter the Number of elements" << endl;
  cin >> elements;
  for(int i = 0; i<elements; i++){
    cout << "Enter the name of the element: " << endl;
    cin >> name;
    cout <<"Enter the x value" << endl;
    cin >> x;
    cout <<"Enter they y vlaue" << endl;
    cin >> y;
    Point p(x,y,name);
    unsorted_list.push_back(p);
    
  }

  cout << elements << endl;
  return;
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
CS_12319
  • 1
  • 1
  • there would be nPn number of results : where n is size of vector - 2, and nPn means permutation. You will probably have to find a way to limit it, otherwise there will be a whole lot of results – WARhead Dec 06 '20 at 05:01
  • 1
    The standard library has a function for finding permutations called [std::next_permutation](https://en.cppreference.com/w/cpp/algorithm/next_permutation). You can just give it iterators to the second and last element as the range to permute and then manually add the first and last value. – nick Dec 06 '20 at 05:13
  • https://softwareengineering.stackexchange.com/questions/315836/algorithm-to-determine-the-fastest-route-passing-in-all-points look through this for a better algorithm, since brute forcing it might not be feasible for longer vectors, brute force has a complexity O(n!) – WARhead Dec 06 '20 at 05:13

1 Answers1

1

Going by your description, the following program demonstrates what you are trying to achieve using std::next_permutation:

#include <algorithm>
#include <string>
#include <iostream>

int main()
{
    std::string test = "ABCDA";

    // sort the items after the beginning and before the end of the sequence
    std::sort(test.begin() + 1, std::prev(test.end()));
    do
    {
        std::cout << test << "\n";
      // permute the middle elements
    } while (std::next_permutation(test.begin() + 1, std::prev(test.end())));
}

Output:

ABCDA
ABDCA
ACBDA
ACDBA
ADBCA
ADCBA

To expand this to your Point class, you will need to sort the middle points in some way, and then apply the same logic using std::next_permutation.

Here is a small example:

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

struct Point
{
    int m_x;
    int m_y;
    int get_x() const { return m_x; }
    int get_y() const { return m_y; }
    Point(int x = 0, int y = 0) : m_x(x), m_y(y) {}
};
    
int main()
{
    std::vector<Point> test = {{0,0},{1,2},{2,1},{3,6},{2,7},{10,10}};
    std::vector<std::vector<Point>> results;
    auto sorter = [](const Point& p1, const Point& p2) { return std::tie(p1.m_x, p1.m_y) < std::tie(p2.m_x, p2.m_y); };
    
    // sort the items after the beginning and before the end of the sequence
    std::sort(test.begin() + 1, std::prev(test.end()), sorter);
    do
    {
        results.push_back(test);
    } while (std::next_permutation(test.begin() + 1, std::prev(test.end()), sorter));
    
    for (auto& r : results)
    {
        for (auto& p : r)
           std::cout << "{" << p.get_x() << "," << p.get_y() << ") ";
        std::cout << "\n";
    }
}

Output:

{0,0) {1,2) {2,1) {2,7) {3,6) {10,10) 
{0,0) {1,2) {2,1) {3,6) {2,7) {10,10) 
{0,0) {1,2) {2,7) {2,1) {3,6) {10,10) 
{0,0) {1,2) {2,7) {3,6) {2,1) {10,10) 
{0,0) {1,2) {3,6) {2,1) {2,7) {10,10) 
{0,0) {1,2) {3,6) {2,7) {2,1) {10,10) 
{0,0) {2,1) {1,2) {2,7) {3,6) {10,10) 
{0,0) {2,1) {1,2) {3,6) {2,7) {10,10) 
{0,0) {2,1) {2,7) {1,2) {3,6) {10,10) 
{0,0) {2,1) {2,7) {3,6) {1,2) {10,10) 
{0,0) {2,1) {3,6) {1,2) {2,7) {10,10) 
{0,0) {2,1) {3,6) {2,7) {1,2) {10,10) 
{0,0) {2,7) {1,2) {2,1) {3,6) {10,10) 
{0,0) {2,7) {1,2) {3,6) {2,1) {10,10) 
{0,0) {2,7) {2,1) {1,2) {3,6) {10,10) 
{0,0) {2,7) {2,1) {3,6) {1,2) {10,10) 
{0,0) {2,7) {3,6) {1,2) {2,1) {10,10) 
{0,0) {2,7) {3,6) {2,1) {1,2) {10,10) 
{0,0) {3,6) {1,2) {2,1) {2,7) {10,10) 
{0,0) {3,6) {1,2) {2,7) {2,1) {10,10) 
{0,0) {3,6) {2,1) {1,2) {2,7) {10,10) 
{0,0) {3,6) {2,1) {2,7) {1,2) {10,10) 
{0,0) {3,6) {2,7) {1,2) {2,1) {10,10) 
{0,0) {3,6) {2,7) {2,1) {1,2) {10,10) 

I chose the sorting criteria based on the x and y values, with the x values being compared first

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • I'm a little confused what do you mean by sort. How do I know what criteria to sort it by. Doesn't std::next_permuatation need some sort of criteria? I tried and got a long list of errors. – CS_12319 Dec 06 '20 at 06:01