Graph with std::vectors? - c++

I thought that a cool way of using vectors could be to have one vector class template hold an two separate int variables for x/y-coordinates to graph.
example:
std::vector<int, int> *name*;
// First int. being the x-intercept on a graph
// Second int. being the y-intercept on a graph
(I also understand that I could just make every even/odd location or two separate vectors to classify each x/y-coordinate, but for me I would just like to see if this could work)
However, after making this vector type, I came across an issue with assigning which int within the vector will be written to or extracted from. Could anyone tell me how to best select and std::cout both x/y ints appropriately?
P.S. - My main goal, in using vectors this way, is to make a very basic graph output to Visual Studio terminal. While being able to change individual x/y-intercepts by 'selecting' and changing if needed. These coordinates will be outputted to the terminal via for/while loops.
Also, would anyone like to list out different ways to best make x/y-coordinates with different containers?

Your question rather broad, in other words it is asking for a bit too much. I will just try to give you some pointers from which you can work your way to what you like.
A) equidistant x
If your x values are equidistant, ie 0, 0.5, 1, 1.5 then there is no need to store them, simply use a
std::vector<int> y;
if the number of variables is not known at compile time, otherwise a
std::array<int,N> y;
B) arbitrary x
There are several options that depend on what you actually want to do. For simply storing (x,y)-pairs and printing them on the screen, they all work equally well.
map
std::map<int,int> map_x_to_y = { { 1,1}, {2,4}, {3,9}};
// print on screen
for (const auto& xy : map_x_to_y) {
std::cout << xy.first << ":" xy.second;
}
a vector of pairs
std::vector<std::pair<int,int>> vector_x_and_y = { { 1,1}, {2,4}, {3,9}};
Printing on screen is actually the same as with map. The advantage of the map is that it has its elements ordered, while this is not the case for the vector.
C) not using any container
For leightweight calculations you can consider to not store the (xy) pairs at all, but simply use a function:
int fun(int x) { return x*x; }
TL;DR / more focussed
A vector stores one type. You cannot have a std::vector<int,int>. If you look at the documentation of std::vector you will find that the second template parameter is an allocator (something you probably dont have to care about for some time). If you want to store two values as one element in a vector you either have to use std::vector<std::pair<double,double>> or a different container.
PS
I used std::pair in the examples above. However, I do consider it as good practice to name things whenever I can and leave std::pair for cases when I simply cannot give names better than first and second. In this spirit you can replace std::pair in the above examples with a
struct data_point {
int x;
int y;
};

Related

Copying vector elements to a vector pair

