Question

This might be similar to Java : Cartesian Product of a List of Lists but not answering my question.

I created the following

TreeMap<String, Set<String>> aMapOfSet

aMapOfSet represents different words in a sentence and Set<String> will contain all variations to the words if there is no variation then set will be empty/null for that word key.

I want to write a method that would take aMapOfSet and returns a Set of all possible sentences.

For instance, the original sentence could be:

tss xes wxy xyz

suppose there are total of 3 variations for the word "wxy" and total of 2 variations for the word "xyz"

Then aMapOfSet would look like this

tss
xes
wxy -> [wxys,wxyes]
xyz -> [xyzs]

The answer would be 6 sentences in resultSet

tss xes wxy xyz
tss xes wxys xyz
tss xes wxyes xyz

tss xes wxy xyzs
tss xes wxys xyzs
tss xes wxyes xyzs

I used treeMap to preserve the sequence of words.

Here is my work in progress code:

Set<String> getCartesianProduct(TreeMap<String, Set<String>> wordVariationSet)
{
    Set<String> resultSet =new HashSet<String>();// to store answer

    for(String theOriginalWord: wordVariationSet.keySet())
    {
       for(String word:wordVariationSet.get(theOriginalWord))
       {

           // TODO create a sentence with 1 space between words and add to resultSet
       }
    }

    return resultSet;

}

I will update the code as I make more progress.

What is the best way to iterate through all variations, so to get all 6 sentences.

Was it helpful?

Solution

This might be a good time to use recursion:

Set<String> getCartesianProduct(List<String> originalWords, TreeMap<String, Set<String>> wordVariationSet) {
    Set<String> resultSet =new HashSet<String>(); // to store answer
    varyWord(resultSet, "", originalWords, wordVariationSet, 0);  // begin recursion with empty sentence
    return resultSet;  // return result
}

void varyWord(Set<String> result, String sentence, List<String> originalWords, Map<String, Set<String>> wordVariationSet, int index) {
    if (index==originalWords.size()) {  // no more words to vary -> sentence is complete
        result.add(sentence);  // add to results
        return;  // done (return from recursion)
    }
    if (index>0) sentence += " ";  // add a space if working on any but first word
    String theOriginalWord = originalWords.get(index);  // grab original word
    varyWord(result, sentence + theOriginalWord, originalWords, wordVariationSet, index+1);  // add to sentence and vary next word
    Set<String> wordVariations = wordVariationSet.get(theOriginalWord);  // grab variations of this word
    if (wordVariations!=null)  // make sure they're not null
        for(String word: wordVariations)  // iterate over variations
            varyWord(result, sentence + word, originalWords, wordVariationSet, index+1);  // add to sentence and vary next word
}

I hope this code is self-explanatory. If not, let me know and I can add some detail.

A couple of things to note:

  1. You wrote "I used treeMap to preserve the sequence of words.", but unfortunately a treemap sorts its keys by their natural ordering (in this case by alphabet), not by when they were added. That's why I included the List<String> originalWords as a parameter, which does preserve ordering. So, you will need to initialize that as well (make an ArrayList and right after you put(...) a word into aMapOfSet, also add(...) it to the list).
  2. This code is missing a couple of checks, like a null-check for originalWords and wordVariationSet, a check whether wordVariationSet contains the same words as originalWords, ...
  3. If your originalWords-sentence contains the same word twice, the wordVariationSet will not be able to handle different variations for each. Instead, your second put(...) will overwrite your first one.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top