I have a set of objects. I also have a set of required objects, containing between 0 and 3 objects. I’m trying to find all combinations of 3 objects from the initial set that include the required objects.
Edit: Example —
objects: {A,B,C,D,E}
required: {A}
output: {A,B,C}, {A,B,D}, {A,B,E}, {A,C,D}, {A,C,E}, {A,D,E}
objects: {A,B,C,D,E}
required: {A,B}
output: {A,B,C}, {A,B,D}, {A,B,E}
The obvious, but slow, solution is something like:
for(int i = 0; i < objects.size()-2 ; i++){
for(int j = i; j < objects.size()-1 ; j++){
for(int k = j; k < objects.size() ; k++){
if(required.contains(i) || required.contains (j) || required.contains(k)){
results.add(new Result(i,j,k));
}
}
}
}
This solution traverses the entire search space regardless of required objects.
Another approach I came up with was to write custom code for each number of required objects:
switch (required.size()){
case 3:
results.add(new Result(required));
break;
case 2:
Object a = requiredIngredients.toArray()[0];
Object b = requiredIngredients.toArray()[1];
for(Object o : objects){
if(!required.contains(i)){
results.add(new Result(EnumSet.of(o, a, b)));
}
}
break;
etc..
This works, but is obnoxious and not generalizable.
A third approach is to make three separate sets, shrinking sets to include only a required value if requirements are present, then iterate over them normally:
for(Object i : firstObjects){
for(Object j : secondObjects){
if(i == j) continue;
for(Object k : thirdObjects){
if(j == k) continue;
results.add(new Result(i,j,k));
}
}
}
This seems somewhat better, but produces duplicate combinations. Eg. It would return both ABC and ACB as two separate results. I could have the result set recognize duplicates, but I’d prefer not to calculate it to begin with.
Hopefully these examples make the problem clear. I feel like someone has figured out how to solve this kind of problem already, but I’m having a hard time identifying the generalized problem type.
Here is a simple and general way, but maybe not the most efficient (in python):
outputs
If the required set is small, then it is probably worse than brute force, but as the size of the required set increases, it will become much more efficient than brute force. For example, if the required set is the same as the input set, then it finds the answer in constant time.