Recursive generator in C++

前端 未结 5 1202
星月不相逢
星月不相逢 2021-02-06 11:13

I have a vector of size = N where each element i can have values from 0 to possible_values[i]-1. I want to do a function that iterates me through all those values.

I was

5条回答
  •  青春惊慌失措
    2021-02-06 11:30

    EDIT: A bit more concise general code with better comments and explanation (I hope ;)).

    This is an iterative, not a recursive, approach for an arbitrary number of positions with arbitrary maximum possible values. The idea is as follows.

    We are given maximum possible value in each position. For each position we generate an array containing of all possible values for this position. We find total number of combinations of how these values can be picked out to fill in positions ("number of permutations", equal to product of all possible values). We then iterate through all combinations, storing each current combination in an array of combinations, and updating current indices to select next combination on the next iteration. We don't need to worry about boundary checks, because we are inherently limited by number of combinations. After iterated through all combinations, we return a 2D array that holds all of them (and then print them).

    Hope it might be useful (code on ideone.com):

    #include 
    #include 
    #include 
    
    namespace so {
    using size = std::size_t;
    using array_1d = std::vector;
    using array_2d = std::vector;
    
    array_2d generate_combinations_all(array_1d const & _values_max) {
     array_2d values_all_; // arrays of all possible values for each position
     size count_combination_{1}; // number of possible combinations
    
     for (auto i_ : _values_max) { // generate & fill in 'values_all_'
      array_1d values_current_(i_);
      size value_current_{0};
    
      std::generate(values_current_.begin(), values_current_.end(), [&] {return (value_current_++);});
      values_all_.push_back(std::move(values_current_));
      count_combination_ *= i_;
     }
    
     array_2d combinations_all_; // array of arrays of all possible combinations
     array_1d indices_(_values_max.size(), 0); // array of current indices
    
     for (size i_{0}; i_ < count_combination_; ++i_) {
      array_1d combinantion_current_; // current combination
    
      for (size j_{0}; j_ < indices_.size(); ++j_) // fill in current combination
       combinantion_current_.push_back(values_all_[j_][indices_[j_]]);
    
      combinations_all_.push_back(std::move(combinantion_current_)); // append to 'combinations_all_'
    
      for (size m_{indices_.size()}; m_-- > 0;) // update current indices
       if (indices_[m_] < _values_max[m_] - 1) { // ++index at highest position possible
        ++indices_[m_];
        break;
       }
       else indices_[m_] = 0; // reset index if it's alrady at max value
     }
    
     return (combinations_all_);
    }
    
    void print_combinations_all(array_2d const & _combinations_all) {
     for (auto const & i_ : _combinations_all) { // "fancy" printing
      std::cout << "[";
      for (size j_{0}; j_ < i_.size(); ++j_)
       std::cout << i_[j_] << ((j_ < i_.size() - 1) ? ", " : "]\n");
     }
    }
    } // namespace so
    
    int main() {
     so::array_1d values_max_a_{3, 2, 2};
     so::array_1d values_max_b_{2, 1, 3, 2};
    
     so::print_combinations_all(so::generate_combinations_all(values_max_a_));
     std::cout << "***************" << std::endl;
     so::print_combinations_all(so::generate_combinations_all(values_max_b_));
    
     return (0);
    }
    

    Program's output:

    [0, 0, 0]
    [0, 0, 1]
    [0, 1, 0]
    [0, 1, 1]
    [1, 0, 0]
    [1, 0, 1]
    [1, 1, 0]
    [1, 1, 1]
    [2, 0, 0]
    [2, 0, 1]
    [2, 1, 0]
    [2, 1, 1]
    ***************
    [0, 0, 0, 0]
    [0, 0, 0, 1]
    [0, 0, 1, 0]
    [0, 0, 1, 1]
    [0, 0, 2, 0]
    [0, 0, 2, 1]
    [1, 0, 0, 0]
    [1, 0, 0, 1]
    [1, 0, 1, 0]
    [1, 0, 1, 1]
    [1, 0, 2, 0]
    [1, 0, 2, 1]
    

提交回复
热议问题