In my C++ code,
vector <string> strVector = GetStringVector();
vector <int> intVector = GetIntVector();
So I combined these two vectors into a single one,
void combineVectors(vector<string>& strVector, vector <int>& intVector, vector < pair <string, int>>& pairVector)
{
for (int i = 0; i < strVector.size() || i < intVector.size(); ++i )
{
pairVector.push_back(pair<string, int> (strVector.at(i), intVector.at(i)));
}
}
Now this function is called like this,
vector <string> strVector = GetStringVector();
vector <int> intVector = GetIntVector();
vector < pair <string, int>> pairVector
combineVectors(strVector, intVector, pairVector);
//rest of the implementation
The combineVectors function uses a loop to add the elements of other 2 vectors to the vector pair. I doubt this is a efficient way as this function gets called hundrands of times passing different data. This might cause a performance issue because everytime it goes through the loop.
My goal is to copy both the vectors in "one go" to the vector pair. i.e., without using a loop. Am not sure whether that's even possible.
Is there a better way of achieving this without compromising the performance?
You have clarified that the arrays will always be of equal size. That's a prerequisite condition.
So, your situation is as follows. You have vector A over here, and vector B over there. You have no guarantees whether the actual memory that vector A uses and the actual memory that vector B uses are next to each other. They could be anywhere.
Now you're combining the two vectors into a third vector, C. Again, no guarantees where vector C's memory is.
So, you have really very little to work with, in terms of optimizations. You have no additional guarantees whatsoever. This is pretty much fundamental: you have two chunks of bytes, and those two chunks need to be copied somewhere else. That's it. That's what has to be done, that's what it all comes down to, and there is no other way to get it done, other than doing exactly that.
But there is one thing that can be done to make things a little bit faster. A vector will typically allocate memory for its values in incremental steps, reserving some extra space, initially, and as values get added to the vector, one by one, and eventually reach the vector's reserved size, the vector has to now grab a new larger block of memory, copy everything in the vector to the larger memory block, then delete the older block, and only then add the next value to the vector. Then the cycle begins again.
But you know, in advance, how many values you are about to add to the vector, so you simply instruct the vector to reserve() enough size in advance, so it doesn't have to repeatedly grow itself, as you add values to it. Before your existing for loop, simply:
pairVector.reserve(pairVector.size()+strVector.size());
Now, the for loop will proceed and insert new values into pairVector which is guaranteed to have enough space.
A couple of other things are possible. Since you have stated that both vectors will always have the same size, you only need to check the size of one of them:
for (int i = 0; i < strVector.size(); ++i )
Next step: at() performs bounds checking. This loop ensures that i will never be out of bounds, so at()'s bound checking is also some overhead you can get rid of safely:
pairVector.push_back(pair<string, int> (strVector[i], intVector[i]));
Next: with a modern C++ compiler, the compiler should be able to optimize away, automatically, several redundant temporaries, and temporary copies here. It's possible you may need to help the compiler, a little bit, and use emplace_back() instead of push_back() (assuming C++11, or later):
pairVector.emplace_back(strVector[i], intVector[i]);
Going back to the loop condition, strVector.size() gets evaluated on each iteration of the loop. It's very likely that a modern C++ compiler will optimize it away, but just in case you can also help your compiler check the vector's size() only once:
int i=strVector.size();
for (int i = 0; i < n; ++i )
This is really a stretch, but it might eke out a few extra quantums of execution time. And that pretty much all obvious optimizations here. Realistically, the most to be gained here is by using reserve(). The other optimizations might help things a little bit more, but it all boils down to moving a certain number of bytes from one area in memory to another area. There aren't really special ways of doing that, that's faster than other ways.
We can use std:generate() to achieve this:
#include <bits/stdc++.h>
using namespace std;
vector <string> strVector{ "hello", "world" };
vector <int> intVector{ 2, 3 };
pair<string, int> f()
{
static int i = -1;
++i;
return make_pair(strVector[i], intVector[i]);
}
int main() {
int min_Size = min(strVector.size(), intVector.size());
vector< pair<string,int> > pairVector(min_Size);
generate(pairVector.begin(), pairVector.end(), f);
for( int i = 0 ; i < 2 ; i++ )
cout << pairVector[i].first <<" " << pairVector[i].second << endl;
}
I'll try and summarize what you want with some possible answers depending on your situation. You say you want a new vector that is essentially a zipped version of two other vectors which contain two heterogeneous types. Where you can access the two types as some sort of pair?
If you want to make this more efficient, you need to think about what you are using the new vector for? I can see three scenarios with what you are doing.
The new vector is a copy of your data so you can do stuff with it without affecting the original vectors. (ei you still need the original two vectors)
The new vector is now the storage mechanism for your data. (ei you
no longer need the original two vectors)
You are simply coupling the vectors together to make use and representation easier. (ei where they are stored doesn't actually matter)
1) Not much you can do aside from copying the data into your new vector. Explained more in Sam Varshavchik's answer.
3) You do something like Shakil's answer or here or some type of customized iterator.
2) Here you make some optimisations here where you do zero coping of the data with the use of a wrapper class. Note: A wrapper class works if you don't need to use the actual std::vector < std::pair > class. You can make a class where you move the data into it and create access operators for it. If you can do this, it also allows you to decompose the wrapper back into the original two vectors without copying. Something like this might suffice.
class StringIntContainer {
public:
StringIntContaint(std::vector<std::string>& _string_vec, std::vector<int>& _int_vec)
: string_vec_(std::move(_string_vec)), int_vec_(std::move(_int_vec))
{
assert(string_vec_.size() == int_vec_.size());
}
std::pair<std::string, int> operator[] (std::size_t _i) const
{
return std::make_pair(string_vec_[_i], int_vec_[_i]);
}
/* You may want methods that return reference to data so you can edit it*/
std::pair<std::vector<std::string>, std::vector<int>> Decompose()
{
return std::make_pair(std::move(string_vec_), std::move(int_vec_[_i])));
}
private:
std::vector<std::string> _string_vec_;
std::vector<int> int_vec_;
};

