I have a pool of options in groups and I'm trying to dynamically generate the combinations for testing purposes. I would like to define the buckets and have code generating all the combinations to be fed to my TestNG test via @DataProvider. Right now I have some cases hardcoded but it's obvious is not the best way of doing it for maintaining the code.
I'm struggling to handle the case where you have x "balls" in y "buckets" when y is > 2.
In the trivial case let's say you have the following example:
public static void main(String [] args){
Object[][] combinations = getCombinations(
new String[]
{
"1", "2"
},
new String[]
{
"3", "4"
}/*,
new String[]
{
"5", "6"
}*/);
for (Object[] combination : combinations)
{
System.out.println(Arrays.toString(combination));
}
}
private Object[][] getCombinations(Object[]... arrays)
{
if (arrays.length == 0)
{
return new Object[0][0];
}
List<Object[]> solutions = new ArrayList<>();
Object[] array1 = arrays[0];
for (Object o : array1)
{
for (int i = 1; i < arrays.length; i++)
{
for (Object o2 : arrays[i])
{
int count = 0;
Object[] path = new Object[arrays.length];
path[count++] = o;
path[count++] = o2;
solutions.add(path);
}
}
}
return solutions.toArray(new Object[0][0]);
}
Output:
[1, 3]
[1, 4]
[2, 3]
[2, 4]
Adding the third "bucket" throws everything out the window.
The solutions would be as follows:
[1,3,5]
[1,3,6]
[1,4,5]
[1,4,6]
[2,3,5]
[2,3,6]
[2,4,5]
[2,4,6]
Any ideas how to attack this issue? Ideally you would pass getCombinations the amount of picks per bucket.
Although a solution code would be welcomed, I'm more interested in the reasoning behind it.
Update For future visitors here's the great answer by Kevin Anderson in a generic form:
Unit Test:
import static org.testng.Assert.assertEquals;
import java.util.Arrays;
import java.util.List;
import org.testng.annotations.Test;
public class CombinationNGTest
{
@Test
public void testCombinaitonOnePick()
{
List<List<Integer>> result
= Combination.pickKfromEach((List<List<Integer>>) Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4)),
1);
assertEquals(result.size(), 4, result.toString());
result = Combination.pickKfromEach((List<List<Integer>>) Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5, 6)),
1);
assertEquals(result.size(), 8, result.toString());
result = Combination.pickKfromEach((List<List<Integer>>) Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5, 6),
Arrays.asList(7, 8)),
1);
assertEquals(result.size(), 16, result.toString());
List<List<String>> result2= Combination.pickKfromEach((List<List<String>>) Arrays.asList(
Arrays.asList("A", "B"),
Arrays.asList("C", "D")),
1);
assertEquals(result2.size(), 4, result.toString());
}
@Test
public void testCombinaitonMultiplePicks()
{
List<List<Integer>> result
= Combination.pickKfromEach((List<List<Integer>>) Arrays.asList(
Arrays.asList(1, 2, 3),
Arrays.asList(4, 5, 6)),
2);
assertEquals(result.size(), 9, result.toString());
}
}
[1,3], [1,4], [1,5], [1,6], [2,3]. [2,4], [2,5], [2,6]or[1,3,5], [1,3,6], [1,4,5], [1,4,6], [2,3,5], [2,3,6], [2,4,5], [2,4,6]?