/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2015:
* Stanislav Poslavsky
* Bolotin Dmitriy
*
* This file is part of Redberry.
*
* Redberry 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.
*
* Redberry 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 Redberry. If not, see .
*/
package cc.redberry.core.combinatorics;
/**
* This class represents an iterator over over all possible unique
* combinations with permutations (i.e. {0,1} and {1,0} both will appear in the iteration) of {@code k} numbers, which
* can be chosen from the set of {@code n} numbers (0,1,2,...,{@code n}). The total number of such combinations will be
* {@code n!/(n-k)!}.
*
* For example, for {@code k=2} and {@code n=3}, it will produce
* the following arrays sequence: [0,1], [1,0], [0,2], [2,0], [1,2],
* [2,1].
*
* The iterator is implemented such that each next combination will be calculated only on
* the invocation of method {@link #next()} (no pre-calculation of results).
*
* Note: method {@link #next()} returns the same reference on each invocation.
* So, if it is needed not only to obtain the information from {@link #next()}, but also to save the result,
* it is necessary to clone the returned array!
*
* Inner implementation of this class is simply uses the combination of {@link IntCombinationsGenerator}
* and {@link IntPermutationsGenerator}.
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
* @see IntCombinationsGenerator
* @see IntPermutationsGenerator
* @since 1.0
*/
public final class IntCombinationPermutationGenerator
extends IntCombinatorialGenerator
implements IntCombinatorialPort {
private final int[] permutation, combination;
final int[] combinationPermutation;
private final IntPermutationsGenerator permutationsGenerator;
private final IntCombinationsGenerator combinationsGenerator;
private final int k;
public IntCombinationPermutationGenerator(int n, int k) {
this.k = k;
this.combinationsGenerator = new IntCombinationsGenerator(n, k);
this.combination = this.combinationsGenerator.combination;
this.permutationsGenerator = new IntPermutationsGenerator(k);
this.permutation = this.permutationsGenerator.permutation;
this.combinationPermutation = new int[k];
combinationsGenerator.next();
System.arraycopy(combination, 0, combinationPermutation, 0, k);
}
@Override
public int[] take() {
return hasNext() ? next() : null;
}
@Override
public boolean hasNext() {
return combinationsGenerator.hasNext() || permutationsGenerator.hasNext();
}
/**
* Calculates and returns the next combination.
*
* @return the next combination
*/
@Override
public int[] next() {
if (!permutationsGenerator.hasNext()) {
permutationsGenerator.reset();
combinationsGenerator.next();
}
permutationsGenerator.next();
for (int i = 0; i < k; ++i)
combinationPermutation[i] = combination[permutation[i]];
return combinationPermutation;
}
/**
* Throws UnsupportedOperationException.
*/
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public void reset() {
permutationsGenerator.reset();
combinationsGenerator.reset();
combinationsGenerator.next();
}
@Override
public int[] getReference() {
return combinationPermutation;
}
}
Ads help maintain this website.