Domanda

I want to write the maximal clique algorithm for use with an adjacency matrix. I'm following a video which explains how to code and implement the algorithm using Python. I'm currently trying to code the powerset function at 2 minutes into the video.

def powerSet(elts):
    if len(elts) == 0:
        return [[]]
    else:
        smaller = powerSet(elts[1:])
        elt = [elts[0]]
        withElt = []
        for s in smaller:
            withElt.append(s + elt)
        allofthem = smaller + withElt
    return allofthem

print powerSet([1, 2, 3, 4, 5])

I want to rewrite this in C++. I'm not sure if I should be using arrays or not. So far I have coded the below but I don't know how to return an empty array inside an empty array (when the elts list is of size 0).

I wrote an isEmpty function for the array since I cant use len(elts) like in Python. My approach is probably not the best approach to take so I am open to any advice.

UPDATE:

array powerSet(int elts[])
{
     if (isEmpty(elts)==1)
     {
          return {{}};
     }

}

In my int main I have:

list<int> elts;

list<int>::iterator i;

for (i=elts.begin(); i != elts.end(); ++i)
      cout << *i << " ";
      cout << endl;

powerSet(elts);    

I don't know what to do from here.

The code should use either an array/list/vector that we call 'elts' (short for elements). Then firstly, it should add the empty list [], then the rest of the power set (all shown in the video).

So for example, in the case that elts = [1,2,3,4], my code should return:

`[ [],[4],[3],[4,3],[2],[4,2],[3,2],[4,3,2],[1],[4,1],[3,1],[4,3,1],[2,1],[4,2,1],[‌​3,2,1],[4,3,2,1] ]  `  

I don't know how to use array/list/vector to do the above.

È stato utile?

Soluzione

Here's a fairly literal translation of the Python code

#include <vector>
using std::vector;
#include <iostream>
using std::cout;

//def powerSet(elts):
vector<vector<int>> powerSet(const vector<int>& elts)
{
//  if len(elts) == 0:
    if (elts.empty()) {
//      return [[]]
        return vector<vector<int>>(
            1, // vector contains 1 element which is...
            vector<int>()); // ...empty vector of ints
    }
//  else:
    else {
//      smaller = powerSet(elts[1:])
        vector<vector<int>> smaller = powerSet(
            vector<int>(elts.begin() +1, elts.end()));
//      elt = [elts[0]]
        int elt = elts[0]; // in Python elt is a list (of int)
//      withElt = []
        vector<vector<int>> withElt;
//      for s in smaller:
        for (const vector<int>& s: smaller) {
//          withElt.append(s + elt)
            withElt.push_back(s);
            withElt.back().push_back(elt);
        }
//      allofthem = smaller + withElt
        vector<vector<int>> allofthem(smaller);
        allofthem.insert(allofthem.end(), withElt.begin(), withElt.end());
//      return allofthem
        return allofthem;
    }
}

This uses vector<int> for the set of integers. And then a vector of this, i.e. vector<vector<int>> is a list of sets of integers. You specifically asked about one thing

I don't know how to return an empty array inside an empty array (when the elts list is of size 0).

The first return statement returns a list with one element, the empty set, using a vector constructor, whose first argument n is the number of elements in the vector, and whose second argument is the element to repeat n times. An equivalent but more long-winded alternative is

    vector<vector<int>> powerSetOfEmptySet;
    vector<int> emptySet;
    powerSetOfEmptySet.push_back(emptySet);
    return powerSetOfEmptySet;

I've tried to keep the code simple and avoid too many esoteric C++ features. Hopefully you can work through it with the aid of a good reference. One C++ idiom I have used is appending one vector to another as in allofthem.insert(allofthem.end(), withElt.begin(), withElt.end());.

Also in C++, which is "closer to the metal" than Python, you would probably use just one vector in place of the three vectors smaller, withElt and allofthem. This leads to the shorter and more optimal code below.

//def powerSet(elts):
vector<vector<int>> powerSet(const vector<int>& elts)
{
//  if len(elts) == 0:
    if (elts.empty()) {
//      return [[]]
        return vector<vector<int>>(1, vector<int>());
    }
//  else:
    else {
//      smaller = powerSet(elts[1:])
        vector<vector<int>> allofthem = powerSet(
            vector<int>(elts.begin() +1, elts.end()));
//      elt = [elts[0]]
        int elt = elts[0]; // in Python elt is a list (of int)
//      withElt = []
//      for s in smaller:
//          withElt.append(s + elt)
//      allofthem = smaller + withElt
        const int n = allofthem.size();
        for (int i=0; i<n; ++i) {
            const vector<int>& s = allofthem[i];
            allofthem.push_back(s);
            allofthem.back().push_back(elt);
        }
//      return allofthem
        return allofthem;
    }
}

Test code below

int main()
{
    const int N = 5;
    vector<int> input;
    for(int i=1; i<=N; ++i) {
        input.push_back(i);
    }
    vector<vector<int>> ps = powerSet(input);
    for(const vector<int>& set:ps) {
        cout << "[ ";
        for(int elt: set) {
            cout << elt << " ";
        }
        cout << "]\n";
    }
    return 0;
}

As a footnote, I was pleasantly surprised as to how straightforward it was to translate from Python into C++. I had read that it might make sense to use Python to write (or prototype) algorithms, and then rewrite in a language such as C++ as necessary, but, as the proverb goes, seeing is believing.


Here is a version of the program that works with C++98. I reverted the basic C++11 features that I used (>> in template declarations and range-based for).

#include <vector>
using std::vector;
#include <iostream>
using std::cout;

vector<vector<int> > powerSet(const vector<int>& elts)
{
    if (elts.empty()) {
        return vector<vector<int> >(1, vector<int>());
    }
    else {
        vector<vector<int> > allofthem = powerSet(
            vector<int>(elts.begin() +1, elts.end()));
        int elt = elts[0];
        const int n = allofthem.size();
        for (int i=0; i<n; ++i) {
            const vector<int>& s = allofthem[i];
            allofthem.push_back(s);
            allofthem.back().push_back(elt);
        }
        return allofthem;
    }
}

int main()
{
    const int N = 5;
    vector<int> input;
    for(int i=1; i<=N; ++i) {
        input.push_back(i);
    }
    vector<vector<int> > ps = powerSet(input);
    for(vector<vector<int> >::const_iterator i=ps.begin(); i!=ps.end(); ++i) {
        const vector<int>& set = *i;
        cout << "[ ";
        for(vector<int>::const_iterator j=set.begin(); j!=set.end(); ++j) {
            int elt = *j;
            cout << elt << " ";
        }
        cout << "]\n";
    }
    return 0;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top