Listing all permutations of a string/integer

Viewed 211304

A common task in programming interviews (not from my experience of interviews though) is to take a string or an integer and list every possible permutation.

Is there an example of how this is done and the logic behind solving such a problem?

I've seen a few code snippets but they weren't well commented/explained and thus hard to follow.

28 Answers

First of all: it smells like recursion of course!

Since you also wanted to know the principle, I did my best to explain it human language. I think recursion is very easy most of the times. You only have to grasp two steps:

  1. The first step
  2. All the other steps (all with the same logic)

In human language:

In short:

  1. The permutation of 1 element is one element.
  2. The permutation of a set of elements is a list each of the elements, concatenated with every permutation of the other elements.

Example:

If the set just has one element -->
return it.
perm(a) -> a

If the set has two characters: for each element in it: return the element, with the permutation of the rest of the elements added, like so:

perm(ab) ->

a + perm(b) -> ab

b + perm(a) -> ba

Further: for each character in the set: return a character, concatenated with a permutation of > the rest of the set

perm(abc) ->

a + perm(bc) --> abc, acb

b + perm(ac) --> bac, bca

c + perm(ab) --> cab, cba

perm(abc...z) -->

a + perm(...), b + perm(....)
....

I found the pseudocode on http://www.programmersheaven.com/mb/Algorithms/369713/369713/permutation-algorithm-help/:

makePermutations(permutation) {
  if (length permutation < required length) {
    for (i = min digit to max digit) {
      if (i not in permutation) {
        makePermutations(permutation+i)
      }
    }
  }
  else {
    add permutation to list
  }
}

C#

