/*
* 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 all unordered combinations (i.e. [0,1] and [1,0] are
* considered as same, so only [0,1] will appear in the sequence) 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 is a
* binomial coefficient {@code n!/(k!(n-k)!)}. Each returned array is sorted.
*
* 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.
* So, if it is needed not only to obtain the information from {@link #next()}, but also save the result,
* it is necessary to clone the returned array.
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
* @since 1.0
*/
public final class IntCombinationsGenerator
extends IntCombinatorialGenerator
implements IntCombinatorialPort {
final int[] combination;
private final int n, k;
private boolean onFirst = true;
public IntCombinationsGenerator(int n, int k) {
if (n < k)
throw new IllegalArgumentException(" n < k ");
this.n = n;
this.k = k;
this.combination = new int[k];
reset();
}
@Override
public int[] take() {
return hasNext() ? next() : null;
}
@Override
public boolean hasNext() {
return onFirst || !isLast();
}
@Override
public void reset() {
onFirst = true;
for (int i = 0; i < k; ++i)
combination[i] = i;
}
private boolean isLast() {
for (int i = 0; i < k; ++i)
if (combination[i] != i + n - k)
return false;
return true;
}
@Override
public int[] next() {
if (onFirst)
onFirst = false;
else {
int i;
for (i = k - 1; i >= 0; --i)
if (combination[i] != i + n - k)
break;
int m = ++combination[i++];
for (; i < k; ++i)
combination[i] = ++m;
}
return combination;
}
/**
* @throws UnsupportedOperationException always
*/
@Override
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int[] getReference() {
return combination;
}
}
Ads help maintain this website.