package com.github.timp.anagram;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

public class Query {
  private final Set searchesSoFar;
  private final Tree<String> keyTree;
  private final String key;
  ArrayList<String> keys;
  LetterBag ourLetters;
  HashSet<String> possibles;
  boolean done;

  /**
   *
   * @param keyTree The results tree of Anagram keys
   * @param searchesSoFar All searches, sorted alphabetically
   * @param keys The list of previous keys
   * @param key the potential key
   * @param possibles the collection of legal keys
   * @param letters the remaining letters to include
   */
  public Query(Tree<String> keyTree, Set searchesSoFar, ArrayList<String> keys, String key, HashSet<String> possibles, LetterBag letters) {
    this.keyTree = keyTree;
    this.searchesSoFar = searchesSoFar;
    this.keys = keys;
    this.key = key;
    keys.add(key);
    String searchKey = new ComparableSearchRepresentation(keys).toKey();
    done = ! searchesSoFar.add(searchKey);
    ourLetters = letters.copy().remove(key);
    this.possibles = possibles;
  }

  public boolean producesResults() {

    if (done) {
      return false;
    }

    if (ourLetters.count() == 0) {
      Tree<String> childKeyResultTree = new Tree<String>(key);
      keyTree.add(childKeyResultTree);
      return true;
    } else {
      HashSet<String> remainingPossibilities = new HashSet<>();
      for (String p: possibles) {
        if (ourLetters.contains(p)) {
          remainingPossibilities.add(p);
        }
      }

      Tree<String> childKeyResultTree = new Tree<>(key);


      boolean found = false;
      for (String p : remainingPossibilities) {

        ArrayList<String> childKeys = (ArrayList)keys.clone();
        Query childQuery = new Query(
            childKeyResultTree,
            searchesSoFar,
            childKeys,
            p,
            remainingPossibilities,
            ourLetters);
        boolean terminal = childQuery.producesResults();
        if (terminal) {
          found = true;
        //  keys.add(p);

          keyTree.add(childKeyResultTree);

        }
      }
      return found;
    }
  }
}

@@ -124,16 +124,276 @@
  Query %7B
+%0A%0A  // Tuned to enable %22Benedict Cumberbatch%22 to return in 21s%0A  // This throttling is allowed within the specification which%0A  // does NOT specify all possible anagrams from the dictionary must be produced.%0A  public static int MAX_POSSIBILITIES_THROTTLE = 51;
 %0A  priva
@@ -524,20 +524,17 @@
 tterBag 
-ourL
+l
 etters;%0A
@@ -845,17 +845,25 @@
  @param 
-l
+previousL
 etters t
@@ -991,16 +991,31 @@
 ing key,
+%0A              
  HashSet
@@ -1033,16 +1033,31 @@
 ssibles,
+%0A              
  LetterB
@@ -1055,25 +1055,33 @@
   LetterBag 
-l
+previousL
 etters) %7B%0A  
@@ -1323,28 +1323,25 @@
 chKey);%0A    
-ourL
+l
 etters = let
@@ -1337,17 +1337,25 @@
 tters = 
-l
+previousL
 etters.c
@@ -1491,36 +1491,33 @@
 %0A    %7D%0A%0A    if (
-ourL
+l
 etters.count() =
@@ -1717,24 +1717,58 @@
 ashSet%3C%3E();%0A
+      int possibilitiesCount = 0;%0A
       for (S
@@ -1805,84 +1805,272 @@
 if (
-ourLetters.contains(p)) %7B%0A          remainingPossibilities.add(p);%0A        %7D
+possibilitiesCount %3C MAX_POSSIBILITIES_THROTTLE) %7B%0A          if (letters.contains(p)) %7B%0A            possibilitiesCount++;%0A            remainingPossibilities.add(p);%0A          %7D%0A        %7D%0A      %7D%0A      if (remainingPossibilities.size() == 0) %7B%0A        return false;
 %0A   
@@ -2462,12 +2462,9 @@
     
-ourL
+l
 ette

Add throttle