package net.sf.colossus.util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * An iterator that returns permutations of the originally passed list. * * The first permutation is the unmodified list. */ public final class PermutationIterator<T> implements Iterator<List<T>> { private final List<T> permList; private final PermGen pg; private boolean foundNext = false; private boolean anyLeft = true; private boolean first = true; private int nextSwap; /** Set up a permutation generator for the passed list. */ public PermutationIterator(List<T> list) { pg = new PermGen(list.size()); // Since we're not going to mess with the elements, just // their order, a shallow copy should be fine. permList = new ArrayList<T>(list); } /** hasNext should not change things if called repeatedly, * so when it's called we'll lazily evaluate the next * permutation, and then keep returning true until next() * is called. */ public boolean hasNext() { if (first) { return true; } if (foundNext) { return anyLeft; } else { nextSwap = pg.getNext(); foundNext = true; anyLeft = (nextSwap != -1); return anyLeft; } } public List<T> next() { // Return the unmodified list the first time. if (first) { first = false; return permList; } // If we haven't already found the next permutation, find it. if (!foundNext) { nextSwap = pg.getNext(); foundNext = true; anyLeft = (nextSwap != -1); } // All done. if (!anyLeft) { return null; } // Modify and return the list. swap(nextSwap); foundNext = false; return permList; } public void remove() { throw new UnsupportedOperationException(); } /** Swap elements lower and lower + 1 of permList */ private void swap(int lower) { T temp = permList.get(lower); permList.set(lower, permList.get(lower + 1)); permList.set(lower + 1, temp); } }