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(); } } }