class RecursivePermuter {
/** Returns the set of permutations formed by adding item to perm at every
* possible distinct index of perm, i.e. at 0, ..., perm.length.
*/
private static Object[][] combine(final Object[] perm, final Object item) {
final int dim = perm.length + 1;
final Object[][] derivatives = new Object[dim][dim];
for (int i = 0; i < dim; ++i) {
Object[] derivative = derivatives[i];
for (int j = 0, k = 0; j < dim; ++j) {
if (i == j) {
derivative[j] = item;
}
else {
derivative[j] = perm[k];
k = k + 1;
}
}
}
return derivatives;
}
/** Returns a copy of array with the element at index removeAt removed.
*/
private static Object[] reduce(final Object[] array, final int removeAt) {
final int n = array.length - 1;
Object[] smaller = new Object[n];
for (int i = 0, j = 0; i < n; ++i, ++j) {
if (i == removeAt) ++j;
smaller[i] = array[j];
}
return smaller;
}
/** Returns a grid (an array of arrays) consisting of all permutations of array.
*/
public static Object[][] permute(final Object[] array) {
/* I. If "Base Case", return the answer. */
// If the problem can't get any smaller, return the
// answer to the trivial problelm.
if (array.length == 0) return new Object[1][0];
/* II. Else NOT Base Case, so... */
/* II-A. Reduce the size of the problem. */
// Create a smaller problem by removing an element
// from array. (We can remove an element at any valid
// index; however, zero is the only constant, always-
// valid index.)
final int removeAt = 0;
Object removed = array[removeAt];
Object[] smallerArray = reduce(array, removeAt);
/* II-B. Solve the smaller problem recursively. */
Object[][] smallAnswer = permute(smallerArray);
/* II-C. Combine results. */
// Allocate space for the final answer.
final int smallPermLength = smallAnswer[0].length;
final int smallPermCount = smallAnswer.length;
int n = smallPermCount * (smallPermLength + 1);
final Object[][] grid = new Object[n][];
// For each permutation in the solution to the smaller
// problem, combine the removed element with the
// permutation and combine the resulting permutations.
for (Object[] smallPerm : smallAnswer) {
for (Object[] newPerm : combine(smallPerm, removed))
grid[--n] = newPerm;
}
return grid;
}
}
public class Permuter {
public static void main(String args[]) {
Object[][] perms = RecursivePermuter.permute(args);
for (Object[] row : perms) {
for (Object element : row) {
System.out.print(element);
System.out.print(" ");
}
System.out.println();
}
}
}