3
votes

How is it possible to do the Cartesian product using two arrays?

A={1,2,3}
B={2,3,4}
C={(1,2),(1,3),(1,4),(2,2),(2,3),(2,4),(3,2),(3,3),(3,4)}

This is the code I was using, but I always get a IndexOutOfBoundException.

public int[] cartesianProduct(int[] s1, int[] s2) {
    ArrayList<Integer> list = new ArrayList<>();
    for (int i = 0; i < s1.length; i++) {
        for (int v1 : s1) {
            for (int v2 : s2) {
                list.add(s1[i], s2[i]);
            }
        }
    }
    int[] result = new int[list.size()];
    int k = 0;
    for (int i : list) {
        result[k++] = i;
    }
    return result;
}
6

6 Answers

3
votes

To get Cartesian product with Java 8:

int[] A = {1, 2, 3};
int[] B = {2, 3, 4};
int[][] AB = Arrays.stream(A).boxed()
        .flatMap(ai -> Arrays.stream(B).boxed()
                .map(bi -> new int[]{ai, bi}))
        .toArray(int[][]::new);
System.out.println("Cartesian product:\n" + Arrays.deepToString(AB));

Output:

Cartesian product:
[[1, 2], [1, 3], [1, 4], [2, 2], [2, 3], [2, 4], [3, 2], [3, 3], [3, 4]]
1
votes

You don't need List. Try this.

public static int[][] cartesianProduct(int[] s1, int[] s2) {
    int size1 = s1.length;
    int size2 = s2.length;
    int[][] result = new int[size1 * size2][2];
    for (int i = 0, d = 0; i < size1; ++i) {
        for (int j = 0; j < size2; ++j, ++d) {
            result[d][0] = s1[i];
            result[d][1] = s2[j];
        }
    }
    return result;
}
1
votes

Recursive solution for n arrays. Call with param i = 0

public <T> List<List<T>> cartesianProduct(int i, List<T>... a) {
    if (i == a.length) {
        List<List<T>> result = new ArrayList<>();
        result.add(new ArrayList());
        return result;
    }
    List<List<T>> next = cartesianProduct(i + 1, a);
    List<List<T>> result = new ArrayList<>();
    for (int j = 0; j < a[i].size(); j++) {
        for (int k = 0; k < next.size(); k++) {
            List<T> concat = new ArrayList();
            concat.add(a[i].get(j));
            concat.addAll(next.get(k));
            result.add(concat);
        }
    }
    return result;
}
1
votes

As an alternative to the answer given by @Eran, I would just stop at having a list of ordered pairs:

public List<int[]> cartesianProduct(int[] s1, int[] s2) {
    List<int[]> list = new ArrayList<int[]>();
    for (int v1 : s1) {
        for (int v2 : s2) {
            list.add(new int[]{v1, v2});
        }
    }
    return list;
}

To get the output you want, you can just iterate over the list as follows.

Usage:

int[] s1 = new int[]{1, 2, 3};
int[] s2 = new int[]{2, 3, 4};
List<int[]> list = cartesianProduct(s1, s2);
System.out.print("{");
for (int i = 0; i < list.size(); ++i) {
    if (i > 0) System.out.print(", ");
    System.out.print("(" + list.get(i)[0] + ", " + list.get(i)[1] + ")");
}
System.out.println("}");

Output:

{(1, 2), (1, 3), (1, 4), (2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4)}
1
votes

The elements of the output array should be pairs of integers, therefore an int array cannot be the type of the output, and you can't use a List<Integer> to collect the data.

One way to represent each pair of numbers is an int array of two elements. This way the output would be a 2D array, and the List used to collect the data can be a List<int[]>:

public int[][] cartesianProduct(int[] s1, int[] s2) {
    List<int[]> list = new ArrayList<>();
    for (int v1 : s1) {
        for (int v2 : s2) {
            list.add(new int[]{v1, v2});
        }
    }
    int[][] result = new int[list.size()][2];
    int k = 0;
    for (int[] i : list) {
        result[k++] = i;
    }
    return result;
}
0
votes
//Also, works great with int[][] input, returning int[][][]
public static int[][][] cartesianProduct(int[][] s1, int[][] s2) {
    int size1 = s1.length;
    int size2 = s2.length;
    int[][][] result = new int[size1 * size2][2][2];
    for (int i = 0, d = 0; i < size1; ++i) {
        for (int j = 0; j < size2; ++j, ++d) {
            result[d][0] = s1[i];
            result[d][1] = s2[j];
        }
    }
    return result;
}