The knights tour. Chosing a container

I have been reading up on C++ lately, especially STL, and I decided to do the Knights Tour problem again. I'm thinking about the best way to implement this, and I'm looking for some help.
Just for fun and practice, I thought I'd start with a "Piece" base class, which a "Knight" class can inherit from. I want to do this so I later can try adding other pieces(even though most of the pieces can't walk over the whole board and complete the problem).
So the "piece class" will need some sort of container to store the coordinates of the piece on the board and the number of moves it has made in that specific step.
I'm thinking I need a linked list with 64 (8 * 8) places to do this most efficiently, containing x,y and moves.
Looking at the STL containers, I can't find anything except map that will hold more than one type.
What can I do to store the coordinate pair and an int for the number of moves in one container? Are there more efficient ways of doing this than using vector, list or map? Do I need a custom container?
Thanks!
You can use
struct CellInfo
{
int x, y, move_count;
}
And store it in std::vector for constant access.
Apart from STL and encapsulation, a very efficient way is to use arrays:
pair<int, int> piece_pos[N];
int piece_move[N];
This avoids the overhead of memory leakage and is faster than dynamic allocation.
If you stell want to use STL, then:
vector<pair<int, int> > piece_pos(N);
vector<int> piece(N);
The C++ STL now has static arrays as well. If you want to store the number of times a given x,y coordinate has been moved to, you can create an array of arrays like the following:
using container_type = std::array<std::array<int, 8>, 8>;
// ...
container_type c;
int moves = c[x][y]; // constant-time access.
If you don't need to look moves up based on x,y, and just want the data stored efficiently, use a flat array of size 8x8 = 64.
If your compiler is out of date, consider using std::vector instead.

Is it possible to use boost accumulators with vectors?

