All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cc.redberry.combinatorics.IntPermutations Maven / Gradle / Ivy

Go to download

A number of combinatorial algorithms for enumerating (without in-memory storing) of different types of combinations.

There is a newer version: 2.1
Show newest version
package cc.redberry.combinatorics;

/**
 * Iterator over all possible permutations.
 *
 * 

Example *

 * IntPermutations its = new IntPermutations(3);
 * while (its.hasNext())
 *     System.out.println(Arrays.toString(its.next()))
 * 
* The result will be *
 *      [0, 1, 2]
 *      [0, 2, 1]
 *      [1, 0, 2]
 *      [1, 2, 0]
 *      [2, 0, 1]
 *      [2, 1, 0]
 * 
* It is also possible to iterate in the opposite direction via {@link #previous()} method. * *

The iterator is implemented such that each next combination will be calculated only on the invocation of method * {@link #next()}. * *

Note: method {@link #next()} returns the same reference on each invocation. * * @author Dmitry Bolotin * @author Stanislav Poslavsky * @since 1.0 */ public final class IntPermutations implements CombinatorialIterator { private static final long serialVersionUID = 783197504482907083L; final int[] permutation; private boolean onFirst = true; private final int size; /** * Construct iterator over all permutations with specified dimension starting with identity. * * @param dimension dimension of permutations */ public IntPermutations(int dimension) { permutation = new int[dimension]; for (int i = 0; i < dimension; ++i) permutation[i] = i; this.size = dimension; } /** * Construct iterator over permutations with specified permutation at the start. If starting permutation is not * identity, the iterator will not iterate over all possible permutations, but only from starting permutation up to * the last permutation, which is [size-1,size-2,....1,0]. * *

Note: parameter {@code permutation} is not copied in constructor and the same instance will be used * during iteration.

* * @param permutation starting permutation * @throws IllegalArgumentException if permutation is inconsistent with one-line notation */ public IntPermutations(int[] permutation) { this.permutation = permutation; this.size = permutation.length; for (int i = 0; i < size - 1; ++i) { if (permutation[i] >= size || permutation[i] < 0) throw new IllegalArgumentException("Wrong permutation input: image of " + i + " element" + " greater then degree"); for (int j = i + 1; j < size; ++j) if (permutation[i] == permutation[j]) throw new IllegalArgumentException("Wrong permutation input: to elemets have the same image"); } } @Override public boolean hasNext() { return !isLast() || onFirst; } /** * Returns {@code true} if the iteration has more elements, iterating in back order. (In other words, returns {@code * true} if {@link #previous()} would return an element rather than throwing an exception.) * * @return {@code true} if the iteration has more elements */ public boolean hasPrevious() { return !isFirst(); } private boolean isLast() { for (int i = 0; i < size; i++) if (permutation[i] != size - 1 - i) return false; return true; } private boolean isFirst() { for (int i = 0; i < size; i++) if (permutation[i] != i) return false; return true; } /** * Returns the next element in the iteration. * * @return the next element in the iteration */ @Override public int[] next() { if (onFirst) { onFirst = false; return permutation; } final int end = size - 1; int p = end, low, high, med, s; while ((p > 0) && (permutation[p] < permutation[p - 1])) p--; if (p > 0) //if p==0 then it's the last one { s = permutation[p - 1]; if (permutation[end] > s) low = end; else { high = end; low = p; while (high > low + 1) { med = (high + low) >> 1; if (permutation[med] < s) high = med; else low = med; } } permutation[p - 1] = permutation[low]; permutation[low] = s; } high = end; while (high > p) { med = permutation[high]; permutation[high] = permutation[p]; permutation[p] = med; p++; high--; } return permutation; } /** * Returns the previous element in the iteration. * * @return the previous element in the iteration */ public int[] previous() { int Nm1 = size - 1; int p = Nm1, low, high, s, m; while ((p > 0) && (permutation[p] > permutation[p - 1])) p--; if (p > 0) { s = permutation[p - 1]; if (permutation[Nm1] < s) low = Nm1; else { high = Nm1; low = p; while (high > low + 1) { m = (high + low) >> 1; if (permutation[m] > s) high = m; else low = m; } } permutation[p - 1] = permutation[low]; permutation[low] = s; } high = Nm1; while (high > p) { m = permutation[high]; permutation[high] = permutation[p]; permutation[p] = m; p++; high--; } return permutation; } @Override public void reset() { onFirst = true; for (int i = 0; i < size; ++i) permutation[i] = i; } /** * @throws UnsupportedOperationException always */ @Override public void remove() { throw new UnsupportedOperationException("Not supported yet."); } /** * Returns dimension specified in the constructor * * @return dimension specified in the constructor */ public int getDimension() { return size; } @Override public int[] current() { return permutation; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy