permutation for two different list

Hi,
I got a permutation question, I got two different std::list:
1
2
3
4
5
6
7
8
list<string> slist;
slist.push_back("str111");
slist.push_back("str222");
slist.push_back("str333");

list<int> ilist;
ilist.push_back(100);
ilist.push_back(200);

I need the permutation for both two lists(sorry I don't know how to explain this in English), the result should be like this:
------ one permutation ------
str111 str222 str333
100 200
------ one permutation ------
str111 str222 str333
200 100
------ one permutation ------
str111 str333 str222
100 200
------ one permutation ------
str111 str333 str222
200 100
------ one permutation ------
str222 str111 str333
100 200
------ one permutation ------
str222 str111 str333
200 100
------ one permutation ------
str222 str333 str111
100 200
------ one permutation ------
str222 str333 str111
200 100
------ one permutation ------
str333 str111 str222
100 200
------ one permutation ------
str333 str111 str222
200 100
------ one permutation ------
str333 str222 str111
100 200
------ one permutation ------
str333 str222 str111
200 100


here's my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <string>
#include <list>
#include <algorithm>
using namespace std;


template <typename value_t>
void dump_list(const list<value_t>& lst) {
	for_each(lst.begin(), lst.end(), [](const value_t& value) {
		cout << value << " ";
	});
	cout << endl;
}

int main() {
	list<string> slist;
	slist.push_back("str111");
	slist.push_back("str222");
	slist.push_back("str333");

	list<int> ilist;
	ilist.push_back(100);
	ilist.push_back(200);

	do {
		do {
			cout << "------ one permutation ------" << endl;
			dump_list(slist);
			dump_list(ilist);
		} while(next_permutation(ilist.begin(), ilist.end()));
	} while(next_permutation(slist.begin(), slist.end()));
}


see, there are two do while loop, if I need a permutation with more than two lists, there'll be more and more do-while loops, that's make code looks urgly, I wonder if stl has some tricky way that can do this with just one next_permutation? maybe write some helper functor?

Thanks.
Last edited on
Hmm... Maybe something like this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <typename T, typename Iterator>
void recursive_iterator(const T &metalist, Iterator i, Iterator end){
    if (i != end){
        do {
            Iterator next = i;
            ++next;
            recursive_iterator(metalist, next, end);
        } while (next_permutation(i->begin(), i->end()));
        return;
    }
    cout << "------ one permutation ------" << endl;
    for (auto j = metalist.begin(), e = metalist.end(); j != e; ++j)
        dump_list(*j);
}

//metalist may be a container of containers of strings.
template <typename T>
void cartesian_product_of_permutations(const T &metalist){
    recursive_iterator(metalist, metalist.begin(), metalist.end());
}
Last edited on
Thanks, but I still don't understand how to use this, like for a three-list-situation

list<string> slist;
list<int> ilist
list<char> clist;
Oh, they're different types. I didn't notice that.

This is very naughty code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <string>
#include <list>

struct NullPointer{
	NullPointer *data;
	NullPointer *next;
};

template <typename T, typename NodeT>
struct BadList{
	T data;
	NodeT *next;
	~BadList(){
		delete next;
	}
};

template <typename T2>
BadList<T2, NullPointer> *New(const T2 &data){
	BadList<T2, NullPointer> *ret = new BadList<T2, NullPointer>;
	ret->data = data;
	ret->next = 0;
	return ret;
}

template <typename T2, typename NodeT2>
BadList<T2, NodeT2> *cons(const T2 &data, NodeT2 *list){
	BadList<T2, NodeT2> *ret = new BadList<T2, NodeT2>;
	ret->data = data;
	ret->next = list;
	return ret;
}

template <typename T, typename Function>
void iterator(T *list, Function &f){
	if (!list)
		return;
	f(list->data);
	iterator(list->next, f);
}

template <typename Function>
void iterator(NullPointer *list, Function &f){}

struct MyFunction{
	template <typename T>
	void operator()(const T &data){
		auto i = data.begin(), e = data.end();
		for (; i != e; ++i)
			std::cout <<*i<<std::endl;
	}
};

int main(){
	std::list<int> list1;
	std::list<std::string> list2;
	std::list<double> list3;
	list1.push_back(42);
	list1.push_back(84);
	list2.push_back("Hello, ");
	list2.push_back("World!");
	list3.push_back(3.141592);
	list3.push_back(2.718281);
	auto l = cons(list1, cons(list2, New(list3)));
	MyFunction f;
	iterator(l, f);
	delete l;
}
Last edited on
Thanks helios, I got your "use a wrapper" idea.
Well, since I've already been driven insane making this, I may as well post it.
Here's how to make recursive iterators:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

template <typename T, typename Function>
struct recursive_iterator{
	T *list;
	Function *f;
	void operator()() const{
		auto next = get_recursive_iterator(this->list->next, *this->f);
		(*this->f)(this->list->data, next);
	}
};

template <typename T2, typename Function>
recursive_iterator<T2, Function> get_recursive_iterator(T2 *list, Function &f){
	recursive_iterator<T2, Function> ret;
	ret.list = list;
	ret.f = &f;
	return ret;
}

template <typename T>
struct recursive_iterator<NullPointer, T>{
	NullPointer *list;
	T *f;
	void operator()() const{}
};

struct MyOtherFunction{
	template <typename T1, typename T2>
	void operator()(const T1 &data, const T2 &iterator){
		iterator();
		auto i = data.begin(), e = data.end();
		for (; i != e; ++i)
			std::cout <<*i<<std::endl;
	}
};
Topic archived. No new replies allowed.