Permutation

Published: May 24, 2016

Well, how bad naive implementation of generating permutation? Permutation is a well-known problem in mathematics as well as programming. If a set of three characters, {A, B, C}, its permutation is:

ABC, ACB, BAC, BCA, CAB, CBA

Three characters generate six patterns, which is 3*2*1, a factorial of its size.

The easiest implementation is a brute-force, recursing all. How many times will it repeat? The answer is a factorial of total number of given characters. Crap! In terms of Big-O complexity, the factorial is the worst. See Big-O Complexitiy Chart at Big-O Cheat Sheet. To generate only 10 letters of permutation, 3628800 times repetition must be done.

How to effectively find permutation

This is a famous problem, so it’s easy to find the solution for “how to effectively find/generate permutation.” As far as I googled, these three were the best.

Overall, above three take the same approach. The trick is lexicographical order. The lexicographical order is not the goal but is the way to effectively generates permutations. Above three use the lexicographical order to find next permutations one by one. When there’s no next permutation, all permutations are generated.

Permutation generation code

Steps of the algorithm are:

  1. (optional) sort given string or array
  2. find longest non-increasing suffix such that array[index] <= array[index+1]
  3. identify the pivot index such that the first array[index] > array[index+1]
  4. find the ceil (successor), the right most index such that array[pivot] < array[succ]
  5. swap the pivot and successor, array[pivot] and array[succ]
  6. reverse the suffix from array[pivot+1] to array[array.length-1] if the array has been sorted at step 1, sort suffix instead of reversing

The sorted version of permutation in Java will be something like this:

import java.util.Arrays;

public class AllPermutations {
    static void sortedPermutations(char[] array) {
        Arrays.parallelSort(array);
        boolean isFinished = false;
        int count = 0;
        while (!isFinished) {
            if (count !=0 && count % 10 == 0) System.out.println();
            System.out.print((new String(array)) + " "); count++;

            int index = array.length-2;
            // find non-increasing suffix
            while(index >= 0) {
                if (array[index] <= array[index+1]) break;
                index--;
            }
            if (index == -1) {
                isFinished = true;
            } else {
                // the pivot is array[index]
                // find the rightmost successor to the pivot in suffix
                int succ = array.length-1;
                while(array[succ] <= array[index]) succ--;
                // swap the pivot and successor
                char tmp = array[index];
                array[index] = array[succ];
                array[succ] = tmp;
                // sort suffix
                Arrays.parallelSort(array, index+1, array.length);
            }
        }
    }

    public static void main(String[] args) {
      sortedPermutations("ABCDE".toCharArray());
    }
}

The above code prints:

ABCDE ABCED ABDCE ABDEC ABECD ABEDC ACBDE ACBED ACDBE ACDEB
ACEBD ACEDB ADBCE ADBEC ADCBE ADCEB ADEBC ADECB AEBCD AEBDC
AECBD AECDB AEDBC AEDCB BACDE BACED BADCE BADEC BAECD BAEDC
BCADE BCAED BCDAE BCDEA BCEAD BCEDA BDACE BDAEC BDCAE BDCEA
BDEAC BDECA BEACD BEADC BECAD BECDA BEDAC BEDCA CABDE CABED
CADBE CADEB CAEBD CAEDB CBADE CBAED CBDAE CBDEA CBEAD CBEDA
CDABE CDAEB CDBAE CDBEA CDEAB CDEBA CEABD CEADB CEBAD CEBDA
CEDAB CEDBA DABCE DABEC DACBE DACEB DAEBC DAECB DBACE DBAEC
DBCAE DBCEA DBEAC DBECA DCABE DCAEB DCBAE DCBEA DCEAB DCEBA
DEABC DEACB DEBAC DEBCA DECAB DECBA EABCD EABDC EACBD EACDB
EADBC EADCB EBACD EBADC EBCAD EBCDA EBDAC EBDCA ECABD ECADB
ECBAD ECBDA ECDAB ECDBA EDABC EDACB EDBAC EDBCA EDCAB EDCBA 

Latest Posts

Vite + Vue + Bun on Rails

Vue.js is one of frontend frameworks gaining popularity among rapidly emerging JavaScript technologies. The combination of Vue.js and Rails is becoming more popular as well, however, Vue.js development on Rails is not so straightforward. The reason would be that Vue.js relies on Vite for a development environment such as HMR (Hot Module Replacement) and bundling.

Bun + React on Rails

In the frontend world, new technologies keep emerging rapidly these years. Still, React is a well-established and very popular frontend framework, Vue.js, Svelte, Astro and more frameworks are gaining popularity. Not just the frameworks, tools for a transpiler/bundler or sort are also under a rapid development. In JavaScript domain, esbuild, rollup, vite and some more are out.

Ruby on Rails Secrets Management

A web application needs various kinds of values, params and etc which should not be revealed to the public, say GitHub repo. For example, API keys, tokens, passwords, and endpoints, all those should be kept secret. Another important factor is that such secrets should be shared among the team members. Additionally, all those secrets should come along with the deployment.