Как заставить работать разное количество циклов for в соответствии с вводом пользователя в C ++ - PullRequest
0 голосов
/ 21 июня 2020

Я пытаюсь создать структуру данных таблицы на C ++. В настоящее время я написал следующий код:



map<array<int, 3>, array<int, 6>> q_table;

void qtable(){
    for (int i =-SIZE; i<SIZE; i++){ //SIZE is a constant say 10
        for (int j =-SIZE; j<SIZE; j++){
            for (int k =-SIZE; k<SIZE; k++){
                
                q_table[{i,j,k}][0] = (rand() % 5)+1; //Initializing with random numbers
                q_table[{i,j,k}][1] =  (rand() % 5)+1;
                q_table[{i,j,k}][2] =  (rand() % 5)+1;
                q_table[{i,j,k}][3] =  (rand() % 5)+1;
                q_table[{i,j,k}][4] =  (rand() % 5)+1;
                q_table[{i,j,k}][5] =  (rand() % 5)+1; 
//Here I am creating a map such which looks like :
// q_table[{0,0,0}][0] = -0.1;
// q_table[{0,0,0}][1] = 0.2;
// q_table[{0,0,0}][2] = -0.3;
// q_table[{0,0,0}][3] = -3.2;
// q_table[{0,0,0}][4] = -1.2;
// q_table[{0,0,0}][5] = 9.2;
// q_table[{0,0,1}][0] = 5.7;
// q_table[{0,0,1}][1] = -0.9; 
// q_table[{0,0,1}][2] = 3.4;
// q_table[{0,0,1}][3] = 7.9;
// q_table[{0,0,1}][4] = 6.4;
// q_table[{0,0,1}][5] = 3.6; and so on
                
            }
        }
    }
}

Здесь я инициализировал карту (q_table) выше, задав постоянное значение 3 и 6 соответственно. Соответственно, я сделал 3 цикла for для его правильной инициализации.

Теперь я хочу улучшить проект, взяв значение от пользователя в качестве входных данных для создания карты во время выполнения. Я не могу найти способ создать карту во время выполнения. Основная проблема, с которой я сталкиваюсь, заключается в том, что для создания карты используются циклы for, тогда как я могу написать функцию с неизвестным числом циклов for, если я не знаю, сколько из них мне понадобится.

Ответы [ 2 ]

0 голосов
/ 21 июня 2020

Если что-то решается во время выполнения, вам может понадобиться std::arrays в качестве пары ключ-значение .

Есть много способов индексировать многомерные массивы с помощью одного for-l oop. Перейти от многомерного массива к одномерному массиву просто. Если i, j, k - ваши индексы, тогда вы сохраните их в позиции index=k*N*N+j*N+i; в многомерном массиве (где в вашем случае N=2*SIZE. Если вы хотели ввести for (int i =-SIZE; i<=SIZE; i++), тогда у вас будет N=2*SIZE+1). Итак, если у вас есть n-мерный массив, а index [k] - это массив индексов, вы можете упаковать его в одномерный индекс с помощью следующего алгоритма:

//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;

Но если я правильно понимаю, вы хотите решить обратную задачу. Это можно сделать с помощью целочисленного деления и модульной арифметики c. (index[2]*N*N+index[1]*N+index[0])%N - это просто index[0], а (index[2]*N*N+index[1]*N+index[0])/N - это просто index[2]*N+index[1], поэтому, выполняя операции деления и по модулю, вы можете вернуть индексы. В конце концов, у вас будет реализация, которая выглядит примерно так:

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;
}

Вот полная реализация, которая выводит следующее для size = 1, depth = 4 и width = 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];

Исходный код:

#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;
}
0 голосов
/ 21 июня 2020

Что-то в этом роде (непроверено)

int dims = ...;  // the number of dimensions
int size = ...;  // All dimensions run 0 through size-1
std::vector<int> indices(dims);  // starting with all zeros
bool done = false;
while (!done) {
  // Do something with the tuple of indices

  // Advance to next tuple
  for (int dim = dims - 1; dim >= 0; --dim) {
    if (++indices[dim] < size) break;
    indices[dim] = 0;
    done = (dim == 0);
  }
}
...