Algorithm to get Cartesian product

夙愿已清 提交于 2019-12-02 04:55:18

A hard code solution would be:

for (int a1 : {0}) {
  for (int a2 : {0,1,2}) {
    for (int a3 : {0,1,2,3}) {
      for (int a4 : {0}) {
        for (int a5 : {0,1}) {
            do_job(a1, a2, a3, a4, a5);
        }
      }
    }
  }
}

You may use the following for a generic way (putting all as into vector):

bool increase(const std::vector<std::size_t>& v, std::vector<std::size_t>& it)
{
    for (std::size_t i = 0, size = it.size(); i != size; ++i) {
        const std::size_t index = size - 1 - i;
        ++it[index];
        if (it[index] > v[index]) {
            it[index] = 0;
        } else {
            return true;
        }
    }
    return false;
}

void iterate(const std::vector<std::size_t>& v)
{
    std::vector<std::size_t> it(v.size(), 0);

    do {
        do_job(it);
    } while (increase(v, it));
}

Live Demo

From your example, it seem like you want to count with mixed radix, and your input is the maximum digit value for each position.

A simple way is to use arithmetic coding, treating the max digit 0 positions specially. Here's pseudo-code for the case with no 0 max digits:

input radixes
let n_numbers = product_of radixes
for i = 0 to n_numbers-1 inclusive
    let n = i
    for digit_pos = 0 to number-of-radixes-1
        output n mod radix[digit_pos]
        let n = n div radix[digit_pos]
    output newline

I leave the treatment of 0 as max digit in a position, as an exercise. :)


I can't recall any particularly relevant support for this in the C++ standard library. I.e. it's mostly a language-independent question that has nothing to do with C++, nothing to do with permutations, and nothing to do with arrays. Provided my interpretation of it is correct: it would have been better it the problem was described also with words, not just an example.

Recursion seems like the simplest way to approach this problem, given that you may not know the length of the input vector. Something like this:

import java.util.ArrayList;
import java.util.Arrays;

public class Cartesian {

  public static void printCartesian(String head, ArrayList<Integer> array) {
    if (array.size() == 0) {
      System.out.println(head);
      return;
    }
    if (array.size() == 1) {
      for (int i = 0; i <= array.get(0); ++i) {
        System.out.println(head + i + "]");
      }
      return;
    }
    // assert array.size() > 1
    int a0 = array.get(0);
    ArrayList<Integer> array0 = new ArrayList<Integer>(array);
    array0.remove(0);
    for (int i = 0; i <= a0; ++i) {
      printCartesian(head + i + ", ", array0);
    }
  }

  public static void main(String[] args) {
    Integer[] input = { 0, 2, 3, 0, 1 };
    ArrayList<Integer> array = new ArrayList<Integer>(Arrays.asList(input));
    printCartesian("[", array);
  }
}

The initial call would be printCartesian("[", a) where a is an ArrayList containing the elements of your array in order. An extra if clause has to be added for size == 1 because otherwise one too many commas is printed.

Translating this to C++ data structures shouldn't be difficult.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!