Can we make an array containing pairs? - c++

I am new to stl and i came across a question where it is required to store a lot of pairs having same characteristics (like:- (string,int)) together. Can we store pairs in array and if so how? Thanks in advance..

You can try something like:
struct demo
{
string str;
int i;
};
std::array<demo, 5> arr; //for fixed size array of 5 elements
std::vector<demo> vec; //for dynamic size arrays

You want ...
to store a lot of pairs having same characteristics
The terminology is a bit wrong. You want to store many pairs of the same type (not "characteristics").
You could define your own struct as answered by Nipun, or use
std::array<std::pair<std::string,int>, 10> arr;
for an array of 10 pairs of strings and ints.
Spend more time on reading a documentation on standard containers and standard utilities. Perhaps you want some other existing thing (e.g. std::set with std::tuple, maybe with your own comparator).
Templates can (and often should) be combined since they are compositional. Be also aware of the rule of five.

Related

Dynamic initialization of 2 dimensional array of lists in C++

I need to init a 2-dim array of forward_list after I read its sizes from input.
class Foo{
forward_list<int> * koo;
int A, B;
void boo(){
scanf("%d",&A);
scanf("%d",&B);
koo = new forward_list<int>[A][B];
koo[0][0] = 1;
}
};
Compiler:
cannot convert ‘std::forward_list<int> (*)[1]’ to ‘std::forward_list<int>*’ in assignment adjList = new forward_list<int>[A][A];
CLion IDE: Subscribed value is not an array (at koo[0])
I don't do much C++ so I don't quite know what's wrong. How can I do this right? I need to access all forward_list in O(1), and would, therefore, prefer arrays or generally something fast.
Btw: not sure if this is called dynamic initialization, let me know if I should change the title.
Thanks.
A forward_list is incapable of reaching your performance requirement: "I need to access all forward_list in O(1)" you can see that in a comparision here: https://en.wikipedia.org/wiki/Linked_list#Linked_lists_vs._dynamic_arrays You can see that Indexing for a forward_list and other linked list variants is O(n).
The simplest container type that does provide the O(1) indexing you're looking for is a vector or another of the dynamic array variants. I believe your current needs could be satisfied by doing something like:
vector<vector<int>> koo(A, vector<int>(B));
It should be mentioned that while this will satisfy your performance requirements, a vector of vectors isn't a great solution; but you can look at it as a good stopgap solution.

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.

How to make a variable name without creating an array in C++?

How do you make a variable name where you create a variable and then in brackets the variable number? (By the way, I'm just guessing out how the code should be so that you get what I'm trying to say.) For example:
int var[5];
//create a variable var[5], but not var[4], var[3], var[2], etc.
Then, the variable number must be able to be accessed by a variable value:
int number = 5;
int var[number]; //creates a var[5], not a var[4], etc.
int var[2]; //creates a var[2], not a var[1], etc.
cout >>var[number];
number = 2;
cin << var[number];
If I'm way off track with my "example", please suggest something else. I need something similar to this for my game to operate, because I must be able to create an unlimited instance of bullets, but they will also be destroyed at one point.
It looks like you are looking for the functionality provided by std::map which is a container used to map keys to values.
Documentation of std::map
Example use
In the below example we bind the value 123 to the integer key 4, and the value 321 to key 8. We then use a std::map<int,int>::const_iterator to iterate over the key/value pairs in our std::map named m.
#include <map>
...
std::map<int, int> m;
m[4] = 123;
m[8] = 321;
for (std::map<int, int>::const_iterator cit = m.begin (); cit != m.end (); ++cit)
std::cout << cit->first << " -> " << cit->second << std::endl;
output:
4 -> 123
8 -> 321
It looks like you want variable length arrays, which is not something C++ supports. In most cases, the correct solution is to use an std::vector instead, as in
int number = 42; // or whatever
std::vector<int> var(number);
You can use std::vector as you would use an array in most cases, and you gain a lot of bonus functionality.
If I understand what you want correctly (which I'm not certain that I do), you want to be able to create a place to hold objects and use them according to some index number, but to only create the specific objects which go in it on demand. You want do to this either because 1) you don't know how many objects you're going to create or 2) you aren't going to use every index number or 3) both.
If (1) then you should probably just use a vector, which is an array-like structure which grows automatically as you add more things to it. Look up std::vector.
If (2) then you could use an array of pointers and initially set all of the values to null and then use new to create the objects as needed. (Or you could use the solution recommend in part 3.)
If (3) then you want to use some form of map or hash table. These structures will let you find things by number even when not all numbers are in use and will grow as needed. I would highly recommend a hash table, but in C++, there isn't one in the STL, so you have to build your own or find one in a third-party library. For ease, you can use std::map, which is part of the STL. It does basically the same thing, but is slower. Some C++ distributions also include std::hash_map. If it's available, that should be used instead because it will be faster than std::map.

C++ - Multidimensional Arrays

When dealing with multidimensional arrays, is it possible to assign two different variable types to the array...
For example you have the array int example[i][j] is it possible for i and j to be two completely different variable types such as int and string?
Sounds like you're looking for:
std::vector<std::map<std::string, int> > myData1;
or perhaps:
std::map<int, std::map<std::string, int> > myData2;
The first would require you to resize the vector to an appropriate size before using the indexing operators:
myData1.resize(100);
myData1[25]["hello"] = 7;
...while the second would allow you to assign to any element directly (and sparsely):
myData2[25]["hello"] = 7;
No. That's not possible. You may want to look into using the STL map.
No, C++ only allows integer types (ex: int, long, unsigned int, size_t, char) as indexes.
If you want to index by a string, you could try std::map<std::string,mytype> but it gets complicated trying to extend that to two dimensions.
No, but you could use std::maps.
No, you can only use integer types as indices.
No you can't. You could achieve this with std::map though.

std::vector is very slow?

Here is what I'm doing.
I have a class which I instance and it has a std::vector.
when I first instance the class this std::vector is empty.
The way I use it is I exponentially add to it and clear. Ex:
Add a number, clear the vector:
Add 2 numbers, clear the vector:
Add 3 numbers, clear the vector,
Add 4 numbers, clear the vector.
......
Is a std::vector the bst way to do what I'm doing?
I tried to do reserve(100,000) in the constructor but this did not help.
Is there maybe a better container for my usage?
Thanks
Your algorithm appears to be quadratic. If you really need 100,000 elements, you're adding an element 1 + 2 + 3 + ... + 100,000 times. That's about 5,000,000,000 operations. That many operations, no matter how trivial they are, will take a while on a standard pc, regardless of whether you're using std::vector or hand-crafted assembly language.
Something like:
struct A {
std::vector <int> v;
A() : v(100000) {}
};
is probably what you want. When you say:
A a;
This creates an instance the struct A (works for classes too) containing a vector of the required size.