-
Notifications
You must be signed in to change notification settings - Fork 0
/
cartesian_multiplier.h
177 lines (148 loc) · 4.46 KB
/
cartesian_multiplier.h
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#ifndef CARTESIAN_GUARD
#define CARTESIAN_GUARD
#include "defines.h"
#include <vector>
#include <assert.h>
#include <iostream>
namespace ctb
{
/*
* This class serves for generating cartesian product of arbitrary number of sets of the same type. I am writting this explicitly since it is not the first time I need this feature.
*
* The cartesian multiplier is basically an iterator which dereferences to a list of iterators. Respectively it is an iterator which can be used directly to obtain iterators of iterators of the sets over which we are constructing the cartesian product.h
* */
template <typename T>
class cartesian_multiplier : forward_iterator_tag
{
private:
bool end_b;
typedef vector<typename T::iterator> itr;
itr begins;
itr ends;
itr middles;
public:
typedef cartesian_multiplier<const T> constant;
typedef itr iterator;
//lets assume that default constructors and operators will work
cartesian_multiplier();
cartesian_multiplier& operator++();
void add(T&);
void reset();
iterator& operator*();
iterator* operator->();
const iterator& operator*() const;
const iterator* operator->() const;
bool operator==(const cartesian_multiplier&)const ;
bool operator!=(const cartesian_multiplier&)const ;
cartesian_multiplier begin();
cartesian_multiplier end();
cartesian_multiplier::constant begin() const;
cartesian_multiplier::constant end() const;
static void self_test();
};
typedef cartesian_multiplier<vector<int> > cartesian_multiplier_default;
template <typename T>
typename cartesian_multiplier<T>::constant cartesian_multiplier<T>::begin() const
{
return cartesian_multiplier::constant(*this);
}
template <typename T>
typename cartesian_multiplier<T>::constant cartesian_multiplier<T>::end() const
{
return cartesian_multiplier::constant();
}
template <typename T>
cartesian_multiplier<T> cartesian_multiplier<T>::begin()
{
return cartesian_multiplier(*this);
}
template <typename T>
cartesian_multiplier<T> cartesian_multiplier<T>::end()
{
return cartesian_multiplier();
}
template <typename T>
cartesian_multiplier<T>::cartesian_multiplier() : end_b(true)
{
}
template <typename T>
void cartesian_multiplier<T>::reset()
{
for(int i = middles.size()-1; i >= 0; i--)
middles[i] = begins[i];
end_b = false;
}
template <typename T>
void cartesian_multiplier<T>::add(T& t)
{
begins.push_back(t.begin());
ends.push_back(t.end());
middles.push_back(t.begin());
end_b = false;
}
template <typename T>
cartesian_multiplier<T>& cartesian_multiplier<T>::operator++()
{
for(int i = middles.size()-1; i >= 0; i--)
{
++middles[i];
if(middles[i] == ends[i])
middles[i] = begins[i];
else
return *this;
}
end_b = true;
return *this;
}
template <typename T>
const typename cartesian_multiplier<T>::iterator* cartesian_multiplier<T>::operator->() const
{
return &middles;
}
template <typename T>
const typename cartesian_multiplier<T>::iterator& cartesian_multiplier<T>::operator*() const
{
return middles;
}
template <typename T>
typename cartesian_multiplier<T>::iterator* cartesian_multiplier<T>::operator->()
{
return &middles;
}
template <typename T>
typename cartesian_multiplier<T>::iterator& cartesian_multiplier<T>::operator*()
{
return middles;
}
template <typename T>
bool cartesian_multiplier<T>::operator!=(const cartesian_multiplier& c) const
{
return !(this->operator==(c));
}
template <typename T>
bool cartesian_multiplier<T>::operator==(const cartesian_multiplier& c) const
{
return c.end_b == end_b || (middles == c.middles && c.begins == begins && c.ends == ends);
}
template <typename T>
void cartesian_multiplier<T>::self_test()
{
cout << "testing cartesian multiplier" << endl;
vector<int> a = {1,2,3};
vector<int> b = {3,4,5};
vector<int> c = {1,3,1,4,1,5,2,3,2,4,2,5,3,3,3,4,3,5};
vector<int> d;
cartesian_multiplier<vector<int> > itr;
itr.add(a);
itr.add(b);
for( auto r : itr)
{
for( auto s : r)
{
d.push_back(*s);
}
}
assert(c==d);
}
};
#endif