
io.github.deepeshpatel.jnumbertools.generator.permutation.k.KPermutationCombinationOrderMth Maven / Gradle / Ivy
/*
* JNumberTools Library v1.0.3
* Copyright (c) 2022 Deepesh Patel ([email protected])
*/
package io.github.deepeshpatel.jnumbertools.generator.permutation.k;
import io.github.deepeshpatel.jnumbertools.base.Calculator;
import io.github.deepeshpatel.jnumbertools.base.Combinations;
import io.github.deepeshpatel.jnumbertools.base.Permutations;
import io.github.deepeshpatel.jnumbertools.generator.base.AbstractGenerator;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.List;
/**
* Implements the iterable generating every nth unique permutation of size k.
* Permutations are generated in lex order of combinations of indices of input values, considering value at each index as unique.
* Instance of this class is intended to be created via builder and hence do not have any public constructor.
* @author Deepesh Patel
*/
public final class KPermutationCombinationOrderMth extends AbstractKPermutation {
final BigInteger totalPermutations;
final long permutationsPerList;
final BigInteger increment;
final BigInteger start;
private final Calculator calculator;
/**
* Implements the iterable generating every nth unique permutation of size k.
* Permutations are generated in lex order of indices of input values, considering value at each index as unique.
* @param elements Input of size n from which permutations of size k will be generated
* @param k size of permutations. k must be <=n
* @param increment position relative to first permutation which will be generated next in lexicographical order.
* generating every 'increment' permutation in a sequence.
* For example, if increment is set to 2, the output will generate 0th, 2nd,
* 4th.. permutations.
* This is important because for large k, it is impractical to generate all possible k! permutations
* and then increment to the desired position
*/
KPermutationCombinationOrderMth(List elements, int k, BigInteger increment, BigInteger start, Calculator calculator) {
super(elements, k);
AbstractGenerator.checkParamIncrement(increment, "mth K-Permutation");
this.start = start;
this.increment = increment;
this.totalPermutations = calculator.nPr(elements.size(), k);
this. permutationsPerList = calculator.factorial(k).longValue();
this.calculator = calculator;
}
@Override
public Iterator> iterator() {
return ( k==0 || elements.isEmpty()) ? newEmptyIterator() : new Itr();
}
private class Itr implements Iterator> {
BigInteger currentIncrement = start;
public Itr() {
}
@Override
public boolean hasNext() {
return currentIncrement.compareTo(totalPermutations) < 0;
}
@Override
public List next() {
BigInteger[] divideAndRemainder = currentIncrement.divideAndRemainder(BigInteger.valueOf(permutationsPerList));
BigInteger combinationListNumber = divideAndRemainder[0];
long permutationIncrement = divideAndRemainder[1].longValue();
currentIncrement = currentIncrement.add(increment);
List next = combinationListNumber.equals(BigInteger.ZERO) ?
new Combinations(calculator).unique(k,elements).lexOrder().iterator().next() :
new Combinations(calculator).unique(k, elements).lexOrderMth(combinationListNumber, BigInteger.ZERO).build();
return permutationIncrement == 0 ?
new Permutations(calculator).unique(next).lexOrder().iterator().next() :
new Permutations(calculator).unique(next).lexOrderMth(permutationIncrement,0).build();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy