[BAEL-6708] Add Cartesian Product
This commit is contained in:
parent
811df00130
commit
2337e29d0b
|
@ -20,6 +20,17 @@
|
||||||
<version>${junit-platform.version}</version>
|
<version>${junit-platform.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testng</groupId>
|
||||||
|
<artifactId>testng</artifactId>
|
||||||
|
<version>7.7.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>31.0.1-jre</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package com.baeldung.cartesianproduct;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
public class CartesianProduct {
|
||||||
|
// Responsible for calculating Cartesian Product using iterative approach.
|
||||||
|
public List<List<Object>> getCartesianProductIterative(List<List<Object>> sets) {
|
||||||
|
List<List<Object>> result = new ArrayList<>();
|
||||||
|
if(sets == null || sets.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
int totalSets = sets.size();
|
||||||
|
int totalCombinations = 1 << totalSets;
|
||||||
|
for(int i = 0; i < totalCombinations; i++) {
|
||||||
|
List<Object> combination = new ArrayList<>();
|
||||||
|
for(int j = 0; j < totalSets; j++) {
|
||||||
|
if (((i >> j) & 1) == 1) {
|
||||||
|
combination.add(sets.get(j).get(0));
|
||||||
|
} else {
|
||||||
|
combination.add(sets.get(j).get(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.add(combination);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsible for calculating Cartesian Product using recursive approach.
|
||||||
|
public List<List<Object>> getCartesianProductRecursive(List<List<Object>> sets) {
|
||||||
|
List<List<Object>> result = new ArrayList<>();
|
||||||
|
getCartesianProductRecursiveHelper(sets, 0, new ArrayList<>(), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method for recursive approach
|
||||||
|
private void getCartesianProductRecursiveHelper(List<List<Object>> sets, int index, List<Object> current, List<List<Object>> result) {
|
||||||
|
if(index == sets.size()) {
|
||||||
|
result.add(new ArrayList<>(current));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Object> currentSet = sets.get(index);
|
||||||
|
for(Object element: currentSet) {
|
||||||
|
current.add(element);
|
||||||
|
getCartesianProductRecursiveHelper(sets, index+1, current, result);
|
||||||
|
current.remove(current.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsible for calculating Cartesian Product using streams.
|
||||||
|
public List<List<Object>> getCartesianProductUsingStreams(List<List<Object>> sets) {
|
||||||
|
return cartesianProduct(sets,0).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method for streams approach.
|
||||||
|
public Stream<List<Object>> cartesianProduct(List<List<Object>> sets, int index) {
|
||||||
|
if(index == sets.size()) {
|
||||||
|
List<Object> emptyList = new ArrayList<>();
|
||||||
|
return Stream.of(emptyList);
|
||||||
|
}
|
||||||
|
List<Object> currentSet = sets.get(index);
|
||||||
|
return currentSet.stream().flatMap(element -> cartesianProduct(sets, index+1)
|
||||||
|
.map(list -> {
|
||||||
|
List<Object> newList = new ArrayList<>(list);
|
||||||
|
newList.add(0, element); return newList;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsible for calculating Cartesian Product using Guava library.
|
||||||
|
public List<List<Object>> getCartesianProductUsingGuava(List<Set<Object>> sets) {
|
||||||
|
Set<List<Object>> cartesianProduct = Sets.cartesianProduct(sets);
|
||||||
|
List<List<Object>> cartesianList = new ArrayList<>(cartesianProduct);
|
||||||
|
return cartesianList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
package com.baeldung.cartesianproduct;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
public class CartesianProductUnitTest {
|
||||||
|
private CartesianProduct cp = new CartesianProduct();
|
||||||
|
List<List<Object>> sets = Arrays.asList(
|
||||||
|
Arrays.asList(10, 20),
|
||||||
|
Arrays.asList("John", "Jack"),
|
||||||
|
Arrays.asList('I', 'J')
|
||||||
|
);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCalculateCartesianProductUsingStreams() {
|
||||||
|
List<List<Object>> expected = Arrays.asList(
|
||||||
|
Arrays.asList(10, "John", 'I'),
|
||||||
|
Arrays.asList(10, "John", 'J'),
|
||||||
|
Arrays.asList(10, "Jack", 'I'),
|
||||||
|
Arrays.asList(10, "Jack", 'J'),
|
||||||
|
Arrays.asList(20, "John", 'I'),
|
||||||
|
Arrays.asList(20, "John", 'J'),
|
||||||
|
Arrays.asList(20, "Jack", 'I'),
|
||||||
|
Arrays.asList(20, "Jack", 'J')
|
||||||
|
);
|
||||||
|
|
||||||
|
List<List<Object>> cartesianProduct = cp.getCartesianProductUsingStreams(sets);
|
||||||
|
assertEquals(expected, cartesianProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCalculateCartesianProductUsingRecursion() {
|
||||||
|
List<List<Object>> expected = Arrays.asList(
|
||||||
|
Arrays.asList(10, "John", 'I'),
|
||||||
|
Arrays.asList(10, "John", 'J'),
|
||||||
|
Arrays.asList(10, "Jack", 'I'),
|
||||||
|
Arrays.asList(10, "Jack", 'J'),
|
||||||
|
Arrays.asList(20, "John", 'I'),
|
||||||
|
Arrays.asList(20, "John", 'J'),
|
||||||
|
Arrays.asList(20, "Jack", 'I'),
|
||||||
|
Arrays.asList(20, "Jack", 'J')
|
||||||
|
);
|
||||||
|
|
||||||
|
List<List<Object>> cartesianProduct = cp.getCartesianProductRecursive(sets);
|
||||||
|
assertEquals(expected, cartesianProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCalculateCartesianProductUsingIterativeApproach() {
|
||||||
|
List<List<Object>> expected = Arrays.asList(
|
||||||
|
Arrays.asList(20, "Jack", 'J'),
|
||||||
|
Arrays.asList(10, "Jack", 'J'),
|
||||||
|
Arrays.asList(20, "John", 'J'),
|
||||||
|
Arrays.asList(10, "John", 'J'),
|
||||||
|
Arrays.asList(20, "Jack", 'I'),
|
||||||
|
Arrays.asList(10, "Jack", 'I'),
|
||||||
|
Arrays.asList(20, "John", 'I'),
|
||||||
|
Arrays.asList(10, "John", 'I')
|
||||||
|
);
|
||||||
|
|
||||||
|
List<List<Object>> cartesianProduct = cp.getCartesianProductIterative(sets);
|
||||||
|
assertEquals(expected, cartesianProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCalculateCartesianProductUsingGuava() {
|
||||||
|
List<Set<Object>> sets = new ArrayList<>();
|
||||||
|
sets.add(new HashSet<>(Arrays.asList(10, 20)));
|
||||||
|
sets.add(new HashSet<>(Arrays.asList("John", "Jack")));
|
||||||
|
sets.add(new HashSet<>(Arrays.asList('I', 'J')));
|
||||||
|
|
||||||
|
List<List<Object>> expected = Arrays.asList(
|
||||||
|
Arrays.asList(20, "John", 'I'),
|
||||||
|
Arrays.asList(20, "John", 'J'),
|
||||||
|
Arrays.asList(20, "Jack", 'I'),
|
||||||
|
Arrays.asList(20, "Jack", 'J'),
|
||||||
|
Arrays.asList(10, "John", 'I'),
|
||||||
|
Arrays.asList(10, "John", 'J'),
|
||||||
|
Arrays.asList(10, "Jack", 'I'),
|
||||||
|
Arrays.asList(10, "Jack", 'J')
|
||||||
|
);
|
||||||
|
|
||||||
|
List<List<Object>> cartesianProduct = cp.getCartesianProductUsingGuava(sets);
|
||||||
|
assertEquals(expected, cartesianProduct);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue