reverse vector container

I'm making a 2D board game and to desing the board layout and record tokens, I
use a vector of vectors, which gives me the following, unatural, board layout:


    (0,0) (0,1) (0,2) (0,3)
    (1,0) (1,1) (1,2) (1,3)
    (2,0) (2,1) (2,2) (2,3)
    (3,0) (3,1) (3,2) (3,3)


The layout I would like to have is the following:


    (3,0) (3,1) (3,2) (3,3)
    (2,0) (2,1) (2,2) (2,3)
    (1,0) (1,1) (1,2) (1,3)
    (0,0) (0,1) (0,2) (0,3)
     ^
     |
     |
    Rows in reverse order...


which seems more natural to me in terms of use and readability.

In other words, I would like a vector whose behaviour is "reversed". For example,
I would like to be able to do:

1
2
3
4
    reverse_vector a {1, 2, 3, 4};
    
    cout << a[0];   // prints 4
    cout << a[3];   // prints 1 


and "begin" and "end" for iterators are reversed also.

I though about overloading the containing "row" vecor operator[] to give me the
wanted result, but then realized that there were a lot of other methods and
stuff to be overloaded in order to do this, which is starting to make me beleive
there should be a simpler way.

I try googling, but found nothing so far. Do you know of any?
Should I write one from scratch?

Thanks!
You're right, but if I write (assuming I have the above layout):

 
cout << myvect[0][0];


I would still get the unwanted (3,0) interpretation.
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
#include<iostream>
#include<vector>
#include<tuple>

using namespace std;
int main(){

    cout<<"Enter #rows: \n";
    int row{};
    cin>>row;
    cout<<"Enter #cols: \n";
    int col{};
    cin>>col;

    vector<vector<tuple<int,int>>>board(col);
    for(int i = 0;  i <  row; i++)
    {
        for(int j = 0; j < col; j++)
        {
          board[j].emplace_back(make_tuple(col - j - 1, i));
        }
    }

    for(int j = 0; j < col; j++)
    {
        for (auto& itr :board[j])
        {
            cout<<"("<<get<0>(itr)<<", "<<get<1>(itr)<<") \t";
        }
        cout<<"\n";
    }
}
Are you only concerned about displaying the whole board?

If you use reverse_iterator, you never have to use indices. Just reverse_iterate through the rows, and then iterate through the columns. Then print out *iter.

Are you only concerned about displaying the whole board?


No, there are also some validations to be done on the board. Some of which require looping. I had a hard time writing some of these validation algorithms since the board layout was so unnatural.

I think everything I want could be done with the reverse iterator, but I was looking for a "more elegant" like a reverse_vector class or something like that where a user could have the choice of using iterators or indices and not always have to remember to use reverse iterators to, conceptually, go forward.

I did some more research and I'm starting to think I might have to program such a class from scratch...
@BobMorane - can you give me some feedback in what ways my program might not be quite what you are looking for and then I'll play around a bit more and see what I can come up with? I thought that if we could get the numbers into the container in the 'right' order the rest of it might follow more smoothly but maybe I am missing something. Thanks
Last edited on
@gunnerfunner

Your program has the same problem as mine:

 
cout << "(" << get<0>(board[0][0]) << "," << get<1>(board[0][0]) << ")";


outputs as:


Enter #rows: 
2
Enter #cols: 
2
(1, 0) 	(1, 1) 	
(0, 0) 	(0, 1) 	
(1,0) 


What I am looking for is that the position [0][0] outputs as (0,0). In other words, as in a standard coordinate system, with the origin in the down left corner.

Does this help?

Thanks for your time.

I think my explanation of the issue might not be clear enough. The situation:


                        |---------| <-- Row vector (upside down)
 Row 0 (should be 3) -->||0|1|2|3|<-- Column vectors (they are fine)
                        |---------|
 Row 1                  ||0|1|2|3||
                        |---------|
 Row 2                  ||0|1|2|3||
                        |---------|
 Row 3 (should be 0) -->||0|1|2|3||
                        |---------|


(0,0) gets top left, not natural (think of a coordinate system). What I want:


         |---------| <-- Row vector (Natural order, good!)
 Row 3   ||0|1|2|3|<-- Column vectors (they are fine)
         |---------|
 Row 2   ||0|1|2|3||
         |---------|
 Row 1   ||0|1|2|3||
         |---------|
 Row 0   ||0|1|2|3||
         |---------|


(0,0) gets bottom left, natural. Just like (0,0) here:


3 |<-- not (0,0)
2 |
1 |
0 |_ _ _ _ 
   0 1 2 3 
   ^
   |
 (0,0)


Is this clearer?
Vectors are indexed as conventionally as matrices. Anyways, I think I understand what you want, but I don't understand why you want it.

You can manipulate your vector in what feels like the natural way, but change only how you print it. It will make sense if you do it this way. If you flip both printing and access (which is relatively difficult, by the way), you'll still feel like you're doing things backwards, in the same sense that negating a number twice doesn't change the number.
You can manipulate your vector in what feels like the natural way [...]


You mean, with the reverse iterator?
No -- I mean ignoring the way it's going to look when you print it out. Just pretend that index (0, 0) appears in the bottom corner. Manipulate the vector as if this is true.

As long as your internal representation is consistent, it doesn't matter what the vector looks like when you print it out in forward, row-major order. How you choose to print the vector contents has nothing to do with the meaning of the data in the collection.

If you want to pretend that (0, 0) is the bottom left corner instead of the top left corner, do it, and changing nothing else about the vector, print it like this.

1
2
3
4
5
6
std::cout << "Printing rows backwards:" << "\n";
  for (auto i = board.rbegin(); i != board.rend(); ++i) {
    for (auto j = i->begin(); j != i->end(); ++j)
      std::cout << *j << " ";
    std::cout << "\n";
  }


Understand? This is strangely hard to explain.
Last edited on
I guess what mbozzi means is that there is usually a difference between internal and external representation of the data.

External representation is the screen or a file. Which is usually different regarding output and don't forget the input.

What you actually want to do is that the internal is the same as external (-> screen) representation. This is not a good idea because the external representation may change while the internal shouldn't.

In other words it is a good idea to separate the data fom its view.

which gives me the following, unatural, board layout
But for vector this is natural. For the view you can (as shown) change that order.
@mbozzi, and @coder777: I understand perfectly your point. I was actually a bit worried that my internal reprensentation of the data for someone reading my code in the future, by not being the same as my representation, could leed to some trouble in understanding what is actually going on. This is especially the case for validations on the grid, where a lot of comparing from point to point has to be done through nested loops. For example, if you have a validation method that validate something vertically. Internally, which is up, which is down? Should I refrain of using such words in my internal data management (I'm starting to think so...)?

Thanks!
Last edited on
In the data, there is no up or down. It's only when it is displayed on the screen that up and down means anything.

There is nothing wrong with considering increasing rows as "up". The only reason you are hung up with it is that when you print it out with a simple iterator, each subsequent row is printed below the previous. That's a problem with the way you are trying to display the data, not the data itself.

When you realize that you can print out the data any way you want to (in this case with a reverse_iterator for the rows), then your data can be oriented any way you want it to. So, yes! row[1] is ABOVE row[0]. No problem.
Last edited on
@doug4 Ok, I understand. Thanks!
Topic archived. No new replies allowed.