I wanted to use boost accumulators to calculate statistics of a variable that is a vector. Is there a simple way to do this. I think it's not possible to use the dumbest thing:
using namespace boost::accumulators;
//stuff...
accumulator_set<vector<double>, stats<tag::mean> > acc;
vector<double> some_vetor;
//stuff
some_vector = doStuff();
acc(some_vector);
maybe this is obvious, but I tried anyway. :P
What I wanted was to have an accumulator that would calculate a vector which is the mean of the components of many vectors. Is there an easy way out?
EDIT:
I don't know if I was thoroughly clear. I don't want this:
for_each(vec.begin(), vec.end(),acc);
This would calculate the mean of the entries of a given vector. What I need is different. I have a function that will spit vectors:
vector<double> doSomething();
// this is a monte carlo simulation;
And I need to run this many times and calculate the vectorial mean of those vectors:
for(int i = 0; i < numberOfMCSteps; i++){
vec = doSomething();
acc(vec);
}
cout << mean(acc);
And I want mean(acc) to be a vector itself, whose entry [i] would be the means of the entries [i] of the accumulated vectors.
Theres a hint about this in the docs of Boost, but nothing explicit. And I'm a bit dumb. :P
I've looked into your question a bit, and it seems to me that Boost.Accumulators already provides support for std::vector. Here is what I could find in a section of the user's guide :
Another example where the Numeric
Operators Sub-Library is useful is
when a type does not define the
operator overloads required to use it
for some statistical calculations.
For instance, std::vector<> does not overload any arithmetic operators, yet
it may be useful to use std::vector<>
as a sample or variate type. The
Numeric Operators Sub-Library defines
the necessary operator overloads in
the boost::numeric::operators
namespace, which is brought into scope
by the Accumulators Framework with a
using directive.
Indeed, after verification, the file boost/accumulators/numeric/functional/vector.hpp does contain the necessary operators for the 'naive' solution to work.
I believe you should try :
Including either
boost/accumulators/numeric/functional/vector.hpp before any other accumulators header
boost/accumulators/numeric/functional.hpp while defining BOOST_NUMERIC_FUNCTIONAL_STD_VECTOR_SUPPORT
Bringing the operators into scope with a using namespace boost::numeric::operators;.
There's only one last detail left : execution will break at runtime because the initial accumulated value is default-constructed, and an assertion will occur when trying to add a vector of size n to an empty vector. For this, it seems you should initialize the accumulator with (where n is the number of elements in your vector) :
accumulator_set<std::vector<double>, stats<tag::mean> > acc(std::vector<double>(n));
I tried the following code, mean gives me a std::vector of size 2 :
int main()
{
accumulator_set<std::vector<double>, stats<tag::mean> > acc(std::vector<double>(2));
const std::vector<double> v1 = boost::assign::list_of(1.)(2.);
const std::vector<double> v2 = boost::assign::list_of(2.)(3.);
const std::vector<double> v3 = boost::assign::list_of(3.)(4.);
acc(v1);
acc(v2);
acc(v3);
const std::vector<double> &meanVector = mean(acc);
}
I believe this is what you wanted ?
I don't have it set up to try right now, but if all boost::accumulators need is properly defined mathematical operators, then you might be able to get away with a different vector type: http://www.boost.org/doc/libs/1_37_0/libs/numeric/ublas/doc/vector.htm
And what about the documentation?
// The data for which we wish to calculate statistical properties:
std::vector< double > data( /* stuff */ );
// The accumulator set which will calculate the properties for us:
accumulator_set< double, features< tag::min, tag::mean > > acc;
// Use std::for_each to accumulate the statistical properties:
acc = std::for_each( data.begin(), data.end(), acc );

Sort a vector on a value calculated on each element, without performing the calculation multiple times per element

