Как написать C ++ версию функции powerset Python

0

Я хочу написать алгоритм максимальной клики для использования с матрицей смежности. Я следую видео, которое объясняет, как кодировать и реализовывать алгоритм с использованием Python. В настоящее время я пытаюсь закодировать функцию poweret через 2 минуты в видео.

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])

Я хочу переписать это в C++. Я не уверен, должен ли я использовать массивы или нет. До сих пор я кодировал ниже, но я не знаю, как вернуть пустой массив в пустой массив (когда list elts имеет размер 0).

Я написал функцию isEmpty для массива, поскольку я не могу использовать len(elts) как в Python. Мой подход, вероятно, не самый лучший подход, поэтому я открыт для любых советов.

ОБНОВИТЬ:

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

}

В моем основном я имею:

list<int> elts;

list<int>::iterator i;

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

powerSet(elts);    

Я не знаю, что делать дальше.

Код должен использовать либо array/list/vector который мы называем "elts" (short для элементов). Тогда, во-первых, он должен добавить пустой список [], затем остальную часть мощности (все показано на видео).

Так, например, в случае, когда elts = [1,2,3,4], мой код должен возвращать:

'[ [],[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] ]  '  

Я не знаю, как использовать array/list/vector чтобы сделать это.

  • 1
    Начнем с того, что Python Snip использует списки, так что это может быть хорошим местом для начала. Я рекомендую использовать контейнерный класс STL (std :: list, std :: vector, std :: array [если вы можете работать с C ++ 11] и т. Д.), Который позволит вам воспользоваться преимуществами .empty() функции и уберите необходимость для isEmpty.
  • 0
    Нуитка может «компилировать» питон в C ++. Может быть, попробуйте несколько простых утверждений и проверить помощь сгенерированного кода.
Показать ещё 4 комментария
Теги:
arrays
powerset
clique-problem

1 ответ

0
Лучший ответ

Здесь довольно буквальный перевод кода Python

#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;
    }
}

Для этого используется vector<int> для набора целых чисел. И тогда vector этого, т.е. vector<vector<int>> представляет собой список наборов целых чисел. Вы специально спросили об одном

Я не знаю, как вернуть пустой массив в пустой массив (когда list elts имеет размер 0).

Первый оператор return возвращает список с одним элементом, пустым множеством, с использованием vector конструктора, первым аргументом которого является n - количество элементов в vector, а вторым аргументом является элемент, повторяющий n раз. Альтернативная, но более длинная альтернатива

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

Я попытался сохранить код простым и избежать слишком много эзотерических функций C++. Надеюсь, вы сможете справиться с этим с помощью хорошей справки. Одна идиома C++, которую я использовал, добавляет один вектор к другому, как и allofthem.insert(allofthem.end(), withElt.begin(), withElt.end()); ,

Также в C++, который "ближе к металу", чем Python, вы, вероятно, используете только один vector вместо трех векторов smaller, с withElt и allofthem. Это приводит к более короткому и более оптимальному коду ниже.

//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;
    }
}

Тестовый код ниже

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;
}

В качестве сноски я был приятно удивлен, насколько простым было перевести с Python на C++. Я читал, что имеет смысл использовать Python для написания (или прототипа) алгоритмов, а затем переписать на языке, таком как C++ по мере необходимости, но, как говорится в пословице, видение - это верить.


Вот версия программы, которая работает с C++ 98. Я вернулся основные черты C++ 11, которые я использовал (>> в объявлениях шаблона и диапазон на основе 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;
}
  • 0
    Спасибо за ответ TooTone! Я пытаюсь запустить оптимальный код + тестовый код выше. При первой попытке запуска я получаю сообщение об ошибке «>>» должно быть `>> 'в списке аргументов вложенного шаблона", поэтому я изменил везде, где написано vector <vector <int>, на vector <vector <int>> и об ошибке больше не сообщалось. Но теперь она дает мне ошибку «ожидаемое первичное выражение перед« const »» в строке 8 основного тестового кода int «vector <vector <int >> ps = powerSet (input); Msgstr "Не слишком уверен, что нужно сделать, чтобы исправить ошибку.
  • 0
    Это также останавливает меня для той же самой ошибки «ожидаемое первичное выражение перед« const »» в этой строке: «for (const vector <int> & s: меньше) {» в вашем более длинном коде выше.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню