String[] letters; int[] indices; CombinationGenerator x = new CombinationGenerator (letters.length, 3); StringBuffer combination; while (x.hasMore ()) { combination = new StringBuffer (); indices = x.getNext (); for (int i = 0; i < indices.length; i++) { combination.append (elements[indices[i]]); } System.out.println (combination.toString ()); }
public List<T> next() { return nextCombinationAsList(); }
public boolean hasNext() { return hasMore(); }
/** * Generate the next combination and return an array containing * the appropriate elements. This overloaded method allows the caller * to provide an array that will be used and returned. * The purpose of this is to improve performance when iterating over * combinations. This method allows a single array instance to be reused. * @param destination Provides an array to use to create the * combination. The specified array must be the same length as a * combination. * @return The provided array now containing the elements of the combination. */ public T[] nextCombinationAsArray(T[] destination) { if (destination.length != combinationIndices.length) { throw new IllegalArgumentException("Destination array must be the same length as combinations."); } generateNextCombinationIndices(); for (int i = 0; i < combinationIndices.length; i++) { destination[i] = elements[combinationIndices[i]]; } return destination; }
/** * Create a combination generator that generates all combinations of * a specified length from the given set. * @param elements The set from which to generate combinations; will be used directly (not copied) * @param combinationLength The length of the combinations to be generated. */ public CombinationGenerator(T[] elements, int combinationLength) { if (combinationLength > elements.length) { throw new IllegalArgumentException("Combination length cannot be greater than set size."); } this.elements = elements; this.combinationIndices = new int[combinationLength]; BigInteger sizeFactorial = MathExtras.bigFactorial(elements.length); BigInteger lengthFactorial = MathExtras.bigFactorial(combinationLength); BigInteger differenceFactorial = MathExtras.bigFactorial(elements.length - combinationLength); BigInteger total = sizeFactorial.divide(differenceFactorial.multiply(lengthFactorial)); if (total.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { throw new IllegalArgumentException("Total number of combinations must not be more than 2^63."); } totalCombinations = total.longValue(); reset(); }
/** * Generate the next combination and return a list containing * the appropriate elements. This overloaded method allows the caller * to provide a list that will be used and returned. * The purpose of this is to improve performance when iterating over * combinations. If the {@link #nextCombinationAsList()} method is * used it will create a new list every time. When iterating over * combinations this will result in lots of short-lived objects that * have to be garbage collected. This method allows a single list * instance to be reused in such circumstances. * @param destination Provides a list to use to create the * combination. * @return The provided list now containing the elements of the combination. */ public List<T> nextCombinationAsList(List<T> destination) { generateNextCombinationIndices(); // Generate actual combination. destination.clear(); for (int i : combinationIndices) { destination.add(elements[i]); } return destination; }
/** * Generate the next combination and return a list containing the * appropriate elements. * @see #nextCombinationAsList(List) * @return A list containing the elements that make up the next combination. */ public List<T> nextCombinationAsList() { return nextCombinationAsList(new ArrayList<T>(elements.length)); }