I have this function that is suppose to return all possible permutation of integers inside the vector. The code is based from an existing code that does a permutation of strings, I tried to remodeled it to work on vectors but apparently, they dont work similarly as I thought..
I'll appreciate any help that you could offer thanks;
vector<vector<int>> permute(vector<int> &v1, vector<int> &v2){
vector<vector<int>> v;
if( v1.empty() )
{
v.push_back(v2);
return v;
}
for(auto it = v1.begin(); it != v1.end(); it++){
vector<int> temp1 = v1;
temp1.erase(it); //there's a runtime error on this line
vector<int> temp2 = v2;
temp2.push_back(*it);
permute(temp1, temp2);
}
return v;
}
This is the original code that permutes a string.
void string_permutation( std::string& orig, std::string& perm )
{
if( orig.empty() )
{
std::cout<<perm<<std::endl;
return;
}
for(int i=0;i<orig.size();++i)
{
std::string orig2 = orig;
orig2.erase(i,1);
std::string perm2 = perm;
perm2 += orig.at(i);
string_permutation(orig2,perm2);
}
}
Here you go:
template < typename T>
void vec_permute( std::vector<T> &orig, std::vector<T> &perm)
{
if(orig.empty())
{
for( auto &x : perm)
std::cout<<x;
std::cout<<"\n";
return;
}
for(typename std::vector<T>::size_type i=0;i <orig.size();++i)
{
std::vector<T> orig2(orig);
orig2.erase(std::find(orig2.begin(),orig2.end(),orig.at(i)));
std::vector<T> perm2(perm);
perm2.push_back(orig.at(i));
vec_permute(orig2,perm2);
}
}
Demo: http://coliru.stacked-crooked.com/a/01ded4b778aa4165
Iterators can only be used with the container that you instanciated them with
Related
I'm writing program for graphs. In this program I have a method which has to return vertices inside the weak component originating at vertex. I am getting: Error "vector iterators incompatible"
struct graph {
std::vector <std::vector<int>> gr;
};
std::vector<int> weak_component(const graph& g, int vertex) {
std::vector<int> ret;
stack<int> s;
s.push(vertex);
vector<int>::iterator j;
bool* used = new bool[g.gr.size()];
while (!s.empty()) {
int hodn=s.top();
s.pop();
used[hodn] = true;
for (j == g.gr[hodn].begin(); j != g.gr[hodn].end(); j++) {
if (!used[*j]) {
s.push(*j);
ret.push_back(*j);
}
}
}
return ret;
}
What's wrong with it?
Since you are taking g as a const graph&, this means g.gr is treated as const inside your function. begin on a const vector<T> returns a const_iterator. (also you used == instead of = for assignment)
for (std::vector<int>::const_iterator j = g.gr[hodn].begin(); ...)
But with C++11 or newer you may as well use auto to avoid this
for (auto j = g.gr[hodn].begin(); ...)
or a range-based for:
for (auto&& e : g.gr) {
if (!used[e]) {
s.push(e);
ret.push_back(e);
}
}
I'm writing program for graphs. In this program I have a method which has to return vertices inside the weak component originating at vertex. I am getting: Error "vector iterators incompatible"
struct graph {
std::vector <std::vector<int>> gr;
};
std::vector<int> weak_component(const graph& g, int vertex) {
std::vector<int> ret;
stack<int> s;
s.push(vertex);
vector<int>::iterator j;
bool* used = new bool[g.gr.size()];
while (!s.empty()) {
int hodn=s.top();
s.pop();
used[hodn] = true;
for (j == g.gr[hodn].begin(); j != g.gr[hodn].end(); j++) {
if (!used[*j]) {
s.push(*j);
ret.push_back(*j);
}
}
}
return ret;
}
What's wrong with it?
Since you are taking g as a const graph&, this means g.gr is treated as const inside your function. begin on a const vector<T> returns a const_iterator. (also you used == instead of = for assignment)
for (std::vector<int>::const_iterator j = g.gr[hodn].begin(); ...)
But with C++11 or newer you may as well use auto to avoid this
for (auto j = g.gr[hodn].begin(); ...)
or a range-based for:
for (auto&& e : g.gr) {
if (!used[e]) {
s.push(e);
ret.push_back(e);
}
}
In the code below, strArray is a array of strings, and vec contains corresponding ID of each string.
I want to sort IDs in vec based on strings in strArray.
How can I design the Comp function in sort?
class myClass
{
public:
int V;
vector<int> vec;
string* strArray;
myClass(int v);
void myFunc();
}
myClass::myClass(int v, vector<int> vec1)
{
V = v;
strArray = new string[v];
vec.swap(vec1)
}
void myClass::myFunc()
{
//....
for(i = 0; i<V; i++)
strArray[i] = GenerateString(vec[i]);// GenerateString() can return a string.
sort(vec.begin(), vec.end(), Comp);// sort vec based on strArray,how to design the Comp funtion?
//....
}
main()
{
int myints[] = {32,71,12,45,26,80,53,33};
vector<int> myvector (myints, myints+8);
myClass obj(8, myvector);
obj.myFunc();
return 0;
}
Change member string* strArray; to std::pair<std::string, int> strArray;, change allocation strArray = new std::pair<std::string, int>[v]; and make the following changes in your myFunc
void myClass::myFunc()
{
//....
for(i = 0; i<V; i++)
strArray[i] = make_pair(GenerateString(vec[i]), vec[i]);// GenerateString() can return a string.
sort(vec.begin(), vec.end());
std::transform(
strArray,
strArray + V,
vec.begin(),
[](const std::pair<std::string, int> &p) -> int { return p.second; }
);
//....
}
In this code we couple or pair the number (vec[i]) that generated the string and sort the array. Now using std::transform, the number is copied back to the vec
From comment
If you don't understand lambda function, you can also write a function elsewhere and pass it as fourth argument in std::transform
static int fetch_int_from_pair(const std::pair<std::string, int> &p) {
return p.second;
}
...
td::transform(
strArray,
strArray + V,
vec.begin(),
fetch_int_from_pair
);
I'm attempting to create an algorithm in C++ which will give me all of the possible combinations of a set of list items (input in a map format). I want to avoid duplicates and make sure to cover all possible combinations. To simplify the example, here's what the input may look like:
map<string, vector<string> > sandwichMap;
sandwichMap["bread"].push_back("wheat");
sandwichMap["bread"].push_back("white");
sandwichMap["meat"].push_back("ham");
sandwichMap["meat"].push_back("turkey");
sandwichMap["meat"].push_back("roastbeef");
sandwichMap["veggie"].push_back("lettuce");
sandwichMap["sauce"].push_back("mustard");
I'd feed this map into the algorithm, and it should spit out a vector with all of the possible combinations (using one of each key type):
wheat+ham+lettuce+mustard
wheat+turkey+lettuce+mustard
wheat+roastbeef+lettuce+mustard
white+ham+lettuce+mustard
white+turkey+lettuce+mustard
white+roastbeef+lettuce+mustard
It needs to work for any map of string vectors. So far I've tried and gotten close, but I end up with duplicate combinations and missed combinations:
sandwichList getCombinations(sandwichMap sMap)
{
locList retList;
int totalCombos = 1;
for (sandwichMapIt i = sMap.begin(); i != sMap.end(); ++i)
{
totalCombos *= i->second.size();
}
retList.resize(totalCombos);
int locCount;
for (sandwichMapIt a = sMap.begin(); a != sMap.end(); ++a)
{
locCount = 0;
for (locListIt l = a->second.begin(); l != a->second.end(); ++l)
{
for (unsigned int i = 0; i < totalCombos / a->second.size(); ++i)
{
retList[i + a->second.size() * locCount] += *l;
}
locCount++;
}
}
return retList;
}
Any help would be greatly appreciated!
Updated code:
#include <vector>
#include <map>
#include <list>
#include <iostream>
typedef std::vector<std::string> strVec;
typedef std::list<std::string> strList;
typedef std::map<std::string, strVec> sandwichMap;
int main()
{
sandwichMap sMap;
sMap["bread"].push_back("wheat");
sMap["bread"].push_back("white");
sMap["meat"].push_back("ham");
sMap["meat"].push_back("turkey");
sMap["meat"].push_back("roastbeef");
sMap["veggie"].push_back("lettuce");
sMap["sauce"].push_back("mustard");
strList finalSandwichList;
for (sandwichMap::iterator i = sMap.begin(); i != sMap.end(); ++i)
{
strList tmpSandwich;
for (strVec::iterator j = i->second.begin(); j != i->second.end(); ++j)
{
if (finalSandwichList.empty())
{
tmpSandwich.push_back(*j);
}
else
{
for (strList::iterator k = finalSandwichList.begin(); k != finalSandwichList.end(); ++k)
tmpSandwich.push_back(*k + "+" + *j);
}
}
tmpSandwich.swap(finalSandwichList);
}
for (strList::iterator i = finalSandwichList.begin(); i != finalSandwichList.end(); ++i)
{
std::cout << *i << std::endl;
}
return 0;
}
//solution
std::list<std::string> result;
for(auto i=sandwichMap.begin(); i!=sandwichMap.end(); ++i) {
std::list<std::string> new_result;
for(auto j=i->second.begin(); j!=i->second.end(); ++j) {
if(result.empty())
new_result.push_back(*j);
else
for(auto k=result.begin(); k!=result.end(); ++k)
new_result.push_back(*k + "+" + *j);
}
new_result.swap(result);
}
This should work :
#include<iostream>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
map<string, vector<string>> sMap;
vector<string> add;
int sett[200], countt;
void solve(map<string, vector<string>>::iterator itt, int ct, vector<string> addd){
vector<string> tmp = itt->second;
if(ct == countt){
for(int j=0;j<addd.size();j++){
cout<<addd[j]<<" ";
}
cout<<endl;
return;
}
itt++;
for(int i=0;i<tmp.size();i++){
//cout<<tmp[i]<<" ";
addd.push_back(tmp[i]);
solve(itt, ct+1, addd);
vector<string>::iterator tempIt = addd.end();
addd.erase(tempIt--);
}
}
int main(){
sMap["bre"].push_back("wh");
sMap["bre"].push_back("whi");
sMap["me"].push_back("ham");
sMap["me"].push_back("tur");
sMap["me"].push_back("rr");
sMap["veg"].push_back("let");
sMap["sau"].push_back("mus");
countt = sMap.size();
solve(sMap.begin(), 0, add);
return 0;
}
I have used backtracking to evaluate every possible combination.
Note : it is in c++11 you might need to change some part of the code for lower version of c++
link to output : http://ideone.com/Ou2411
The code is kinda long because of the helper methods, but it does the job:
#include <vector>
#include <string>
#include <map>
#include <iostream>
using namespace std;
template <class T>
vector<T> Head(const vector<T> &v) {
return vector<T>(v.begin(), v.begin() + 1);
}
template <class T>
vector<T> Tail(const vector<T> &v) {
auto first = v.begin() + 1;
auto last = v.end();
return vector<T>(first, last);
}
template <class T>
vector<T> Concat(const vector<T> &v1, const vector<T> &v2) {
vector<T> result = v1;
result.insert(result.end(), v2.begin(), v2.end());
return result;
}
vector<vector<string>> CombineVectorWithScalar(const vector<vector<string>> &v, const string &scalar) {
vector<vector<string>> result = v;
for (unsigned i = 0; i < v.size(); i++) {
result[i].push_back(scalar);
}
return result;
}
vector<vector<string>> CombineVectorWithVector(const vector<vector<string>> &v1, const vector<string> &v2) {
if (v2.empty()) {
return vector<vector<string>>();
}
else {
auto headCombination = CombineVectorWithScalar(v1, v2.front());
auto tailCombination = CombineVectorWithVector(v1, Tail(v2));
return Concat(headCombination, tailCombination);
}
}
vector<string> GetKeys(const map<string, vector<string>> &mp) {
vector<string> keys;
for (auto it = mp.begin(); it != mp.end(); ++it) {
keys.push_back(it->first);
}
return keys;
}
vector<vector<string>> CombineMapValues(const map<string, vector<string>> &mp) {
vector<string> keys = GetKeys(mp);
vector<vector<string>> result;
auto &firstVector = mp.begin()->second;
for (auto it = firstVector.begin(); it != firstVector.end(); ++it) {
vector<string> oneElementList;
oneElementList.push_back(*it);
result.push_back(oneElementList);
}
vector<string> restOfTheKeys = Tail(keys);
for (auto it = restOfTheKeys.begin(); it != restOfTheKeys.end(); ++it) {
auto ¤tVector = mp.find(*it)->second;
result = CombineVectorWithVector(result, currentVector);
}
return result;
}
void PrintCombinations(const vector<vector<string>> & allCombinations) {
for (auto it = allCombinations.begin(); it != allCombinations.end(); ++it) {
auto currentCombination = *it;
for (auto itInner = currentCombination.begin(); itInner != currentCombination.end(); ++itInner) {
cout << *itInner << " ";
}
cout << endl;
}
}
int main() {
map<string, vector<string> > sandwichMap;
sandwichMap["bread"].push_back("wheat");
sandwichMap["bread"].push_back("white");
sandwichMap["meat"].push_back("ham");
sandwichMap["meat"].push_back("turkey");
sandwichMap["meat"].push_back("roastbeef");
sandwichMap["veggie"].push_back("lettuce");
sandwichMap["sauce"].push_back("mustard");
auto allCombinations = CombineMapValues(sandwichMap);
PrintCombinations(allCombinations);
return 0;
}
void generate_all(std::map<std::string,std::vector<std::string>>::iterator start,
std::vector<std::string::iterator> accomulator,
std::map<std::string,std::vector<std::string>>& sMap){
for (auto it=start; it!=sMap.end(); ++it){
for (auto jt=it->second.begin(); jt!=it->second.end(); jt++){
generate_all(start+1,accomulator.pus_back[jt],sMap);
}
}
if (accomulator.size() == sMap.size()){
// print accomulator
}
}
Call with generate_all(sMap.begin(),aVector,sMap);
If the map is too big to go recursively, you can always generate an equivalent iterative code.
This solution is not recursive. Basically what it does is the following:
Compute how many combinations are actually possible
Know that for each key in the map, you're going to have to add nrCombinations/nrItemsInKey of them in total.
You can see it as a tree growing, branching more and more the more keys you have visited.
If you keep track of how many there are, how spaced they are and where they start you can automatically fill all combinations.
Code
#include <vector>
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, std::vector<std::string> > sandwichMap;
sandwichMap["bread"].push_back("wheat");
sandwichMap["bread"].push_back("white");
sandwichMap["meat"].push_back("ham");
sandwichMap["meat"].push_back("turkey");
sandwichMap["meat"].push_back("roastbeef");
sandwichMap["veggie"].push_back("lettuce");
sandwichMap["sauce"].push_back("mustard");
sandwichMap["sauce"].push_back("mayo");
// Compute just how many combinations there are
int combinationNr = 1;
for ( auto it : sandwichMap ) {
combinationNr *= it.second.size();
}
std::vector<std::vector<std::string>> solutions(combinationNr);
// We start with empty lists, thus we only have one cluster
int clusters = 1, clusterSize = combinationNr;
for ( auto category : sandwichMap ) {
int startIndex = 0;
int itemsNr = category.second.size();
int itemsPerCluster = clusterSize / itemsNr;
for ( auto item : category.second ) {
for ( int c = 0; c < clusters; ++c ) {
for ( int i = 0; i < itemsPerCluster; ++i ) {
// We sequentially fill each cluster with this item.
// Each fill starts offset by the quantity of items
// already added in the cluster.
solutions[startIndex+i+c*clusterSize].push_back(item);
}
}
startIndex += itemsPerCluster;
}
clusters *= itemsNr;
clusterSize = combinationNr / clusters;
}
for ( auto list : solutions ) {
for ( auto element : list ) {
std::cout << element << ", ";
}
std::cout << "\n";
}
return 0;
}
I have to create a generic function that removes all duplicates in a vectorInt a vectorBook which is a class i created that has getYear and getName functions. I'm not sure how to make the the function because the vectorInt is compared because the Book gets compared with getName and getYear. Int is compared on one level while Book is compared on two levels.
template<class T> vector<T> removeDuplicates(vector<T> n){
for(unsigned int i = 0; i < n.size();i++){
T current = n.at(i);
for(unsigned int j = i + 1; j < n.size(); j++){
T compare = n.at(j);
if(current == compare)
n.erase(n.begin() + j);
}
}
return n;
}
Thanks for the help
EDIT:
Tried using this
template <class T> std::vector<T> removeDuplicates(std::vector<T> vec)
{
std::sort( vec.begin(), vec.end() );
vec.erase( std::unique( vec.begin(), vec.end() ), vec.end() );
return vec;
}
but for books i keep getting an error
class Book {
public:
Book();
Book(std::string, int);
int getYear() const {
return year;
}
std::string getName() const {
return name;
}
bool operator==(Book const &);
private:
std::string name;
int year;
};
A pure STL version:
#include <algorithm>
template <class T> std::vector<T> removeDuplicates(std::vector<T> vec)
{
std::sort( vec.begin(), vec.end() );
std::vec.erase( std::unique( vec.begin(), vec.end() ), vec.end() );
return vec;
}
You can make it more efficient by taking and returning references rather than copies.
Code snarfed shamelessly from answer to this question.
As long as Book has a usable operator == implementation, this should work just fine. If not, then you will need to create a specialization for Book or add such an operator:
class Book
{
// ...
public:
bool operator==(Book const &);
};
bool Book::operator==(Book const & other)
{
return getName() == other.getName() && getYear() == other.getYear();
}
Note that you have an off-by-one error in your traversal -- if you do wind up deleting an item, the very next item will be skipped over. Consider using this loop instead:
for (vector<T>::iterator i = n.begin; i != n.end(); ++i) {
for (vector<T>::iterator j = i + 1; j != n.end(); /* */) {
if (*i == *j) {
n.erase(j++);
} else {
++j;
}
}
}