If things are decided at runtime then you might want std::arrays
as your key-value pairs.
There are many ways to index multidimensional arrays with a single for-loop. Going from a multidimensional array to a one-dimensional array is easy. If i
, j
, k
are your indices, then you'll store this at position index=k*N*N+j*N+i;
in your multidimensional array (where in your case, N=2*SIZE
. If you meant to type for (int i =-SIZE; i<=SIZE; i++)
, then you'd have N=2*SIZE+1
). So if you have an n-dimensional array and index[k] is an array of indices, you can pack this into a one-dimesional index with the following algorithm:
//dynamically allocated array of size depth
std::vector<int> index(depth,0);
// ... populate some interesting index here, where 0<=index[i]<N
//for depth=3, this would calculate 0*N*N*N+index[2]*N*N+index[1]*N+index[0].
int one_dimensional_index=0;
for(int i=depth-1; i>=0; i--) {
one_dimensional_index*=N;
one_dimensional_index+=index[i];
}
std::cout<<"Multidimensional index is stored at one-dimensional index: "<<one_dimensional_index<<std::endl;
But if I understand correctly, you want to do the inverse problem. This can be done by using integer division and modular arithmetic. (index[2]*N*N+index[1]*N+index[0])%N
is just index[0]
, and (index[2]*N*N+index[1]*N+index[0])/N
is just index[2]*N+index[1]
, so by doing division and modulo operations you can get the indices back. In the end, you'd have an implementation that looks something like this:
std::vector<int> indexFromMulti(int one_dimensional_index,int nn, int depth){
std::vector<int> index(depth,0);
for(int i=0; i<depth; i++) {
index[i]=(one_dimensional_index%N);
one_dimensional_index/=N;
}
return index;
}
Here is a full implementation that prints the following for size=1, depth=4, and breadth=4.
user@desktop:~$ g++ test.cpp
user@desktop:~$ ./a.out
qtable populated with:
qtable[{-1, -1, -1, -1}]=[4, 2, 3, 1];
qtable[{-1, -1, -1, 0}]=[3, 4, 5, 3];
qtable[{-1, -1, 0, -1}]=[1, 2, 3, 2];
(...)
qtable[{0, 0, -1, 0}]=[5, 3, 4, 5];
qtable[{0, 0, 0, -1}]=[3, 1, 5, 3];
qtable[{0, 0, 0, 0}]=[1, 1, 5, 3];
Source code:
#include <iostream>
#include <vector>
#include <map>
std::vector<int> indexFromMulti(int one_dimensional_index,int nn, int depth){
std::vector<int> index(depth,0);
for(int i=0; i<depth; i++) {
index[i]=(one_dimensional_index%nn);
one_dimensional_index/=nn;
}
return index;
}
//integer power from https://stackoverflow.com/a/1505791/13783653
int int_pow(int x, int p)
{
if (p == 0) return 1;
if (p == 1) return x;
int tmp = int_pow(x, p/2);
if (p%2 == 0) return tmp * tmp;
else return x * tmp * tmp;
}
//Function to print with pretty formatting
void print_qtable(std::map<std::vector<int>, std::vector<int>> qtable){
std::cout<<"qtable populated with: "<<std::endl;
for(auto iter = qtable.begin(); iter != qtable.end(); ++iter) {
std::cout<<"qtable[{";
for(size_t i=0;i<iter->first.size();i++){
std::cout<<iter->first[i];
if(i!=iter->first.size()-1)
std::cout<<", ";
}
std::cout<<"}]=[";
for(size_t i=0;i<iter->second.size();i++){
std::cout<<iter->second[i];
if(i!=iter->second.size()-1)
std::cout<<", ";
}
std::cout<<"];"<<std::endl;
}
}
std::map<std::vector<int>, std::vector<int>> qtable(int size, int depth, int breadth){
int nn=2*size;
int max_index=int_pow(nn,depth);
std::map<std::vector<int>, std::vector<int>> q_table;
for (int i=0;i<max_index;i++){
std::vector<int> key=indexFromMulti(i,nn,depth);
//change the interval [0,nn) to the interval [-size,size).
for(int j=0;j<depth;j++)
key[j]-=size;
//Fill in the value
std::vector<int> value(breadth,0);
for(int j=0;j<breadth;j++)
value[j] = (rand() % 5)+1;
q_table[key]=value;
}
return q_table;
}
int main() {
print_qtable(qtable(1,4,4));
return 0;
}