0

I have 4 types of Integer values. I want to generate all possible combinations consisting of 3 elements from the below arrays like

5 1 72
3 7 9
8 14 11 //etc

List<Integer> list1 = Arrays.asList(5, 7, 11, 2, 10);
List<Integer> list2 = Arrays.asList(1, 9, 25);
List<Integer> list3 = Arrays.asList(72, 8);
List<Integer> list4 = Arrays.asList(3, 14, 22, 37, 19);

With the current implementation, inspired by this question, I'm getting combinations of 4 elements like

5 1 72 3
7 9 8 14
11 25 22 5 //etc

How can I achieve getting combinations of 3 elements?

private static List<List<Integer>> getCombination(int currentIndex, List<TempContainer<Integer>> containers) {
        if (currentIndex == containers.size()) {
            // Skip the items for the last container
            List<List<Integer>> combinations = new ArrayList<>();
            combinations.add(new ArrayList<>());
            return combinations;
        }
        List<List<Integer>> combinations = new ArrayList<>();
        TempContainer<Integer> container = containers.get(currentIndex);
        List<Integer> containerItemList = container.getItems();
        List<List<Integer>> suffixList = getCombination(currentIndex + 1, containers);
        int size = containerItemList.size();
        for (int ii = 0; ii < size; ii++) {
            Integer containerItem = containerItemList.get(ii);
            if (suffixList != null) {
                for (List<Integer> suffix : suffixList) {
                    List<Integer> nextCombination = new ArrayList<>();
                    nextCombination.add(containerItem);
                    nextCombination.addAll(suffix);
                    combinations.add(nextCombination);
                }
            }
        }
        return combinations;
    }

TempContainer container1 = new TempContainer();
        container1.setItems(list1);
        TempContainer container2 = new TempContainer();
        container2.setItems(list2);
        TempContainer container3 = new TempContainer();
        container3.setItems(list3);
        TempContainer container4 = new TempContainer();
        container4.setItems(list4);
        List<TempContainer<Integer>> containers = new ArrayList<>(3);
        containers.add(container1);
        containers.add(container2);
        containers.add(container3);
        containers.add(container4);
// Get combinations
        List<List<Integer>> combinations = getCombination(0, containers);
3
  • What do you mean with “combinations of 3 elements” when you have four lists? Commented May 24, 2019 at 12:29
  • @Holger I want to use the data from the four lists in such a way that each combination contains only one element from any list. Commented May 24, 2019 at 12:37
  • This still is unclear. The linked solution returns a lists where the first position always contains elements from the first list, the second contains elements from the second list, and so on. How are the elements from four lists supposed to map to lists with only three elements? It seems your task is not even remotely related to the linked one. Commented May 24, 2019 at 12:46

3 Answers 3

1

Basically, you have to do what you did before. The only difference is that since you are now using only three of the four lists, you have to add a second permutation loop that cycles through all possible combinations of the relevant lists. So, the algorithm would be:

  • generate all possible combinations of three lists from four lists
  • for each combination, use the previous algorithm (for generating all possible element combinations)
Sign up to request clarification or add additional context in comments.

Comments

1

I think that the better solution could be this:

public static void main(String[] args) {
    List<Integer> list1 = Arrays.asList(5, 7, 11, 2, 10);
    List<Integer> list2 = Arrays.asList(1, 9, 25);
    List<Integer> list3 = Arrays.asList(72, 8);
    List<Integer> list4 = Arrays.asList(3, 14, 22, 37, 19);

    List<Integer[]> combinations = getCombinations(list1, list2, list3, list4);
    for (Integer[] combination : combinations)
        System.out.println(combination[0] + "," + combination[1] + "," + combination[2]);
}

public static List<Integer[]> getCombinations(List<Integer>... lists) {
    return _getCombination(0, new ArrayList<>(), new ArrayList<>(), lists);
}

private static List<Integer[]> _getCombination(int depth, List<Integer[]> currentCombinations,
                                             List<Integer> currentCombination, List<Integer>... lists) {
    if (currentCombination.size() == 3) {
        currentCombinations.add(currentCombination.toArray(new Integer[3]));
    } else {
        for (int i = 0 ; i < lists.length ; i++)
            for (int j = 0 ; j < lists[i].size() ; j++) {
            currentCombination.add(lists[i].get(j));
            _getCombination(depth + 1, currentCombinations, currentCombination, lists);
            currentCombination.remove(lists[i].get(j));
        }
    }
    return currentCombinations;
}

4 Comments

Thank you. I see one problem with the solution, it returns combinations with repeated numbers in a single combination like: [68,68,66] [68,68,67] [68,68,68]
To solve this you have to add a single if: for (int i = 0 ; i < lists.length ; i++) for (int j = 0 ; j < lists[i].size() ; j++) if (!currentCombination.contains(lists[i].get(j))) { currentCombination.add(lists[i].get(j)); _getCombination(depth + 1, currentCombinations, currentCombination, lists); currentCombination.remove(lists[i].get(j)); }
Could you specify where should I add it?
inside the two for. You have a for iterating over i, then another for iterating over j, and within the two there are 3 lines of code in the example that I put you. Then you place the if between the for and the block that of 3 lines of code. So that the 3 lines are only executed if the if is fulfilled. The if must check if the element that is being checked is already in the partial solution. It is a backtracking system, if you have added for example 2 numbers, check before trying to add the third party if that third is one of the previous two, in which case you do not add it
0

Try similar to this

    List<Integer> list1 = Arrays.asList(72, 8);
    List<Integer> list2 = Arrays.asList(1,  9, 25);
    List<Integer> list3 = Arrays.asList(5,  7, 11,  2, 10);
    List<Integer> list4 = Arrays.asList(3,  14,22, 37, 19, 18);
    List<List<Integer>> mainList = new ArrayList<>();
    mainList.add(list4);
    mainList.add(list3);
    mainList.add(list2);
    mainList.add(list1);
    int max = 0;
    // FIND MAX LIST So that We can ITERATE on that 
    for (int k = 0; k < mainList.size(); k++) {
        if (mainList.get(k).size() > max) {
            max = mainList.get(k).size();
        }
    }

    for (int k = 0; k < max; k++) {
        String string = new String(); // You can use another list of array to store combination. For testing I have used String
        try {
            for (int l = 0; l < mainList.size(); l++) {
                if (mainList.get(l).size() > k)
                    string = string.concat(" " + mainList.get(l).get(k));
            }

            System.out.println(string);
        } catch (Exception e) {
            System.out.println("Error IN CALL");
        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.