/**
* jcombinatorics:
* Java Combinatorics Library
*
* Copyright (c) 2009 by Alistair A. Israel.
*
* This software is made available under the terms of the MIT License.
* See LICENSE.txt.
*
* Created Sep 2, 2009
*/
package org.activityinfo.core.shared.importing.match.names;
/**
* <p>
* An iterator that enumerates <code>P(n,k)</code>, or all permutations of
* <code>n</code> taken <code>k</code> at a time in lexicographic order. Derived
* from the SEPA P(n) iterator.
* </p>
*
* @author Alistair A. Israel, Java Combinatorics Library
* @see <a href="https://github.com/AlistairIsrael/jcombinatorics/blob/7af141f9e48e09ada3d6bde2f038fd71013ba7d4/src/main/java/jcombinatorics/permutations/SepaPnIterator.java">
* Original Source</a>
*/
public final class PartialPermutations {
/**
* Initializes an array {@code a} with the first permutation in a lexicographic sequence.
*
* Fills the given array with a[i] = i. For example, if a = int[4], then
* fills <code>a</code> with <code>{ 0, 1, 2, 3 }</code>.
*
* @param a an array
* @param n the length of the partial permutation
*/
public static void first(final int[] a, int n) {
for (int i = n - 1; i >= 0; --i) {
a[i] = i;
}
}
public static int[] identity(int n) {
int[] a = new int[n];
first(a, n);
return a;
}
/**
* Computes the next partial permutation P(n, k) in a lexicographic
* sequence of partial permutations.
* @param a an array of length >= {@code n} holding the current permutation.
* @param n the number of elements
* @param k taken k at a time
*/
public static boolean next(int[] a, int n, int k) {
assert a.length >= n : "a must have a length >= n";
int i = k - 1;
int j = k;
// find smallest j > k - 1 where a[j] > a[k - 1]
while (j < n && a[i] >= a[j]) {
++j;
}
if (j < n) {
swap(a, i, j);
} else {
reverseRightOf(a, i, n);
// i = (k - 1) - 1
--i;
while (i >= 0 && a[i] >= a[i + 1]) {
--i;
}
if (i < 0) {
return false;
}
// j = n - 1
--j;
while (j > i && a[i] >= a[j]) {
--j;
}
swap(a, i, j);
reverseRightOf(a, i, n);
}
return true;
}
/**
* Reverse the order of elements from <code>a[start + 1]..a[n-1]</code>.
*
* @param a
* @param start the starting element
* @param n the number of elements, {@code >= k}
*/
private static void reverseRightOf(int[] a, final int start, int n) {
int i = start + 1;
int j = n - 1;
while (i < j) {
swap(a, i, j);
++i;
--j;
}
}
/**
* Swaps two elements in an array
*
* @param a
* @param x first position
* @param y second position
*/
private static void swap(int[] a, final int x, final int y) {
final int t = a[x];
a[x] = a[y];
a[y] = t;
}
}