can anyone recommend a nice and tidy way to achieve this:
float CalculateGoodness(const Thing& thing);
void SortThings(std::vector<Thing>& things)
{
// sort 'things' on value returned from CalculateGoodness, without calling CalculateGoodness more than 'things.size()' times
}
Clearly I could use std::sort with a comparison function that calls CalculateGoodness, but then that will get called several times per Thing as it is compared to other elements, which is no good if CalculateGoodness is expensive. I could create another std::vector just to store the ratings and std::sort that, and rearrange things in the same way, but I can't see a tidy way of doing that. Any ideas?
Edit: Apologies, I should have said without modifying Thing, else it's a fairly easy problem to solve :)
I can think of a simple transformation (well two) to get what you want. You could use std::transform with suitable predicates.
std::vector<Thing> to std::vector< std::pair<Result,Thing> >
sort the second vector (works because a pair is sorted by it first member)
reverse transformation
Tadaam :)
EDIT: Minimizing the number of copies
std::vector<Thing> to std::vector< std::pair<Result,Thing*> >
sort the second vector
transform back into a secondary vector (local)
swap the original and local vectors
This way you would only copy each Thing once. Notably remember that sort perform copies so it could be worth using.
And because I am feeling grant:
typedef std::pair<float, Thing*> cached_type;
typedef std::vector<cached_type> cached_vector;
struct Compute: std::unary_function< Thing, cached_type >
{
cached_type operator()(Thing& t) const
{
return cached_type(CalculateGoodness(t), &t);
}
};
struct Back: std::unary_function< cached_type, Thing >
{
Thing operator()(cached_type t) const { return *t.second; }
};
void SortThings(std::vector<Thing>& things)
{
// Reserve to only allocate once
cached_vector cache; cache.reserve(things.size());
// Compute Goodness once and for all
std::transform(things.begin(), things.end(),
std::back_inserter(cache), Compute());
// Sort
std::sort(cache.begin(), cache.end());
// We have references inside `things` so we can't modify it
// while dereferencing...
std::vector<Thing> local; local.reserve(things.size());
// Back transformation
std::transform(cache.begin(), cache.end(),
std::back_inserter(local), Back());
// Put result in `things`
swap(things, local);
}
Provided with the usual caveat emptor: off the top of my head, may kill kittens...
You can have a call to CalculateGoodness that you call for each element before sorting, and then CalculateGoodness simply updates an internal member variable. Then you can sort based on that member variable.
Another possibility if you can't modify your type, is storing some kind of std::map for your objects and their previously calculated values. Your sort function would use that map which acts as a cache.
I've upvoted Brian's answer because it clearly best answers what you're looking for. But another solution you should consider is just write it the easy way. Processors are getting more powerful every day. Make it correct and move on. You can profile it later to see if CalculateGoodness really is the bottleneck.
I'd create pairs of ratings and things, calling CalculateGoodness once per thing, and sort that on the rating. if applicable you could also move this to a map from rating to thing
the other option would be to cache CalculateGoodness in the Thing itself either as a simple field or by making CalculateGoodness a method of Thing (making sure the cache is mutable so const Things still works)
Perhaps a tidy way of doing the separate vector thing is to actually create a vector< pair<float, Thing*> >, where the second element points to the Thing object with the corresponding float value. If you sort this vector by the float values, you can iterate over it and read the Thing objects in the correct order, possibly playing them into another vector or list so they end up stored in order.

Type or Vector for representing points\positions

I have a series of points\positions that won't change. Should I represent as Vector of ints or as a new type?
My preference at the moment is to go with vector:
doSomething(myVec[0], myVec[1] );
doSomethingElse(myVec[2], myVec[3] );
as opposed to:
doSomething( myType.getPos1(), myType.getPos2() );
doSomethingElse( myType.getPos3(), myType.getPos4() );
Any thoughts or ideas?
Thanks
Its difficult to say with the given information. But with whatever information provided so far, I would prefer to write a struct Point with x and y co-ordinates and create a vector of the points. This will give you the benefits of storing the objects in a standard container plus it will logically bind the data in a common structure so that you don't have to vec[0],vec[1] every time when you want a point. As a side note, if you are writing the class with getPos method I would certainly write getPos(int index) rather than getPos1, getPos2 etc.
Why not create an actual vector struct/class?
By vector I mean a mathematical vector. Typically vectors are used for points and positions. A bonus of this is that your code will be much more readable.
This is how games, graphics and other applications do it. Using a list for related data is not OO, and one of the reasons OOP exists.
The IMHO optimal solution would be:
struct Point {
int x, y;
};
[... somewhere else ...]
vector<Point> points();
(My C++ is rusty, might not be correct syntax)
Since you're using stl, I'd use vector< pair<int,int> > (or vector< pair<double,double> > if the points aren't integer). It works great for points.
So then you could do something like this:
vector< pair<int,int> > points;
points.push_back(make_pair(1,2));
points.push_back(make_pair(2,2));
If you need to iterate over them then the answer is obvious.
If they don't change and you can manage the complexity then the first option is fine. The second might be more readable (if you choose good names).
You can also write a class that contains or holds a reference to the vector. In that case you can have the benefits of both.
You could also use the Boost.tuple library.
#include <boost/tuple/tuple.hpp>
boost::tuple<int,int,int,int> position;
and access them as:
position.get<N>(); // where N is in 1,2,3,4