OK, and something more elaborate (and since it is tagged c #), from http://radio.weblogs.com/0111551/stories/2002/10/14/permutations.html : Rather lengthy, but I decided to copy it anyway, so the post is not dependent on the original.

The function takes a string of characters, and writes down every possible permutation of that exact string, so for example, if "ABC" has been supplied, should spill out:

ABC, ACB, BAC, BCA, CAB, CBA.

Code:

class Program
{
    private static void Swap(ref char a, ref char b)
    {
        if (a == b) return;

        var temp = a;
        a = b;
        b = temp;
    }

    public static void GetPer(char[] list)
    {
        int x = list.Length - 1;
        GetPer(list, 0, x);
    }

    private static void GetPer(char[] list, int k, int m)
    {
        if (k == m)
        {
            Console.Write(list);
        }
        else
            for (int i = k; i <= m; i++)
            {
                   Swap(ref list[k], ref list[i]);
                   GetPer(list, k + 1, m);
                   Swap(ref list[k], ref list[i]);
            }
    }

    static void Main()
    {
        string str = "sagiv";
        char[] arr = str.ToCharArray();
        GetPer(arr);
    }
}
class Program
{
    public static void Main(string[] args)
    {
        Permutation("abc");
    }

    static void Permutation(string rest, string prefix = "")
    {
        if (string.IsNullOrEmpty(rest)) Console.WriteLine(prefix);

        // Each letter has a chance to be permutated
        for (int i = 0; i < rest.Length; i++)
        {                
            Permutation(rest.Remove(i, 1), prefix + rest[i]);
        }
    }
}

First of all, sets have permutations, not strings or integers, so I'll just assume you mean "the set of characters in a string."

Note that a set of size n has n! n-permutations.

The following pseudocode (from Wikipedia), called with k = 1...n! will give all the permutations:

function permutation(k, s) {
    for j = 2 to length(s) {
        swap s[(k mod j) + 1] with s[j]; // note that our array is indexed starting at 1
        k := k / j; // integer division cuts off the remainder
    }
    return s;
}

Here's the equivalent Python code (for 0-based array indexes):

def permutation(k, s):
    r = s[:]
    for j in range(2, len(s)+1):
        r[j-1], r[k%j] = r[k%j], r[j-1]
        k = k/j+1
    return r

Here's a purely functional F# implementation:


let factorial i =
    let rec fact n x =
        match n with
        | 0 -> 1
        | 1 -> x
        | _ -> fact (n-1) (x*n)
    fact i 1

let swap (arr:'a array) i j = [| for k in 0..(arr.Length-1) -> if k = i then arr.[j] elif k = j then arr.[i] else arr.[k] |]

let rec permutation (k:int,j:int) (r:'a array) =
    if j = (r.Length + 1) then r
    else permutation (k/j+1, j+1) (swap r (j-1) (k%j))

let permutations (source:'a array) = seq { for k = 0 to (source |> Array.length |> factorial) - 1 do yield permutation (k,2) source }

Performance can be greatly improved by changing swap to take advantage of the mutable nature of CLR arrays, but this implementation is thread safe with regards to the source array and that may be desirable in some contexts. Also, for arrays with more than 16 elements int must be replaced with types with greater/arbitrary precision as factorial 17 results in an int32 overflow.

Here is a simple solution in c# using recursion,

void Main()
{
    string word = "abc";
    WordPermuatation("",word);
}

void WordPermuatation(string prefix, string word)
{
    int n = word.Length;
    if (n == 0) { Console.WriteLine(prefix); }
    else
    {
        for (int i = 0; i < n; i++)
        {
            WordPermuatation(prefix + word[i],word.Substring(0, i) + word.Substring(i + 1, n - (i+1)));
        }
    }
}

Building on @Peter's solution, here's a version that declares a simple LINQ-style Permutations() extension method that works on any IEnumerable<T>.

Usage (on string characters example):

foreach (var permutation in "abc".Permutations())
{
    Console.WriteLine(string.Join(", ", permutation));
}

Outputs:

a, b, c
a, c, b
b, a, c
b, c, a
c, b, a
c, a, b

Or on any other collection type:

foreach (var permutation in (new[] { "Apples", "Oranges", "Pears"}).Permutations())
{
    Console.WriteLine(string.Join(", ", permutation));
}

Outputs:

Apples, Oranges, Pears
Apples, Pears, Oranges
Oranges, Apples, Pears
Oranges, Pears, Apples
Pears, Oranges, Apples
Pears, Apples, Oranges
using System;
using System.Collections.Generic;
using System.Linq;

public static class PermutationExtension
{
    public static IEnumerable<T[]> Permutations<T>(this IEnumerable<T> source)
    {
        var sourceArray = source.ToArray();
        var results = new List<T[]>();
        Permute(sourceArray, 0, sourceArray.Length - 1, results);
        return results;
    }

    private static void Swap<T>(ref T a, ref T b)
    {
        T tmp = a;
        a = b;
        b = tmp;
    }

    private static void Permute<T>(T[] elements, int recursionDepth, int maxDepth, ICollection<T[]> results)
    {
        if (recursionDepth == maxDepth)
        {
            results.Add(elements.ToArray());
            return;
        }

        for (var i = recursionDepth; i <= maxDepth; i++)
        {
            Swap(ref elements[recursionDepth], ref elements[i]);
            Permute(elements, recursionDepth + 1, maxDepth, results);
            Swap(ref elements[recursionDepth], ref elements[i]);
        }
    }
}

Base/Revise on Pengyang answer

And inspired from permutations-in-javascript

The c# version FunctionalPermutations should be this

static IEnumerable<IEnumerable<T>> FunctionalPermutations<T>(IEnumerable<T> elements, int length)
    {
        if (length < 2) return elements.Select(t => new T[] { t });
        /* Pengyang answser..
          return _recur_(list, length - 1).SelectMany(t => list.Where(e => !t.Contains(e)),(t1, t2) => t1.Concat(new T[] { t2 }));
        */
        return elements.SelectMany((element_i, i) => 
          FunctionalPermutations(elements.Take(i).Concat(elements.Skip(i + 1)), length - 1)
            .Select(sub_ei => new[] { element_i }.Concat(sub_ei)));
    }

I hope this will suffice:

using System;
                
public class Program
{
    public static void Main()
    {
        //Example using word cat
        permute("cat");
    
    }

static void permute(string word){
    for(int i=0; i < word.Length; i++){
        char start = word[0];
        for(int j=1; j < word.Length; j++){
            string left = word.Substring(1,j-1);
            string right = word.Substring(j);
            Console.WriteLine(start+right+left);
        }
        if(i+1 < word.Length){
            word = wordChange(word, i + 1);
        }
            
    }
}

static string wordChange(string word, int index){
    string newWord = "";
    for(int i=0; i<word.Length; i++){
        if(i== 0)
            newWord += word[index];
        else if(i== index)
            newWord += word[0];
        else
            newWord += word[i];
    }
    return newWord;
}

output:

cat
cta
act
atc
tca
tac

Here's another appraoch that is slighly more generic.

void Main()
{
    var perms = new Permutations<char>("abc");
    perms.Generate();
}


class Permutations<T> {
    
    private List<T> permutation = new List<T>();
    HashSet<T> chosen;
    
    int n;
    List<T> sequence;
    
    public Permutations(IEnumerable<T> sequence)
    {
        this.sequence = sequence.ToList();
        this.n = this.sequence.Count;
        chosen = new HashSet<T>();
        
    }
    
    public void Generate()
    {
        if(permutation.Count == n) {
            Console.WriteLine(string.Join(",",permutation));
        } 
        else 
        {
            foreach(var elem in sequence)
            {
                if(chosen.Contains(elem)) continue;
                chosen.Add(elem);
                permutation.Add(elem);
                Generate();
                chosen.Remove(elem);
                permutation.Remove(elem);
            }
        }
    }
}
Related