/*
Copyright (C) 2011 Stephan Schiffel <stephan.schiffel@gmx.de>
This file is part of GameController.
GameController is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GameController is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GameController. If not, see <http://www.gnu.org/licenses/>.
*/
package tud.auxiliary;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
/**
* CrossProduct computes a cross product of a collection of lists on the fly.
* It contains a list of tuples with each combination of elements of given lists.
*
* @author "Stephan Schiffel" <stephan.schiffel@gmx.de>
*
* @param <E> the type of the elements of the tuples, so far all elements must be of the same type
*/
public class CrossProduct<E> extends AbstractCollection<List<E>> implements
Collection<List<E>> {
private final class CrossProductIterator implements
Iterator<List<E>> {
private List<Iterator<E>> iterators;
private List<E> nextTuple;
private int tupleSize;
public CrossProductIterator(List<? extends Iterable<E>> iterables) {
super();
tupleSize = iterables.size();
iterators = new Vector<Iterator<E>>(tupleSize);
nextTuple = new Vector<E>(tupleSize);
for (Iterable<E> iterable : iterables) {
Iterator<E> iterator = iterable.iterator();
iterators.add(iterator);
if(nextTuple!=null && iterator.hasNext()) {
nextTuple.add(iterator.next());
} else {
nextTuple=null;
}
}
}
@Override
public boolean hasNext() {
return nextTuple!=null;
}
@Override
public List<E> next() {
List<E> currentTuple = nextTuple;
if(currentTuple!=null) {
nextTuple = new Vector<E>(currentTuple);
int i=0;
while(i<tupleSize && !iterators.get(i).hasNext()) {
Iterator<E> iterator = collections.get(i).iterator();
iterators.set(i, iterator);
nextTuple.set(i, iterator.next());
++i;
}
if(i<=tupleSize){
nextTuple.set(i, iterators.get(i).next());
} else {
nextTuple=null;
}
}
return currentTuple;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
private List<Collection<E>> collections;
public CrossProduct(List<Collection<E>> collections) {
super();
this.collections = collections;
}
@Override
public Iterator<List<E>> iterator() {
return new CrossProductIterator(collections);
}
@Override
public int size() {
int size = 1;
for (Collection<E> collection : collections) {
size*=collection.size();
}
return size;
}
}