[BAEL-6708] Add Cartesian Product
This commit is contained in:
parent
811df00130
commit
2337e29d0b
|
@ -20,6 +20,17 @@
|
|||
<version>${junit-platform.version}</version>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
|
||||
<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