ordering a map

Aug 19, 2008 at 6:55pm
If I have 2 maps like ..
1
2
map <int, int> X;
map <int, int> Y;

.. and they holds coordinates for drawing something, like a house. The data looks like ..
1
2
3
4
5
6
7
8
X[0] = 15;
X[1] = 19;
X[2] = 32;
X[3] = 2;
Y[0] = 42;
Y[1] = 73;
Y[2] = 22;
Y[3] = 4;


I loop through them and draw lines from each to form a shape.

How is the best way to flip the shape vertically or horizontally ?

I am sure it's a simple algorithim, but I am drawing a blank.
Aug 19, 2008 at 7:19pm
First, you need the boundaries of the screen. Let's say it's xtotal=640 and ytotal=480.

For a horizontal mirror (<-- becomes -->) do x[i]=xtotal-x[i].
For a vertical mirror (v becomes ^) do y[i]=ytotal-y[i].
Doing both horizontal and vertical mirrors at the same time is the same as rotating 180°.

And don't use a map for that. Use a vector. Maps are used for different purposes (e.g. storing variables defined at run-time).
Aug 19, 2008 at 7:36pm
Thanks for the reply Helios.

I knew it was something simple like that.

Also, the data is read from a text file and the values are set at run time. I'm not sure why a map shouldn't be used in this case.
Aug 19, 2008 at 7:42pm
You *could* use a map, but if you access a variable that does not exist, then the map will create it for you...which could be a problem...you could either make two vectors:

1
2
vector <int> xcoord;
vector <int> ycoord;


Or use one vector:

 
vector < vector <int> > coords; //<-- Last spaces are IMPORTANT!! 


And access it like this:

coords.at(x).at(y) == 1;

Maps are used more for stuff like this (I think):

1
2
3
4
5
6
7
map <string, MyClass> MyClasses;
//add classes to MyClasses
if(MyClasses.find("MyClassName") != MyClasses.end()) {
    cout<<MyClasses["MyClassName"].somedata;
} else {
    cout<<"Class does not exist."<<endl;
}


So that you don't have to iterate through a very large vector until you find the right "name" or whatever you looking for.
Last edited on Aug 19, 2008 at 7:47pm
Aug 19, 2008 at 7:51pm
If you make it multi-dimensional vector like that, is there a way to have seperate iterators ?
Aug 19, 2008 at 8:00pm
I'm not sure why a map shouldn't be used in this case.

The simple answer: prefer a std::vector whenever it suffices, and a std::list when you have many insertion/deletions "in the middle".
In this case, I would use a std::vector<std::pair<int, int> >

The somewhat more complicated answer: you have to access each element, one after another. If you use map::operator[], each call costs you O(log n) if n elements are being stored in the map, so doing it n times results in a total cost of O(n*log n). If you use a vector instead, the same thing can be done in O(n). You could use map's iterator, which provides a O(1) operator++, but still you have overhead due to the underlaying representation (in my STL implementation (g++/HP), that is a Red-Black-Tree).

If you make it multi-dimensional vector like that, is there a way to have seperate iterators ?

Yes, of course. The value type of the first iterator is then a std::vector<int>, which provides it's own iterator.
Last edited on Aug 19, 2008 at 8:00pm
Aug 19, 2008 at 8:05pm
Ahh, thanks for the explanation guys.

I will switch it to a vector and read up on the differences.
Aug 19, 2008 at 8:06pm
firedraco is correct. That's what I meant by variables defined at run-time. Another name for maps is dictionary, because you look up a value assigned to a key, which is the exact behavior of variables.

However, that is not the way to face this problem. You're supposed to use a structure:
1
2
3
4
struct 2D_point{
	int x;
	int y;
};

And declare it like this: std::vector<2D_point> points

EDIT: Or you can use what exception posted there. I prefer the simpler solution, but you use the one you like the best.
Last edited on Aug 19, 2008 at 8:08pm
Aug 19, 2008 at 8:07pm
Not really, no. The ycoord iterator would always be dependant on the xcoord iterator.

You can use integer indices to the same effect:
1
2
3
for (unsigned col = 0; col < coords.at(0).at(0).size(); col++)
for (unsigned row = 0; row < coords.at(0).size(); row++)
  cout << coords[row][col] << endl;

This, of course, assumes that all the rows have the same number of columns.
Topic archived. No new replies allowed.