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

io.github.deepeshpatel.jnumbertools.generator.permutation.k.KPermutationCombinationOrderMth Maven / Gradle / Ivy

Go to download

JNumberTools is the combinatorics and number-theory library which provides useful APIS related to said topics

The newest version!
/*
 * 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