Skip to content

Commit 9040aed

Browse files
committed
1 parent 046f1d0 commit 9040aed

File tree

2 files changed

+215
-0
lines changed

2 files changed

+215
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package org.paukov.combinatorics.cartesian;
2+
3+
import org.paukov.combinatorics.Factory;
4+
import org.paukov.combinatorics.ICombinatoricsVector;
5+
6+
import java.util.Iterator;
7+
8+
/**
9+
* Iterator for the cartesian product generator
10+
*
11+
* @param <T> Type of the elements in the cartesian product
12+
* @author Julius Iglesia, Dmytro Paukov
13+
* @version 2.2
14+
* @see CartesianProductGenerator
15+
*/
16+
public class CartesianProductIterator<T> implements
17+
Iterator<ICombinatoricsVector<T>> {
18+
19+
private ICombinatoricsVector<ICombinatoricsVector<T>> vector;
20+
21+
private final int vectorSize;
22+
23+
private int nextIndex;
24+
25+
private final int[] indices;
26+
27+
private ICombinatoricsVector<T> current;
28+
29+
private int index = 0;
30+
31+
private boolean hasEmptyList = false;
32+
33+
CartesianProductIterator(CartesianProductGenerator<T> generator) {
34+
vector = generator.originalVector;
35+
vectorSize = generator.originalVector.getSize();
36+
37+
// start from the last index
38+
nextIndex = vectorSize - 1;
39+
40+
// for tracking the indices of the product
41+
indices = new int[this.vectorSize];
42+
43+
// for the tracking the lengths of the lists
44+
for (int i = 0; i < vectorSize; i++) {
45+
hasEmptyList = hasEmptyList || vector.getValue(i).getSize() == 0;
46+
}
47+
}
48+
49+
/**
50+
* Returns true if all cartesian products were iterated, otherwise false
51+
*/
52+
@Override
53+
public boolean hasNext() {
54+
return !hasEmptyList && nextIndex >= 0;
55+
}
56+
57+
/**
58+
* Moves to the next Cartesian product
59+
*/
60+
@Override
61+
public ICombinatoricsVector<T> next() {
62+
if (index == 0) {
63+
return generateCartesianProduct();
64+
}
65+
66+
if (nextIndex < 0) {
67+
throw new RuntimeException("No more cartesian product.");
68+
}
69+
70+
// Move to the next element
71+
indices[nextIndex]++;
72+
73+
for (int i = nextIndex + 1; i < vectorSize; i++) {
74+
indices[i] = 0;
75+
}
76+
77+
return generateCartesianProduct();
78+
}
79+
80+
@Override
81+
public void remove() {
82+
throw new UnsupportedOperationException();
83+
}
84+
85+
@Override
86+
public String toString() {
87+
return "CartesianProductIterator=[#" + index + ", " + current + "]";
88+
}
89+
90+
private ICombinatoricsVector<T> generateCartesianProduct() {
91+
current = Factory.createVector();
92+
for (int i = 0; i < vectorSize; i++) {
93+
current.addValue(vector.getValue(i).getValue(indices[i]));
94+
}
95+
96+
// After generating the current, check if has still next cartesian product,
97+
// this will be used by #hasNext function
98+
checkIfHasNextCartesianProduct();
99+
index++;
100+
101+
return current;
102+
}
103+
104+
private void checkIfHasNextCartesianProduct() {
105+
// Check if has still cartesian product by finding an array that has more elements left
106+
nextIndex = vectorSize - 1;
107+
while (nextIndex >= 0 &&
108+
indices[nextIndex] + 1 >= vector.getValue(nextIndex).getSize()) {
109+
nextIndex--;
110+
}
111+
}
112+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package org.paukov.combinatorics.cartesian;
2+
3+
import org.junit.Test;
4+
import org.paukov.combinatorics.Factory;
5+
import org.paukov.combinatorics.Generator;
6+
import org.paukov.combinatorics.ICombinatoricsVector;
7+
8+
import java.util.Iterator;
9+
import java.util.List;
10+
11+
import static org.junit.Assert.assertEquals;
12+
import static org.paukov.combinatorics.Factory.createVector;
13+
14+
/**
15+
* Created by dpaukov on 5/3/18.
16+
*/
17+
public class CartesianProductTest {
18+
19+
@Test
20+
public void test_cartesian_product() {
21+
22+
ICombinatoricsVector<String> set01 = createVector(new String[]{"a", "b"});
23+
ICombinatoricsVector<String> set02 = createVector(new String[]{"x", "y"});
24+
25+
ICombinatoricsVector<ICombinatoricsVector<String>> initialVector = createVector();
26+
initialVector.addValue(set01);
27+
initialVector.addValue(set02);
28+
29+
Generator<String> cartesianProduct = new CartesianProductGenerator<String>(
30+
initialVector);
31+
32+
Iterator<ICombinatoricsVector<String>> itr = cartesianProduct
33+
.iterator();
34+
35+
while (itr.hasNext()) {
36+
ICombinatoricsVector<String> combination = itr
37+
.next();
38+
System.out.println(combination);
39+
}
40+
41+
List<ICombinatoricsVector<String>> list = cartesianProduct
42+
.generateAllObjects();
43+
44+
assertEquals(4, list.size());
45+
assertEquals(4, cartesianProduct.getNumberOfGeneratedObjects());
46+
47+
assertEquals(list.get(0), createVector(new String[]{"a", "x"}));
48+
assertEquals(list.get(1), createVector(new String[]{"a", "y"}));
49+
assertEquals(list.get(2), createVector(new String[]{"b", "x"}));
50+
assertEquals(list.get(3), createVector(new String[]{"b", "y"}));
51+
}
52+
53+
@Test
54+
public void test_cartesian_product_one_set_is_empty() {
55+
56+
ICombinatoricsVector<String> set01 = createVector(new String[]{"a", "b"});
57+
ICombinatoricsVector<String> set02 = createVector();
58+
59+
ICombinatoricsVector<ICombinatoricsVector<String>> initialVector = createVector();
60+
initialVector.addValue(set01);
61+
initialVector.addValue(set02);
62+
63+
Generator<String> cartesianProduct = new CartesianProductGenerator<String>(
64+
initialVector);
65+
66+
Iterator<ICombinatoricsVector<String>> itr = cartesianProduct
67+
.iterator();
68+
69+
while (itr.hasNext()) {
70+
ICombinatoricsVector<String> combination = itr
71+
.next();
72+
System.out.println(combination);
73+
}
74+
75+
List<ICombinatoricsVector<String>> list = cartesianProduct
76+
.generateAllObjects();
77+
78+
assertEquals(0, list.size());
79+
assertEquals(0, cartesianProduct.getNumberOfGeneratedObjects());
80+
}
81+
82+
@Test
83+
public void test_cartesian_product_empty() {
84+
85+
Generator<String> cartesianProduct = new CartesianProductGenerator<String>(
86+
Factory.<ICombinatoricsVector<String>>createVector());
87+
88+
Iterator<ICombinatoricsVector<String>> itr = cartesianProduct
89+
.iterator();
90+
91+
while (itr.hasNext()) {
92+
ICombinatoricsVector<String> combination = itr
93+
.next();
94+
System.out.println(combination);
95+
}
96+
97+
List<ICombinatoricsVector<String>> list = cartesianProduct
98+
.generateAllObjects();
99+
100+
assertEquals(0, list.size());
101+
assertEquals(0, cartesianProduct.getNumberOfGeneratedObjects());
102+
}
103+
}

0 commit comments

Comments
 (0)