blob: 3e22af649b48e0de407cc319e1665cb7c468573f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 University of Illinois at Urbana-Champaign and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.rephraserengine.testing.combinatorial;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.rephraserengine.core.util.Pair;
/**
*
* @author Jeff Overbey
*
* @since 2.0
*/
public class ForEach
{
private ForEach() {;}
public static <T> Iterable<List<T>> combinationOf(List<T> list)
{
return combinationOf(1, list.size(), list);
}
public static <T> Iterable<List<T>> combinationOf(int numElementsToChoose,
List<T> list)
{
return combinationOf(numElementsToChoose, numElementsToChoose, list);
}
public static <T> Iterable<List<T>> combinationOf(final int minNumElementsInCombination,
final int maxNumElementsInCombination,
final List<T> list)
{
return new Iterable<List<T>>()
{
public Iterator<List<T>> iterator()
{
return new CombinationIterator<T>(minNumElementsInCombination,
maxNumElementsInCombination,
list);
}
};
}
private static class CombinationIterator<T> implements Iterator<List<T>>
{
protected List<T> list;
protected CombinationGenerator gen;
protected int[] nextCombination;
public CombinationIterator(int minNumElementsInCombination,
int maxNumElementsInCombination,
List<T> list)
{
if (minNumElementsInCombination < 1
|| minNumElementsInCombination > list.size()
|| maxNumElementsInCombination < 0
|| maxNumElementsInCombination > list.size())
throw new IllegalArgumentException();
this.list = list;
this.gen = new CombinationGenerator(list.size(), maxNumElementsInCombination);
this.nextCombination = gen.firstCombination(minNumElementsInCombination);
}
public boolean hasNext()
{
return nextCombination != null;
}
public List<T> next()
{
if (nextCombination == null) return null;
List<T> combination = new ArrayList<T>(nextCombination.length);
for (int i = 0; i < nextCombination.length; i++)
combination.add(list.get(nextCombination[i]));
nextCombination = gen.nextCombination(nextCombination);
return combination;
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
/**
* @return all pairs of two objects from the given set
*/
public static <T> Iterable<Pair<T,T>> pairOf(final List<T> objects)
{
return new Iterable<Pair<T,T>>()
{
public Iterator<Pair<T,T>> iterator()
{
return new PairIterator<T>(objects);
}
};
}
private static class PairIterator<T> implements Iterator<Pair<T,T>>
{
/** Set of objects from which pairs will be generated */
protected final List<T> objects;
/** Index of the first component of the pair in {@link #objects} */
protected int fstIndex;
/** Index of the second component of the pair in {@link #objects} */
protected int sndIndex;
public PairIterator(List<T> objects)
{
if (objects == null) throw new IllegalArgumentException();
if (objects == null || objects.isEmpty())
throw new IllegalArgumentException();
this.objects = objects;
this.fstIndex = 0;
this.sndIndex = 0;
}
public boolean hasNext()
{
return fstIndex < objects.size();
}
public Pair<T,T> next()
{
if (fstIndex == objects.size()) return null;
Pair<T,T> result = new Pair<T,T>(objects.get(fstIndex), objects.get(sndIndex));
if (++sndIndex == objects.size())
{
++fstIndex;
sndIndex = 0;
}
return result;
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
/**
* @return all tuples of objects with one component from each of the given sets
*/
public static <T> Iterable<List<T>> tupleOf(final List<? extends T>... objects)
{
return new Iterable<List<T>>()
{
public Iterator<List<T>> iterator()
{
return new TupleIterator<T>(objects);
}
};
}
private static class TupleIterator<T> implements Iterator<List<T>>
{
/** Sets of objects from which pairs will be generated */
protected final List<? extends T>[] objects;
/** Indices of the components of the tuple: <code>index[i]</code> is an
* index into {@link #objects}[i] */
protected int[] indices;
public TupleIterator(List<? extends T>... objects)
{
if (objects == null) throw new IllegalArgumentException();
for (List<? extends T> list : objects)
if (list == null || list.isEmpty())
throw new IllegalArgumentException();
this.objects = objects;
this.indices = new int[objects.length];
}
public boolean hasNext()
{
return indices[0] < objects[0].size();
}
public List<T> next()
{
if (indices[0] == objects[0].size()) return null;
List<T> result = new ArrayList<T>(indices.length);
for (int i = 0; i < indices.length; i++)
result.add(objects[i].get(indices[i]));
incrementIndices();
return result;
}
private void incrementIndices()
{
for (int i = indices.length-1; i >= 0; i--)
{
indices[i]++;
if (indices[i] < objects[i].size())
break;
else if (i > 0)
indices[i] = 0;
}
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
}