For some reason the check_sort function can only be called once within the main function otherwise the workflow freezes after it's first executed.
For example. The output ends at:
How many elements for container? 5000
Check: list is sorted
Elapsed time: 0.32 seconds
Instead of continuing like:
How many elements for next container? 5000
Check: list is sorted
Elapsed time: 0.30 seconds
Check: set is sorted
Elapsed time: 0.01 seconds
Check: vector is sorted
Elapsed time: 0.25 seconds
Full program below:
#include <cmath>
#include <iterator>
#include <iostream>
#include <iomanip>
#include <vector>
#include <ctime>
#include <list>
#include <set>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef void Inserter(vector<double>);
vector<double> gen_data(int num_elts);
void insert_list(vector<double> data);
void insert_set(vector<double> data);
void insert_vector(vector<double> data);
void time_insert( Inserter inserter, vector<double> data);
template <class Iter> bool is_sorted(Iter first, Iter last);
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind);
list<double> l;
set<double> s;
vector<double> v;
int main() {
srand(time(0));// initialize random number generator
cout << "How many elements for container? ";
int num_elts = 0;
while (cin >> num_elts) {
if (num_elts <= 0)
cout << "Error, should be > 1";
else {
vector<double> data = gen_data(num_elts);
check_sort(l.begin(), l.end(), "list");
time_insert(insert_list, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_set, data);
check_sort(v.begin(), v.end(), "vector");
time_insert(insert_vector, data);
}
cout << "\nHow many elements for next container? ";
}
return 0;
}
void time_insert( Inserter inserter, vector<double> data) {
clock_t t1 = clock();
if (t1 == clock_t(-1)) { //if clock() doesn’t work
cerr << "sorry, no clock\n";
exit(1);
}
inserter(data);
clock_t t2 = clock();
if (t2 == clock_t(-1)) {
cerr << "sorry, clock overflow\n";
exit(2);
}
cout << "Elapsed time: " << fixed << setprecision(2)
<< double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";
}
class Larger_than {
double v;
public:
Larger_than(double vv) : v(vv){}
bool operator()(double x) const {return x>v;}
};
// Sorts and then inserts data into a list
void insert_list(vector<double> data)
{
list<double> l;
for(int i=0; i < data.size(); i++){
list<double>::iterator p = find_if(l.begin(),l.end(), Larger_than(data[i]));
l.insert(p, data[i]);
}
}
// Sorts and then inserts data into a list
void insert_set(vector<double> data)
{
set<double> s;
for(int i=0; i < data.size(); i++){
set<double>::iterator p = find_if(s.begin(),s.end(), Larger_than(data[i]
));
s.insert(p, data[i]);
}
}
// Sorts and then inserts data into a list
void insert_vector(vector<double> data)
{
vector<double> v;
for(int i=0; i < data.size(); i++){
vector<double>::iterator p = find_if(v.begin(),v.end(), Larger_than(data
[i]));
v.insert(p, data[i]);
}
}
// generate num_elts random numbers in the range [0.0, 1.0),
// which are returned in a vector
vector<double> gen_data (int num_elts)
{
vector<double> result;
for (int i = 0; i < num_elts; i++) {
double datum = 1.0*rand()/RAND_MAX;
result.push_back(datum);
}
return result;
}
// is container spanned by [from, last) sorted?
template <class Iter> bool is_sorted(Iter first, Iter last)
{
Iter next = first; // next element
for (next++; next != last; next++, first++) {
if (*first > *next)
return false;
}
return true;
}
// prints a msg describing container kind, as well as whether container
// spanned by [from, last) is sorted
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind)
{
cout << "Check: " << cont_kind << " is ";
if (!is_sorted(first, last)) cout << "not ";
cout << "sorted\n";
}
I don't know if this is part of your problem, but is_sorted doesn't work right if first is the end of the container. next gets incremented past end and undefined behavior is encountered.
EDIT: Actually this is definitely it: You don't populate the vector/list/set containers prior to calling the check function on them. Even if you called the insert functions before calling the check function it still wouldn't work because each insert_* function declares a local to populate which shadows the global variable you're trying to fill.
EDIT2: In insert_set the find_if is actually making your code less performant than it should be. You should just use std::set::insert and let it use its built-in sorting, which will be more efficient than find_if because it knows the implementation of the underlying set.
Your template function is_sorted() doesn't check properly whether first is equal to last before incrementing next which is a copy of first:
template <class Iter> bool is_sorted(Iter first, Iter last)
{
Iter next = first; // next element
for (next++; next != last; next++, first++) {
if (*first > *next)
return false;
}
return true;
}
This could lead to problems if you get to iterate over an empty range, I believe.
template <class Iter> bool is_sorted(Iter first, Iter last)
{
if (first == last)
return false;
for (Iter next = first+1; next != last; next++, first++)
{
if (*first > *next)
return false;
}
return true;
}
I'm not certain you get empty ranges...so this may be a red herring.
Since you don't set the list before checking that it is sorted (and you don't check that it is sorted after inserting the data), you do run into issues with empty ranges. You need to reverse the sequence of your insert and check operations:
vector<double> data = gen_data(num_elts);
time_insert(insert_list, data);
check_sort(l.begin(), l.end(), "list");
time_insert(insert_set, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_vector, data);
check_sort(v.begin(), v.end(), "vector");
You should avoid duplicated code in your main loop by calling a function to get the number of elements to process. Also, it is conventional to report errors on cerr.
static int get_num_elts()
{
int num_elts;
cout << "How many elements for container? ";
cin >> num_elts;
if (num_elts < 1)
cerr << "Error: number should be >= 1" << endl;
return num_elts;
}
...
int num_elts;
while ((num_elts = get_num_elts()) > 0)
{
vector<double> data = gen_data(num_elts);
time_insert(insert_list, data);
check_sort(l.begin(), l.end(), "list");
time_insert(insert_set, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_vector, data);
check_sort(v.begin(), v.end(), "vector");
}
Your code does not enter the body of the loop in the is_sorted function
instead for (next++; next != last; next++, first++) do for (next; next != last; next++, first++) . Because if first == last, then it would be a problem and that is what you are facing. But not incrementing the next pointer will do no harm as the first comparison will compare the first element with itself which will always be evaluated as false in a greater than comparison with itself.
Related
The problem arise when I am trying to write an insert function that is suppose to move all elements in the array up at the specified location given by the iterator and then insert a new value into the array at the position given by the iterator.
The code is getting errors in the insert function with the following error:
no match for 'operator[]' (operand types are 'std::basic_string [1000]' and 'std::basic_string')
I am new to using iterators, and I think that it is not possible to access array elements with pointers as indices. So I am not sure if there is another way to do this, or do I need to overload the [] operator to make it work some how?
template <class T>
class Vector {
public:
typedef T* iterator;
Vector () { }
T& operator[](unsigned int i) {
return items[i];
}
// T& operator[](iterator i) {
//return items[*i];
//}
iterator begin () {
return &items[0];
}
iterator end () {
return &items[used];
}
int size () { return used; }
iterator insert (iterator position, const T& item) {
for(Vector<T>::iterator i=&items[998]; i>=position; i--)
{
items[*(i+1)]=items[*i];
}
items[*position]= item;
return position;
}
private:
T items[1000];
int used=0;
};
This code is problematic in the sense that it creates 1000 elements of type T, even if logically it is empty. Also, if there are more than 1000 insertions, then the upper elements are discarded.
As for the compilation issues, I have tries to compile the code with Vector<int> and it compiles fine, but crashes. For the same reason it crashes with Vector<int> it does not compile with Vector<std::string>. The Issue is with the type of *i, which is , i.e., std::string in the case of Vector<std::string>. Either use iterator all the way, or use indexes, but don't mix. Using iterators:
for(Vector<T>::iterator i=&items[998]; i>=position; i--)
{
*(i+1)=*i;
}
Edit :
[Just noticed an answer by Scheff that figured this out, after completing this edit]
The above invokes undefined behavior for v.insert(v.begin(), value) since i iterates before items. To avoid that, the iteration should stop before it falls off items:
for(Vector<T>::iterator i=&items[999]; i > position; i--)
{
*i = *(i-1);
}
Also, note that the line following the loop should also be fixed:
items[*position]= item; // <--- BUG: also mixing indexes and iterators
Or using indexes:
for(int i= 998; begin() + i>=position; i--)
{
items[i+1]=items[i];
}
In addition to the answer of Michael Veksler, I tried to get it working (and hence needed a bit longer).
So, with his first proposed fix and additionally
items[*position]= item;
changed to
*position = item;
the following test compiles and runs:
#include <iostream>
int main()
{
Vector<double> vec;
vec.insert(vec.begin(), 1.0);
vec.insert(vec.begin(), 2.0);
vec.insert(vec.begin(), 3.0);
std::cout << "vec.size(): " << vec.size() << '\n';
for (int i = 0; i < vec.size(); ++i) {
std::cout << "vec[" << i << "]: " << vec[i] << '\n';
}
return 0;
}
Output:
vec.size(): 0
Oops!
The update of used is missing in insert() as well:
++used;
And, now it looks better:
vec.size(): 3
vec[0]: 3
vec[1]: 2
vec[2]: 1
The complete MCVE:
#include <iostream>
template <class T>
class Vector {
public:
typedef T* iterator;
Vector () { }
T& operator[](unsigned int i) {
return items[i];
}
// T& operator[](iterator i) {
//return items[*i];
//}
iterator begin () {
return &items[0];
}
iterator end () {
return &items[used];
}
int size () { return used; }
iterator insert (iterator position, const T& item) {
for(Vector<T>::iterator i=&items[998]; i>=position; i--)
{
*(i+1) = *i;
}
*position = item;
++used;
return position;
}
private:
T items[1000];
int used=0;
};
int main()
{
Vector<double> vec;
vec.insert(vec.begin(), 1.0);
vec.insert(vec.begin(), 2.0);
vec.insert(vec.begin(), 3.0);
std::cout << "vec.size(): " << vec.size() << '\n';
for (int i = 0; i < vec.size(); ++i) {
std::cout << "vec[" << i << "]: " << vec[i] << '\n';
}
return 0;
}
Live Demo on coliru
So you can think of an iterator in this context as essentially a glorified pointer to the elements in the array, as you defined in your typedef at the beginning of your class.
When you're trying to access the elements in your array in your insert function, you are essentially dereferencing these pointers to yield the elements themselves and THEN using those elements as indices for your array, hence producing the error that the index is of the wrong type.
So for example suppose you had a Vector<std::string>. Inside the for loop in the insert function, you have this line:
items[*(i+1)]=items[*i];
Because i is an iterator as you defined, i has the type std::string * and hence *i has the type std::string. When you then write items[*i] you are trying to use the std::string as an index for your array which you can't do.
Instead, you should use a line similar to the following:
*(i + 1) = *i
There are also a couple of logical errors in your code, but I'll leave you to find those later on.
Hope this helps!
Have a look at how std::move_backward can be implemented
template< class BidirIt1, class BidirIt2 >
BidirIt2 move_backward(BidirIt1 first, BidirIt1 last, BidirIt2 d_last)
{
while (first != last) {
*(--d_last) = std::move(*(--last));
}
return d_last;
}
You don't need to move any of the elements past end, and we can rewrite your insert to be similar
iterator insert (iterator position, const T& item) {
for(iterator i = end(), d = end() + 1; i != position; )
{
*(--d) = std::move(*(--i));
}
*position = item;
++used;
return position;
}
Note that this is undefined if you try to insert into a full Vector
I've just started to code in C++, so i'm new to STL .
Here i'm trying to iterate over a graph stored as vector of vectors.
#include <iostream>
#include <vector>
#include <iostream>
using namespace std;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for (it = adj.begin(); it != adj.end(); it++)
{
cout << (*it) << endl;
if ((*it) == x)
for (i = (*it).begin(); i != (*it).end(); i++)
{
cout << (*i) << endl;
if ((*i) == y)
return 1;
}
}
return 0;
}
int main()
{
}
I'm getting an error std::vector<int> is not derived from const gnu cxx. Can someone point me in the right direction ?
*it pointing to vector not int that is why you are getting error
following code may work for you
#include <vector>
#include <iostream>
using namespace std;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for (it = adj.begin(); it != adj.end(); it++)
{
cout << (*(*it).begin()) << endl;
if (( (*(*it).begin())) == x)
for (i = (*it).begin(); i != (*it).end(); i++)
{
cout << (*i) << endl;
if ((*i) == y)
return 1;
}
}
return 0;
}
int main()
{
}
for accessing first element of the vector of the use
(*(*it).begin()) in place of (*it)
if you are studying graph then use array of vector. for more details please go through following url
C++ Depth First Search (DFS) Implementation
cout << (*it) << endl;
Here, you declared it as a:
vector<vector<int> >::iterator it;
Therefore, *it is a:
vector<int>
So you are attempting to use operator<< to send it to std::cout. This, obviously, will not work. This is equivalent to:
vector<int> v;
cout << v;
There is no operator<< overload that's defined for what cout is, and a vector<int>. As you know, in order to print the contents of a vector, you have to iterate over its individual values, and print its individual values.
So, whatever your intentions were, when you wrote:
cout << (*it) << endl;
you will need to do something else, keeping in mind that *it here is an entire vector<int>. Perhaps your intent is to iterate over the vector and print each int in the vector, but you're already doing it later.
Similarly:
if ((*it) == x)
This won't work either. As explained, *it is a vector<int>, which cannot be compared to a plain int.
It is not clear what your intentions are here. "Graph stored as a vector or vectors" is too vague.
The following code compiles with the option std=c++11. But x is missing in vector<vector<int>>. If adj had type vector<pair<int, vector<int>>> it would better match.
The following code compiles for vector<vector<int>> but it doesn't use x.
using std::vector;
using std::pair;
using std::cout;
using std::endl;
int reach(vector<vector<int> > &adj, int x, int y) {
vector<vector<int> >::iterator it;
vector<int>::iterator i;
for(it=adj.begin();it!=adj.end();it++)
{
// cout << (*it) << endl;
for (const auto& nexts: *it)
cout << nexts << ' ';
cout << endl;
for(i=(*it).begin();i!=(*it).end();i++)
{
cout << (*i) << endl;
if((*i)==y)
return 1;
}
}
return 0;
}
This code compiles with <vector<pair<int, vector<int>>> and uses x.
using std::vector;
using std::pair;
using std::cout;
using std::endl;
int reach(vector<pair<int, vector<int> > > &adj, int x, int y) {
vector<pair<int, vector<int> > >::iterator it;
vector<int>::iterator i;
for(it=adj.begin();it!=adj.end();it++)
{
cout << it->first << endl;
if (it->first == x)
for(i=it->second.begin();i!=it->second.end();i++)
{
cout << (*i) << endl;
if((*i)==y)
return 1;
}
}
return 0;
}
Wrap it up in an iterator.
This can be templated for reuse.
Here is a minimal working example for the std::vector<T> container:
#include <iostream>
#include <utility>
#include <vector>
/// Iterable vector of vectors
/// (This just provides `begin` and `end for `Vector2Iterable<T>::Iterator`).
template<typename T>
class VovIterable
{
public:
static const std::vector<T> EMPTY_VECTOR;
/// Actual iterator
class Iterator
{
typename std::vector<std::vector<T>>::const_iterator _a1;
typename std::vector<T>::const_iterator _a2;
typename std::vector<std::vector<T>>::const_iterator _end;
public:
/// \param a1 Outer iterator
/// \param a2 Inner iterator
/// \param end End of outer iterator
explicit Iterator(typename std::vector<std::vector<T>>::const_iterator a1, typename std::vector<T>::const_iterator a2, typename std::vector<std::vector<T>>::const_iterator end)
: _a1(a1)
, _a2(a2)
, _end(end)
{
Check();
}
bool operator!=(const Iterator &b) const
{
return _a1 != b._a1 || _a2 != b._a2;
}
Iterator &operator++()
{
++_a2; // Increment secondary
Check();
return *this;
}
const T &operator*() const
{
return *_a2;
}
private:
void Check()
{
while (true)
{
if (_a2 != _a1->end()) // Is secondary live?
{
break;
}
// Increment primary
_a1++;
if (_a1 == _end) // Is primary dead?
{
_a2 = EMPTY_VECTOR.end();
break;
}
_a2 = _a1->begin(); // Reset secondary
}
}
};
private:
std::vector<std::vector<T>> _source;
public:
explicit VovIterable(std::vector<std::vector<T>> source)
: _source(std::move(source))
{
}
/// Start of vector of vectors
[[nodiscard]] Iterator begin() const
{
if (this->_source.empty())
{
return end();
}
return Iterator(this->_source.cbegin(), this->_source.cbegin()->cbegin(), this->_source.cend());
}
/// End of vector of vectors
[[nodiscard]] Iterator end() const
{
return Iterator(this->_source.cend(), EMPTY_VECTOR.end(), this->_source.cend());
}
};
template<typename T>
const std::vector<T> VovIterable<T>::EMPTY_VECTOR = {0};
/// Sample usage
int main()
{
std::vector<std::vector<int>> myVov{{1, 2, 3},
{4, 5, 6},
{7, 8, 9}};
for (int i: VovIterable(myVov))
{
std::cout << i << std::endl;
}
return 0;
}
Heya I'm trying to implement selection sort algorithm on a singly linked list , I'm aware that there is some problem in the code but although My linked list includes the numbers 7 1 2 6 the output after running is 7777 . Any help would be appreciated.
template<class Type>
void UnOrderedLinkedList<Type>::selectionSort()
{
nodeType<Type>* loc;
nodeType<Type>* minIndex;
nodeType<Type>* temp;
temp = first;
if(temp == NULL)
cerr<<"Cannot sort an empty list."<<endl;
else
if(temp->link == NULL)
cerr<<"List has only one item so it is already sorted."<<endl;
else
while(temp != NULL)
{
minIndex = minLocation(temp, last);
swap(temp, minIndex);
temp = temp->link;
}
}
template<class Type>
nodeType<Type>* UnOrderedLinkedList<Type>::minLocation(nodeType<Type>* first, nodeType<Type>* last)
nodeType<Type>* minIndex;
nodeType<Type>* other;
minIndex = first;
other = minIndex->link;
while(other != NULL)
{
if(minIndex->info > other->info)
{
minIndex = other;
other = other->link;
}
else
{
other = other->link;
}
}
return minIndex;
}
Then to swap:
template<class Type>
void UnOrderedLinkedList<Type>::swap(nodeType<Type>* first, nodeType<Type>* second)
{
nodeType<Type>* temp;
temp->info = first->info;
first->info = second->info;
second->info = temp->info;
}
From your swap function:
nodeType<Type>* temp;
temp->info = first->info;
That is a clear case of undefined behavior! You declare a local variable, a pointer, without initialization. Then you directly uses the uninitialized variable, leading to said UB. Since you use pointers, you should actually be happy that the program didn't crash.
Here you don't need a pointer or a node as you don't actually swap nodes. All you need is an instance of what info is, and use that:
SomeType temp;
temp = first->info;
first->info = second->info;
second->info = temp;
The answer by #JoachimPileborg works of course, but note that you don't need to write a member function sort of your own singly linked list in order to do selection sort.
The reason is that a generic version of selection_sort (with O(N^2) complexity) is already compatible any singly linked list that exposes forward iterators, such as the one from the Standard Library, std::forward_list:
#include <algorithm> // min_element, iter_swap, is_sorted
#include <cassert> // assert
#include <forward_list> // forward_list
#include <functional> // less
#include <iostream> // cout
#include <ios> // boolalpha
#include <iterator> // distance, next
template<class FwdIt, class Compare = std::less<>>
void selection_sort(FwdIt first, FwdIt last, Compare cmp = Compare{})
{
for (auto it = first; it != last; ++it) {
auto const selection = std::min_element(it, last, cmp);
std::iter_swap(selection, it);
assert(std::is_sorted(first, std::next(it), cmp));
}
}
int main()
{
auto fl = std::forward_list<int> { 2, 4, 1, 0, -1, 8, 2 };
std::cout << std::boolalpha << std::is_sorted(fl.begin(), fl.end()) << '\n';
for (auto const& e : fl) std::cout << e << ", "; std::cout << '\n';
selection_sort(fl.begin(), fl.end());
std::cout << std::boolalpha << std::is_sorted(fl.begin(), fl.end()) << '\n';
for (auto const& e : fl) std::cout << e << ", "; std::cout << '\n';
}
Live Example
Note that std::forward_list also implements its own member function sort. This version -which does an O(N log N) merge sort- can not be implemented based on the public interface alone (actually you can, but with O(N) extra storage instead of the O(1) storage that forward_list guarantees).
I've a vector of vectors say vector<vector<int> > items of different sizes like as follows
1,2,3
4,5
6,7,8
I want to create combinations in terms of Cartesian product of these vectors like
1,4,6
1,4,7
1,4,8
and so on till
3,5,8
How can I do that ? I've looked up several links and I've also listed them at the end of this post but I'm not able to interpret that as I'm not that familiar with the language. Could some body help me with this.
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int main()
{
vector<vector<int> > items;
int k = 0;
for ( int i = 0; i < 5; i++ ) {
items.push_back ( vector<int>() );
for ( int j = 0; j < 5; j++ )
items[i].push_back ( k++ );
}
cartesian ( items ); // I want some function here to do this.
}
This program has equal length vectors and I put this so that it will be easier to understand my data structure. It will be very helpful even if somebody uses others answers from other links and integrate with this to get the result. Thank you very much
Couple of links I looked at
one
Two
Program from : program
First, I'll show you a recursive version.
// Cartesion product of vector of vectors
#include <vector>
#include <iostream>
#include <iterator>
// Types to hold vector-of-ints (Vi) and vector-of-vector-of-ints (Vvi)
typedef std::vector<int> Vi;
typedef std::vector<Vi> Vvi;
// Just for the sample -- populate the intput data set
Vvi build_input() {
Vvi vvi;
for(int i = 0; i < 3; i++) {
Vi vi;
for(int j = 0; j < 3; j++) {
vi.push_back(i*10+j);
}
vvi.push_back(vi);
}
return vvi;
}
// just for the sample -- print the data sets
std::ostream&
operator<<(std::ostream& os, const Vi& vi)
{
os << "(";
std::copy(vi.begin(), vi.end(), std::ostream_iterator<int>(os, ", "));
os << ")";
return os;
}
std::ostream&
operator<<(std::ostream& os, const Vvi& vvi)
{
os << "(\n";
for(Vvi::const_iterator it = vvi.begin();
it != vvi.end();
it++) {
os << " " << *it << "\n";
}
os << ")";
return os;
}
// recursive algorithm to to produce cart. prod.
// At any given moment, "me" points to some Vi in the middle of the
// input data set.
// for int i in *me:
// add i to current result
// recurse on next "me"
//
void cart_product(
Vvi& rvvi, // final result
Vi& rvi, // current result
Vvi::const_iterator me, // current input
Vvi::const_iterator end) // final input
{
if(me == end) {
// terminal condition of the recursion. We no longer have
// any input vectors to manipulate. Add the current result (rvi)
// to the total set of results (rvvvi).
rvvi.push_back(rvi);
return;
}
// need an easy name for my vector-of-ints
const Vi& mevi = *me;
for(Vi::const_iterator it = mevi.begin();
it != mevi.end();
it++) {
// final rvi will look like "a, b, c, ME, d, e, f"
// At the moment, rvi already has "a, b, c"
rvi.push_back(*it); // add ME
cart_product(rvvi, rvi, me+1, end); add "d, e, f"
rvi.pop_back(); // clean ME off for next round
}
}
// sample only, to drive the cart_product routine.
int main() {
Vvi input(build_input());
std::cout << input << "\n";
Vvi output;
Vi outputTemp;
cart_product(output, outputTemp, input.begin(), input.end());
std::cout << output << "\n";
}
Now, I'll show you the recursive iterative version that I shamelessly stole from #John :
The rest of the program is pretty much the same, only showing the cart_product function.
// Seems like you'd want a vector of iterators
// which iterate over your individual vector<int>s.
struct Digits {
Vi::const_iterator begin;
Vi::const_iterator end;
Vi::const_iterator me;
};
typedef std::vector<Digits> Vd;
void cart_product(
Vvi& out, // final result
Vvi& in) // final result
{
Vd vd;
// Start all of the iterators at the beginning.
for(Vvi::const_iterator it = in.begin();
it != in.end();
++it) {
Digits d = {(*it).begin(), (*it).end(), (*it).begin()};
vd.push_back(d);
}
while(1) {
// Construct your first product vector by pulling
// out the element of each vector via the iterator.
Vi result;
for(Vd::const_iterator it = vd.begin();
it != vd.end();
it++) {
result.push_back(*(it->me));
}
out.push_back(result);
// Increment the rightmost one, and repeat.
// When you reach the end, reset that one to the beginning and
// increment the next-to-last one. You can get the "next-to-last"
// iterator by pulling it out of the neighboring element in your
// vector of iterators.
for(Vd::iterator it = vd.begin(); ; ) {
// okay, I started at the left instead. sue me
++(it->me);
if(it->me == it->end) {
if(it+1 == vd.end()) {
// I'm the last digit, and I'm about to roll
return;
} else {
// cascade
it->me = it->begin;
++it;
}
} else {
// normal
break;
}
}
}
}
Here is a solution in C++11.
The indexing of the variable-sized arrays can be done eloquently with modular arithmetic.
The total number of lines in the output is the product of the sizes of the input vectors. That is:
N = v[0].size() * v[1].size() * v[2].size()
Therefore the main loop has n as the iteration variable, from 0 to N-1. In principle, each value of n encodes enough information to extract each of the indices of v for that iteration. This is done in a subloop using repeated modular arithmetic:
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
void cartesian( vector<vector<int> >& v ) {
auto product = []( long long a, vector<int>& b ) { return a*b.size(); };
const long long N = accumulate( v.begin(), v.end(), 1LL, product );
vector<int> u(v.size());
for( long long n=0 ; n<N ; ++n ) {
lldiv_t q { n, 0 };
for( long long i=v.size()-1 ; 0<=i ; --i ) {
q = div( q.quot, v[i].size() );
u[i] = v[i][q.rem];
}
// Do what you want here with u.
for( int x : u ) cout << x << ' ';
cout << '\n';
}
}
int main() {
vector<vector<int> > v { { 1, 2, 3 },
{ 4, 5 },
{ 6, 7, 8 } };
cartesian(v);
return 0;
}
Output:
1 4 6
1 4 7
1 4 8
...
3 5 8
Shorter code:
vector<vector<int>> cart_product (const vector<vector<int>>& v) {
vector<vector<int>> s = {{}};
for (const auto& u : v) {
vector<vector<int>> r;
for (const auto& x : s) {
for (const auto y : u) {
r.push_back(x);
r.back().push_back(y);
}
}
s = move(r);
}
return s;
}
Seems like you'd want a vector of iterators which iterate over your individual vector<int>s.
Start all of the iterators at the beginning. Construct your first product vector by pulling out the element of each vector via the iterator.
Increment the rightmost one, and repeat.
When you reach the end, reset that one to the beginning and increment the next-to-last one. You can get the "next-to-last" iterator by pulling it out of the neighboring element in your vector of iterators.
Continue cycling through until both the last and next-to-last iterators are at the end. Then, reset them both, increment the third-from-last iterator. In general, this can be cascaded.
It's like an odometer, but with each different digit being in a different base.
Here's my solution. Also iterative, but a little shorter than the above...
void xp(const vector<vector<int>*>& vecs, vector<vector<int>*> *result) {
vector<vector<int>*>* rslts;
for (int ii = 0; ii < vecs.size(); ++ii) {
const vector<int>& vec = *vecs[ii];
if (ii == 0) {
// vecs=[[1,2],...] ==> rslts=[[1],[2]]
rslts = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) {
vector<int>* v = new vector<int>;
v->push_back(vec[jj]);
rslts->push_back(v);
}
} else {
// vecs=[[1,2],[3,4],...] ==> rslts=[[1,3],[1,4],[2,3],[2,4]]
vector<vector<int>*>* tmp = new vector<vector<int>*>;
for (int jj = 0; jj < vec.size(); ++jj) { // vec[jj]=3 (first iter jj=0)
for (vector<vector<int>*>::const_iterator it = rslts->begin();
it != rslts->end(); ++it) {
vector<int>* v = new vector<int>(**it); // v=[1]
v->push_back(vec[jj]); // v=[1,3]
tmp->push_back(v); // tmp=[[1,3]]
}
}
for (int kk = 0; kk < rslts->size(); ++kk) {
delete (*rslts)[kk];
}
delete rslts;
rslts = tmp;
}
}
result->insert(result->end(), rslts->begin(), rslts->end());
delete rslts;
}
I derived it with some pain from a haskell version I wrote:
xp :: [[a]] -> [[a]]
xp [] = []
xp [l] = map (:[]) l
xp (h:t) = foldr (\x acc -> foldr (\l acc -> (x:l):acc) acc (xp t)) [] h
Since I needed the same functionality, I implemented an iterator which computes the Cartesian product on the fly, as needed, and iterates over it.
It can be used as follows.
#include <forward_list>
#include <iostream>
#include <vector>
#include "cartesian.hpp"
int main()
{
// Works with a vector of vectors
std::vector<std::vector<int>> test{{1,2,3}, {4,5,6}, {8,9}};
CartesianProduct<decltype(test)> cp(test);
for(auto const& val: cp) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
// Also works with something much less, like a forward_list of forward_lists
std::forward_list<std::forward_list<std::string>> foo{{"boo", "far", "zab"}, {"zoo", "moo"}, {"yohoo", "bohoo", "whoot", "noo"}};
CartesianProduct<decltype(foo)> bar(foo);
for(auto const& val: bar) {
std::cout << val.at(0) << ", " << val.at(1) << ", " << val.at(2) << "\n";
}
}
The file cartesian.hpp looks like this.
#include <cassert>
#include <limits>
#include <stdexcept>
#include <vector>
#include <boost/iterator/iterator_facade.hpp>
//! Class iterating over the Cartesian product of a forward iterable container of forward iterable containers
template<typename T>
class CartesianProductIterator : public boost::iterator_facade<CartesianProductIterator<T>, std::vector<typename T::value_type::value_type> const, boost::forward_traversal_tag>
{
public:
//! Delete default constructor
CartesianProductIterator() = delete;
//! Constructor setting the underlying iterator and position
/*!
* \param[in] structure The underlying structure
* \param[in] pos The position the iterator should be initialized to. std::numeric_limits<std::size_t>::max()stands for the end, the position after the last element.
*/
explicit CartesianProductIterator(T const& structure, std::size_t pos);
private:
//! Give types more descriptive names
// \{
typedef T OuterContainer;
typedef typename T::value_type Container;
typedef typename T::value_type::value_type Content;
// \}
//! Grant access to boost::iterator_facade
friend class boost::iterator_core_access;
//! Increment iterator
void increment();
//! Check for equality
bool equal(CartesianProductIterator<T> const& other) const;
//! Dereference iterator
std::vector<Content> const& dereference() const;
//! The part we are iterating over
OuterContainer const& structure_;
//! The position in the Cartesian product
/*!
* For each element of structure_, give the position in it.
* The empty vector represents the end position.
* Note that this vector has a size equal to structure->size(), or is empty.
*/
std::vector<typename Container::const_iterator> position_;
//! The position just indexed by an integer
std::size_t absolutePosition_ = 0;
//! The begin iterators, saved for convenience and performance
std::vector<typename Container::const_iterator> cbegins_;
//! The end iterators, saved for convenience and performance
std::vector<typename Container::const_iterator> cends_;
//! Used for returning references
/*!
* We initialize with one empty element, so that we only need to add more elements in increment().
*/
mutable std::vector<std::vector<Content>> result_{std::vector<Content>()};
//! The size of the instance of OuterContainer
std::size_t size_ = 0;
};
template<typename T>
CartesianProductIterator<T>::CartesianProductIterator(OuterContainer const& structure, std::size_t pos) : structure_(structure)
{
for(auto & entry: structure_) {
cbegins_.push_back(entry.cbegin());
cends_.push_back(entry.cend());
++size_;
}
if(pos == std::numeric_limits<std::size_t>::max() || size_ == 0) {
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
// Initialize with all cbegin() position
position_.reserve(size_);
for(std::size_t i = 0; i != size_; ++i) {
position_.push_back(cbegins_[i]);
if(cbegins_[i] == cends_[i]) {
// Empty member, so Cartesian product is empty
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
}
// Increment to wanted position
for(std::size_t i = 0; i < pos; ++i) {
increment();
}
}
template<typename T>
void CartesianProductIterator<T>::increment()
{
if(absolutePosition_ == std::numeric_limits<std::size_t>::max()) {
return;
}
std::size_t pos = size_ - 1;
// Descend as far as necessary
while(++(position_[pos]) == cends_[pos] && pos != 0) {
--pos;
}
if(position_[pos] == cends_[pos]) {
assert(pos == 0);
absolutePosition_ = std::numeric_limits<std::size_t>::max();
return;
}
// Set all to begin behind pos
for(++pos; pos != size_; ++pos) {
position_[pos] = cbegins_[pos];
}
++absolutePosition_;
result_.emplace_back();
}
template<typename T>
std::vector<typename T::value_type::value_type> const& CartesianProductIterator<T>::dereference() const
{
if(absolutePosition_ == std::numeric_limits<std::size_t>::max()) {
throw new std::out_of_range("Out of bound dereference in CartesianProductIterator\n");
}
auto & result = result_[absolutePosition_];
if(result.empty()) {
result.reserve(size_);
for(auto & iterator: position_) {
result.push_back(*iterator);
}
}
return result;
}
template<typename T>
bool CartesianProductIterator<T>::equal(CartesianProductIterator<T> const& other) const
{
return absolutePosition_ == other.absolutePosition_ && structure_ == other.structure_;
}
//! Class that turns a forward iterable container of forward iterable containers into a forward iterable container which iterates over the Cartesian product of the forward iterable containers
template<typename T>
class CartesianProduct
{
public:
//! Constructor from type T
explicit CartesianProduct(T const& t) : t_(t) {}
//! Iterator to beginning of Cartesian product
CartesianProductIterator<T> begin() const { return CartesianProductIterator<T>(t_, 0); }
//! Iterator behind the last element of the Cartesian product
CartesianProductIterator<T> end() const { return CartesianProductIterator<T>(t_, std::numeric_limits<std::size_t>::max()); }
private:
T const& t_;
};
If someone has comments how to make it faster or better, I'd highly appreciate them.
I was just forced to implement this for a project I was working on and I came up with the code below. It can be stuck in a header and it's use is very simple but it returns all of the combinations you can get from a vector of vectors. The array that it returns only holds integers. This was a conscious decision because I just wanted the indices. In this way, I could index into each of the vector's vector and then perform the calculations I/anyone would need... best to avoid letting CartesianProduct hold "stuff" itself, it is a mathematical concept based around counting not a data structure. I'm fairly new to c++ but this was tested in a decryption algorithm pretty thoroughly. There is some light recursion but overall this is a simple implementation of a simple counting concept.
// Use of the CartesianProduct class is as follows. Give it the number
// of rows and the sizes of each of the rows. It will output all of the
// permutations of these numbers in their respective rows.
// 1. call cp.permutation() // need to check all 0s.
// 2. while cp.HasNext() // it knows the exit condition form its inputs.
// 3. cp.Increment() // Make the next permutation
// 4. cp.permutation() // get the next permutation
class CartesianProduct{
public:
CartesianProduct(int num_rows, vector<int> sizes_of_rows){
permutation_ = new int[num_rows];
num_rows_ = num_rows;
ZeroOutPermutation();
sizes_of_rows_ = sizes_of_rows;
num_max_permutations_ = 1;
for (int i = 0; i < num_rows; ++i){
num_max_permutations_ *= sizes_of_rows_[i];
}
}
~CartesianProduct(){
delete permutation_;
}
bool HasNext(){
if(num_permutations_processed_ != num_max_permutations_) {
return true;
} else {
return false;
}
}
void Increment(){
int row_to_increment = 0;
++num_permutations_processed_;
IncrementAndTest(row_to_increment);
}
int* permutation(){
return permutation_;
}
int num_permutations_processed(){
return num_permutations_processed_;
}
void PrintPermutation(){
cout << "( ";
for (int i = 0; i < num_rows_; ++i){
cout << permutation_[i] << ", ";
}
cout << " )" << endl;
}
private:
int num_permutations_processed_;
int *permutation_;
int num_rows_;
int num_max_permutations_;
vector<int> sizes_of_rows_;
// Because CartesianProduct is called first initially with it's values
// of 0 and because those values are valid and important output
// of the CartesianProduct we increment the number of permutations
// processed here when we populate the permutation_ array with 0s.
void ZeroOutPermutation(){
for (int i = 0; i < num_rows_; ++i){
permutation_[i] = 0;
}
num_permutations_processed_ = 1;
}
void IncrementAndTest(int row_to_increment){
permutation_[row_to_increment] += 1;
int max_index_of_row = sizes_of_rows_[row_to_increment] - 1;
if (permutation_[row_to_increment] > max_index_of_row){
permutation_[row_to_increment] = 0;
IncrementAndTest(row_to_increment + 1);
}
}
};
#include <iostream>
#include <vector>
void cartesian (std::vector<std::vector<int>> const& items) {
auto n = items.size();
auto next = [&](std::vector<int> & x) {
for ( int i = 0; i < n; ++ i )
if ( ++x[i] == items[i].size() ) x[i] = 0;
else return true;
return false;
};
auto print = [&](std::vector<int> const& x) {
for ( int i = 0; i < n; ++ i )
std::cout << items[i][x[i]] << ",";
std::cout << "\b \n";
};
std::vector<int> x(n);
do print(x); while (next(x)); // Shazam!
}
int main () {
std::vector<std::vector<int>>
items { { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8 } };
cartesian(items);
return 0;
}
The idea behind this is as follows.
Let n := items.size().
Let m_i := items[i].size(), for all i in {0,1,...,n-1}.
Let M := {0,1,...,m_0-1} x {0,1,...,m_1-1} x ... x {0,1,...,m_{n-1}-1}.
We first solve the simpler problem of iterating through M. This is accomplished by the next lambda. The algorithm is simply the "carrying" routine grade schoolers use to add 1, albeit with a mixed radix number system.
We use this to solve the more general problem by transforming a tuple x in M to one of the desired tuples via the formula items[i][x[i]] for all i in {0,1,...,n-1}. We perform this transformation in the print lambda.
We then perform the iteration with do print(x); while (next(x));.
Now some comments on complexity, under the assumption that m_i > 1 for all i:
This algorithm requires O(n) space. Note that explicit construction of the Cartesian product takes O(m_0 m_1 m_2 ... m_{n-1}) >= O(2^n) space. So this is exponentially better on space than any algorithm which requires all tuples to be stored simultaneously in memory.
The next function takes amortized O(1) time (by a geometric series argument).
The print function takes O(n) time.
Hence, altogether, the algorithm has time complexity O(n|M|) and space complexity O(n) (not counting the cost of storing items).
An interesting thing to note is that if print is replaced with a function which inspects on average only O(1) coordinates per tuple rather than all of them, then time complexity falls to O(|M|), that is, it becomes linear time with respect to the size of the Cartesian product. In other words, avoiding the copy of the tuple each iterate can be meaningful in some situations.
This version supports no iterators or ranges, but it is a simple direct implementation that uses the multiplication operator to represent the Cartesian product, and a lambda to perform the action.
The interface is designed with the particular functionality I needed. I needed the flexibility to choose vectors over which to apply the Cartesian product in a way that did not obscure the code.
int main()
{
vector< vector<long> > v{ { 1, 2, 3 }, { 4, 5 }, { 6, 7, 8 } };
(Cartesian<long>(v[0]) * v[1] * v[2]).ForEach(
[](long p_Depth, long *p_LongList)
{
std::cout << p_LongList[0] << " " << p_LongList[1] << " " << p_LongList[2] << std::endl;
}
);
}
The implementation uses recursion up the class structure to implement the embedded for loops over each vector. The algorithm works directly on the input vectors, requiring no large temporary arrays. It is simple to understand and debug.
The use of std::function p_Action instead of void p_Action(long p_Depth, T *p_ParamList) for the lambda parameter would allow me to capture local variables, if I wanted to. In the above call, I don't.
But you knew that, didn't you. "function" is a template class which takes the type parameter of a function and makes it callable.
#include <vector>
#include <iostream>
#include <functional>
#include <string>
using namespace std;
template <class T>
class Cartesian
{
private:
vector<T> &m_Vector;
Cartesian<T> *m_Cartesian;
public:
Cartesian(vector<T> &p_Vector, Cartesian<T> *p_Cartesian=NULL)
: m_Vector(p_Vector), m_Cartesian(p_Cartesian)
{};
virtual ~Cartesian() {};
Cartesian<T> *Clone()
{
return new Cartesian<T>(m_Vector, m_Cartesian ? m_Cartesian->Clone() : NULL);
};
Cartesian<T> &operator *=(vector<T> &p_Vector)
{
if (m_Cartesian)
(*m_Cartesian) *= p_Vector;
else
m_Cartesian = new Cartesian(p_Vector);
return *this;
};
Cartesian<T> operator *(vector<T> &p_Vector)
{
return (*Clone()) *= p_Vector;
};
long Depth()
{
return m_Cartesian ? 1 + m_Cartesian->Depth() : 1;
};
void ForEach(function<void (long p_Depth, T *p_ParamList)> p_Action)
{
Loop(0, new T[Depth()], p_Action);
};
private:
void Loop(long p_Depth, T *p_ParamList, function<void (long p_Depth, T *p_ParamList)> p_Action)
{
for (T &element : m_Vector)
{
p_ParamList[p_Depth] = element;
if (m_Cartesian)
m_Cartesian->Loop(p_Depth + 1, p_ParamList, p_Action);
else
p_Action(Depth(), p_ParamList);
}
};
};
The problem lies within the block:
check_sort(l.begin(), l.end(), "list");
time_insert(insert_list, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_set, data);
check_sort(v.begin(), v.end(), "vector");
time_insert(insert_vector, data);
The error states that the variables are not declared in the scope, but shouldn't l,s,v be universal variables here? What am I doing wrong.
#include <cmath>
#include <iterator>
#include <iostream>
#include <iomanip>
#include <vector>
#include <ctime>
#include <list>
#include <set>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef void Inserter(vector<double>);
vector<double> gen_data(int num_elts);
void insert_list(vector<double> data);
void insert_set(vector<double> data);
void insert_vector(vector<double> data);
void time_insert( Inserter inserter, vector<double> data);
template <class Iter> bool is_sorted(Iter first, Iter last);
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind);
int main() {
srand(time(0));// initialize random number generator
cout << "How many elements for container? ";
int num_elts = 0;
while (cin >> num_elts) {
if (num_elts <= 0)
cout << "Error, should be > 1";
else {
vector<double> data = gen_data(num_elts);
check_sort(l.begin(), l.end(), "list");
time_insert(insert_list, data);
check_sort(s.begin(), s.end(), "set");
time_insert(insert_set, data);
check_sort(v.begin(), v.end(), "vector");
time_insert(insert_vector, data);
}
cout << "\nHow many elements for next container? ";
}
return 0;
}
void time_insert( Inserter inserter, vector<double> data) {
clock_t t1 = clock();
if (t1 == clock_t(-1)) { //if clock() doesn’t work
cerr << "sorry, no clock\n";
exit(1);
}
inserter(data);
clock_t t2 = clock();
if (t2 == clock_t(-1)) {
cerr << "sorry, clock overflow\n";
exit(2);
}
cout << "Elapsed time: " << fixed << setprecision(2)
<< double(t2-t1)/CLOCKS_PER_SEC << " seconds\n";
}
class Larger_than {
double v;
public:
Larger_than(double vv) : v(vv){}
bool operator()(double x) const {return x>v;}
};
// Sorts and then inserts data into a list
void insert_list(vector<double> data)
{
list<double> l;
for(int i=0; i < data.size(); i++){
list<double>::iterator p = find_if(l.begin(),l.end(), Larger_than(data[i]));
l.insert(p, data[i]);
}
}
// Sorts and then inserts data into a list
void insert_set(vector<double> data)
{
set<double> s;
for(int i=0; i < data.size(); i++){
set<double>::iterator p = find_if(s.begin(),s.end(), Larger_than(data[i]
));
s.insert(p, data[i]);
}
}
// Sorts and then inserts data into a list
void insert_vector(vector<double> data)
{
vector<double> v;
for(int i=0; i < data.size(); i++){
vector<double>::iterator p = find_if(v.begin(),v.end(), Larger_than(data
[i]));
v.insert(p, data[i]);
}
}
// generate num_elts random numbers in the range [0.0, 1.0),
// which are returned in a vector
vector<double> gen_data (int num_elts)
{
vector<double> result;
for (int i = 0; i < num_elts; i++) {
double datum = 1.0*rand()/RAND_MAX;
result.push_back(datum);
}
return result;
}
// is container spanned by [from, last) sorted?
template <class Iter> bool is_sorted(Iter first, Iter last)
{
Iter next = first; // next element
for (next++; next != last; next++, first++) {
if (*first > *next)
return false;
}
return true;
}
// prints a msg describing container kind, as well as whether container
// spanned by [from, last) is sorted
template <class Iter> void check_sort(Iter first, Iter last, string cont_kind)
{
cout << "Check: " << cont_kind << " is ";
if (!is_sorted(first, last)) cout << "not ";
cout << "sorted\n";
}
How should main know about s, l and v at all? They're local variables of completely unrelated functions (the insert_xxx ones), there's no way main could know about them. If you want to make them globally accessible, just make them global variables, i.e., put their definition before main:
// ...
list<double> l;
set<double> s;
vector<double> v;
int main(){
// ....
}
// ...
It looks like l is defined in the 'insert_list' function and would not available in main. Only variables defined insider your function are available.
You don't appear to have declared the variables at all. Why do you think they should exist in main? There are no globals or locals with those names anywhere that I can see. Try declaring them before using them.