Listing all permutations of a string/integer
Asked Answered
P

29

198

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.

Pallaton answered 16/4, 2009 at 13:13 Comment(1)
Here is a question to Permutations with some good explaining answers, including a graph, but not in C#.Anthelmintic
C
185

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);
    }
}
Clougher answered 16/4, 2009 at 13:22 Comment(7)
For a bit more clarity, I would call k "recursionDepth" and call m "maxDepth".Mesognathous
The 2nd swap (Swap(ref list[k], ref list[i]);) is unncessary.Wingding
Thank you for this solution. I created this fiddle (dotnetfiddle.net/oTzihw) from it (with proper naming instead of k and m). As far as I understand the algo, the second Swap is required (to backtrack) since you edit the original array in-place.Bravery
a minor point: It looks like the Swap method is better to be implemented with a temporary buffer variable and not using XORs (dotnetperls.com/swap)Veterinarian
This is not working when repeated characters are there. How to avoid duplication when characters are repeated in String.Amoeboid
Using C# 7 tuples you can make the swap a lot more elegant: (a[x], a[y]) = (a[y], a[x]);Comparison
Can this technique be modified to find all the permutations of any length of the characters in a string ?Solingen
C
103

It's just two lines of code if LINQ is allowed to use. Please see my answer here.

EDIT

Here is my generic function which can return all the permutations (not combinations) from a list of T:

static IEnumerable<IEnumerable<T>>
    GetPermutations<T>(IEnumerable<T> list, int length)
{
    if (length == 1) return list.Select(t => new T[] { t });

    return GetPermutations(list, length - 1)
        .SelectMany(t => list.Where(e => !t.Contains(e)),
            (t1, t2) => t1.Concat(new T[] { t2 }));
}

Example:

IEnumerable<IEnumerable<int>> result =
    GetPermutations(Enumerable.Range(1, 3), 3);

Output - a list of integer-lists:

{1,2,3} {1,3,2} {2,1,3} {2,3,1} {3,1,2} {3,2,1}

As this function uses LINQ so it requires .net 3.5 or higher.

Curvaceous answered 17/5, 2012 at 4:54 Comment(10)
combinations and permutations are different things. it's similar, but your answer there seems to be answering a different problem than all the permutations of a set of elements.Oubre
@ShawnKovac, thanks for pointing this out! I've updated my code from combination to permutation.Curvaceous
@Curvaceous I looked at your other answer and I will say that this helped me a great deal but I have another situation that I don't know if you pointed out the correct way of solving it. I wanted to find all permutations of a word like 'HALLOWEEN' but found that I also want to include both 'L's and both 'E's in the result set. In my iterations I loop over your method giving increased length with each iteration(length++) and would expect that given the full length of the word HALLOWEEN (9 chars) I would get results 9 chars long... but this is not the case: I only get 7 (1 L and 1 E are omitted)Kolyma
I would also like to point out that I DON'T want a situation where I see 9 'H's as 'H' only appears once in the word.Kolyma
@Kolyma This function requires the elements to be unique. Try this: const string s = "HALLOWEEN"; var result = GetPermutations(Enumerable.Range(0, s.Length), s.Length).Select(t => t.Select(i => s[i]));Curvaceous
This answer expanded my horizons on what is possible with LINQ. Thanks!Melee
When the list contains any duplicate elements, this just returns an empty IEnumerable. @Najera solution works with duplicates, but you get a constant total count (perm 1 selects the first E, perm 2 selects the second E, etc) meaning duplicates in the outputHydrobomb
While I am a fan of LINQ myself, I'm afraid this solution has a horrible performance. This may be caused by lazy evaluation or all the iterator overhead, I don't know, but I did a few time measures comparing this solution to Yurik's implementation and his one was around factor 40 faster.Atticism
PS: Measuring code, ran a few times in csi: var watch = new Stopwatch(); watch.Start(); for (int i = 0; i < 10; i++) GeneratePermutations(Enumerable.Range(1, 8).ToArray(), 0).ToList(); watch.Stop(); watch.ElapsedMillisecondsAtticism
@Atticism There's a good reason for that. Yurik's implementation isn't creating a new array for each permutation, it's returning the same array each time after having modified it. This means it breaks if you try to use something like .ToArray() on it. In Pengyang's version you have to do .Select(v => v.ToArray()).ToArray() instead, but it does work as intended.Hagioscope
W
47

Here I have found the solution. It was written in Java, but I have converted it to C#. I hope it will help you.

Enter image description here

Here's the code in C#:

static void Main(string[] args)
{
    string str = "ABC";
    char[] charArry = str.ToCharArray();
    Permute(charArry, 0, 2);
    Console.ReadKey();
}

static void Permute(char[] arry, int i, int n)
{
    int j;
    if (i==n)
        Console.WriteLine(arry);
    else
    {
        for(j = i; j <=n; j++)
        {
            Swap(ref arry[i],ref arry[j]);
            Permute(arry,i+1,n);
            Swap(ref arry[i], ref arry[j]); //backtrack
        }
    }
}

static void Swap(ref char a, ref char b)
{
    char tmp;
    tmp = a;
    a=b;
    b = tmp;
}
Woolpack answered 18/2, 2014 at 3:11 Comment(2)
Is it ported from another language? Definitely +1 for the image, because it really adds value. However, the code itself seems to have a certain improvement potential. Some minor parts aren't needed but most importantly, I'm getting this C++ feeling when we send in something and do stuff to it instead of providing in-parameters and fetching a returned value. In fact, I used your image to implement a C#-styled C# code (style being my personal perception, of course), and it aided me greatly, so when I'll post it I'll definitely steal it from you (and credit you for it).Audryaudrye
C# supports swapping like Python since its introduction of tuples.Britten
D
23

Recursion is not necessary, here is good information about this solution.

var values1 = new[] { 1, 2, 3, 4, 5 };

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

var values2 = new[] { 'a', 'b', 'c', 'd', 'e' };

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

Console.ReadLine();

I have been used this algorithm for years, it has O(N) time and space complexity to calculate each permutation.

public static class SomeExtensions
{
    public static IEnumerable<IEnumerable<T>> GetPermutations<T>(this IEnumerable<T> enumerable)
    {
        var array = enumerable as T[] ?? enumerable.ToArray();

        var factorials = Enumerable.Range(0, array.Length + 1)
            .Select(Factorial)
            .ToArray();

        for (var i = 0L; i < factorials[array.Length]; i++)
        {
            var sequence = GenerateSequence(i, array.Length - 1, factorials);

            yield return GeneratePermutation(array, sequence);
        }
    }

    private static IEnumerable<T> GeneratePermutation<T>(T[] array, IReadOnlyList<int> sequence)
    {
        var clone = (T[]) array.Clone();

        for (int i = 0; i < clone.Length - 1; i++)
        {
            Swap(ref clone[i], ref clone[i + sequence[i]]);
        }

        return clone;
    }

    private static int[] GenerateSequence(long number, int size, IReadOnlyList<long> factorials)
    {
        var sequence = new int[size];

        for (var j = 0; j < sequence.Length; j++)
        {
            var facto = factorials[sequence.Length - j];

            sequence[j] = (int)(number / facto);
            number = (int)(number % facto);
        }

        return sequence;
    }

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

    private static long Factorial(int n)
    {
        long result = n;

        for (int i = 1; i < n; i++)
        {
            result = result * i;
        }

        return result;
    }
}
Delft answered 12/9, 2015 at 23:47 Comment(3)
Works out of the box!Hujsak
maybe I don't understand O(n) notation. doesn't the N refer to how many "inner loops" are necessary to make your algorithm work? seems to me like if you have N numbers, it seems like it's O(N * N!) (because N! times it has to do N swaps). Plus, it has to do a ton of array copying. This code is "neat", but I wouldn't use it.Ransack
@ericfrazer Each permutation only uses one array copy, and O(N-1) for the sequence and O(N) for the swaps, which is O(N). And I'm still using this in production but with a refactor to generate only one permutation like: GetPermutation(i) where 0 <= i <= N!-1. I will be happy to use something with better performance than this, so be free to call a reference for something better, the most of the alternatives uses O(N!) in memory so you might check that too.Delft
A
16
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]);
        }
    }
}
Apocopate answered 7/5, 2018 at 17:23 Comment(0)
L
14

Slightly modified version in C# that yields needed permutations in an array of ANY type.

    // USAGE: create an array of any type, and call Permutations()
    var vals = new[] {"a", "bb", "ccc"};
    foreach (var v in Permutations(vals))
        Console.WriteLine(string.Join(",", v)); // Print values separated by comma


public static IEnumerable<T[]> Permutations<T>(T[] values, int fromInd = 0)
{
    if (fromInd + 1 == values.Length)
        yield return values;
    else
    {
        foreach (var v in Permutations(values, fromInd + 1))
            yield return v;

        for (var i = fromInd + 1; i < values.Length; i++)
        {
            SwapValues(values, fromInd, i);
            foreach (var v in Permutations(values, fromInd + 1))
                yield return v;
            SwapValues(values, fromInd, i);
        }
    }
}

private static void SwapValues<T>(T[] values, int pos1, int pos2)
{
    if (pos1 != pos2)
    {
        T tmp = values[pos1];
        values[pos1] = values[pos2];
        values[pos2] = tmp;
    }
}
Laky answered 23/10, 2012 at 0:44 Comment(2)
One slight caveat with this implementation: it only works properly if you don't attempt to store the enumeration value. If you try to do something like Permutations(vals).ToArray() then you end up with N references to the same array. If you want to be able to store the results you have to manually create a copy. E.g. Permutations(values).Select(v => (T[])v.Clone())Hagioscope
I have tested this approach on very big permutations (tens of millions). It does require a very careful use. It totally outperforms other solutions in both speed and memory usage.Purposive
D
9

I liked FBryant87 approach since it's simple. Unfortunately, it does like many other "solutions" not offer all permutations or of e.g. an integer if it contains the same digit more than once. Take 656123 as an example. The line:

var tail = chars.Except(new List<char>(){c});

using Except will cause all occurrences to be removed, i.e. when c = 6, two digits are removed and we are left with e.g. 5123. Since none of the solutions I tried solved this, I decided to try and solve it myself by FBryant87's code as base. This is what I came up with:

private static List<string> FindPermutations(string set)
    {
        var output = new List<string>();
        if (set.Length == 1)
        {
            output.Add(set);
        }
        else
        {
            foreach (var c in set)
            {
                // Remove one occurrence of the char (not all)
                var tail = set.Remove(set.IndexOf(c), 1);
                foreach (var tailPerms in FindPermutations(tail))
                {
                    output.Add(c + tailPerms);
                }
            }
        }
        return output;
    }

I simply just remove the first found occurrence using .Remove and .IndexOf. Seems to work as intended for my usage at least. I'm sure it could be made cleverer.

One thing to note though: The resulting list may contain duplicates, so make sure you either make the method return e.g. a HashSet instead or remove the duplicates after the return using any method you like.

Dearman answered 18/5, 2015 at 20:23 Comment(1)
Works like an absolute beauty, first I've found that handles duplicate characters +1Albuminoid
G
8

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
Guesstimate answered 16/4, 2009 at 13:25 Comment(1)
what language is this? the question is marked C#. i don't know what k := k / j; does.Oubre
P
6

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)));
        }
    }
}
Pean answered 20/10, 2016 at 15:16 Comment(0)
E
5

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.

Elegist answered 16/4, 2009 at 14:46 Comment(0)
A
5

Here is an easy to understand permutaion function for both string and integer as input. With this you can even set your output length(which in normal case it is equal to input length)

String

    static ICollection<string> result;

    public static ICollection<string> GetAllPermutations(string str, int outputLength)
    {
        result = new List<string>();
        MakePermutations(str.ToCharArray(), string.Empty, outputLength);
        return result;
    }

    private static void MakePermutations(
       char[] possibleArray,//all chars extracted from input
       string permutation,
       int outputLength//the length of output)
    {
         if (permutation.Length < outputLength)
         {
             for (int i = 0; i < possibleArray.Length; i++)
             {
                 var tempList = possibleArray.ToList<char>();
                 tempList.RemoveAt(i);
                 MakePermutations(tempList.ToArray(), 
                      string.Concat(permutation, possibleArray[i]), outputLength);
             }
         }
         else if (!result.Contains(permutation))
            result.Add(permutation);
    }

and for Integer just change the caller method and MakePermutations() remains untouched:

    public static ICollection<int> GetAllPermutations(int input, int outputLength)
    {
        result = new List<string>();
        MakePermutations(input.ToString().ToCharArray(), string.Empty, outputLength);
        return result.Select(m => int.Parse(m)).ToList<int>();
    }

example 1: GetAllPermutations("abc",3); "abc" "acb" "bac" "bca" "cab" "cba"

example 2: GetAllPermutations("abcd",2); "ab" "ac" "ad" "ba" "bc" "bd" "ca" "cb" "cd" "da" "db" "dc"

example 3: GetAllPermutations(486,2); 48 46 84 86 64 68

Abridge answered 4/7, 2016 at 0:50 Comment(1)
I like your solution because this is easy to understand, thank you for that! Yet I chose to go with that one: #756555. The reason being that ToList, ToArray and RemoveAt all have a time complexity of O(N). So basically you have to go over all the elements of the collection (see https://mcmap.net/q/82382/-linq-tolist-toarray-todictionary-performance). Same for the int where you basically go over all the elements again at the end to convert them to int. I agree that this doesn't have much impact for "abc" or 486 though.Bravery
H
4

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]);
        }
    }
}
Hyperopia answered 12/11, 2019 at 21:15 Comment(0)
L
2

Here is the function which will print all permutaion. This function implements logic Explained by peter.

public class Permutation
{
    //http://www.java2s.com/Tutorial/Java/0100__Class-Definition/RecursivemethodtofindallpermutationsofaString.htm

    public static void permuteString(String beginningString, String endingString)
    {           

        if (endingString.Length <= 1)
            Console.WriteLine(beginningString + endingString);
        else
            for (int i = 0; i < endingString.Length; i++)
            {

                String newString = endingString.Substring(0, i) + endingString.Substring(i + 1);

                permuteString(beginningString + endingString.ElementAt(i), newString);

            }
    }
}

    static void Main(string[] args)
    {

        Permutation.permuteString(String.Empty, "abc");
        Console.ReadLine();

    }
Lashandralashar answered 19/12, 2011 at 20:9 Comment(0)
W
2

The below is my implementation of permutation . Don't mind the variable names, as i was doing it for fun :)

class combinations
{
    static void Main()
    {

        string choice = "y";
        do
        {
            try
            {
                Console.WriteLine("Enter word :");
                string abc = Console.ReadLine().ToString();
                Console.WriteLine("Combinatins for word :");
                List<string> final = comb(abc);
                int count = 1;
                foreach (string s in final)
                {
                    Console.WriteLine("{0} --> {1}", count++, s);
                }
                Console.WriteLine("Do you wish to continue(y/n)?");
                choice = Console.ReadLine().ToString();
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc);
            }
        } while (choice == "y" || choice == "Y");
    }

    static string swap(string test)
    {
        return swap(0, 1, test);
    }

    static List<string> comb(string test)
    {
        List<string> sec = new List<string>();
        List<string> first = new List<string>();
        if (test.Length == 1) first.Add(test);
        else if (test.Length == 2) { first.Add(test); first.Add(swap(test)); }
        else if (test.Length > 2)
        {
            sec = generateWords(test);
            foreach (string s in sec)
            {
                string init = s.Substring(0, 1);
                string restOfbody = s.Substring(1, s.Length - 1);

                List<string> third = comb(restOfbody);
                foreach (string s1 in third)
                {
                    if (!first.Contains(init + s1)) first.Add(init + s1);
                }


            }
        }

        return first;
    }

    static string ShiftBack(string abc)
    {
        char[] arr = abc.ToCharArray();
        char temp = arr[0];
        string wrd = string.Empty;
        for (int i = 1; i < arr.Length; i++)
        {
            wrd += arr[i];
        }

        wrd += temp;
        return wrd;
    }

    static List<string> generateWords(string test)
    {
        List<string> final = new List<string>();
        if (test.Length == 1)
            final.Add(test);
        else
        {
            final.Add(test);
            string holdString = test;
            while (final.Count < test.Length)
            {
                holdString = ShiftBack(holdString);
                final.Add(holdString);
            }
        }

        return final;
    }

    static string swap(int currentPosition, int targetPosition, string temp)
    {
        char[] arr = temp.ToCharArray();
        char t = arr[currentPosition];
        arr[currentPosition] = arr[targetPosition];
        arr[targetPosition] = t;
        string word = string.Empty;
        for (int i = 0; i < arr.Length; i++)
        {
            word += arr[i];

        }

        return word;

    }
}
Weksler answered 22/9, 2012 at 8:29 Comment(0)
M
2

Here's a high level example I wrote which illustrates the human language explanation Peter gave:

    public List<string> FindPermutations(string input)
    {
        if (input.Length == 1)
            return new List<string> { input };
        var perms = new List<string>();
        foreach (var c in input)
        {
            var others = input.Remove(input.IndexOf(c), 1);
            perms.AddRange(FindPermutations(others).Select(perm => c + perm));
        }
        return perms;
    }
Millepore answered 19/8, 2014 at 15:8 Comment(2)
This solution is actually flawed in that if the string set contains any repeat characters, it will fail. For example, on the word 'test', the Except command will remove both instances of 't' instead of just the first and last when necessary.Remediless
@Remediless well spotted, fortunately hug has come up with a solution to address this.Millepore
A
2

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)));
    }
Arbour answered 10/10, 2020 at 10:59 Comment(0)
P
1

This is my solution which it is easy for me to understand

class ClassicPermutationProblem
{
    ClassicPermutationProblem() { }

    private static void PopulatePosition<T>(List<List<T>> finalList, List<T> list, List<T> temp, int position)
    {
         foreach (T element in list)
         {
             List<T> currentTemp = temp.ToList();
             if (!currentTemp.Contains(element))
                currentTemp.Add(element);
             else
                continue;

             if (position == list.Count)
                finalList.Add(currentTemp);
             else
                PopulatePosition(finalList, list, currentTemp, position + 1);
        }
    }

    public static List<List<int>> GetPermutations(List<int> list)
    {
        List<List<int>> results = new List<List<int>>();
        PopulatePosition(results, list, new List<int>(), 1);
        return results;
     }
}

static void Main(string[] args)
{
    List<List<int>> results = ClassicPermutationProblem.GetPermutations(new List<int>() { 1, 2, 3 });
}
Petrillo answered 16/8, 2015 at 17:28 Comment(0)
U
1

If performance and memory is an issue, I suggest this very efficient implementation. According to Heap's algorithm in Wikipedia, it should be the fastest. Hope it will fits your need :-) !

Just as comparison of this with a Linq implementation for 10! (code included):

  • This: 36288000 items in 235 millisecs
  • Linq: 36288000 items in 50051 millisecs

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Text;
    
    namespace WpfPermutations
    {
        /// <summary>
        /// EO: 2016-04-14
        /// Generator of all permutations of an array of anything.
        /// Base on Heap's Algorithm. See: https://en.wikipedia.org/wiki/Heap%27s_algorithm#cite_note-3
        /// </summary>
        public static class Permutations
        {
            /// <summary>
            /// Heap's algorithm to find all pmermutations. Non recursive, more efficient.
            /// </summary>
            /// <param name="items">Items to permute in each possible ways</param>
            /// <param name="funcExecuteAndTellIfShouldStop"></param>
            /// <returns>Return true if cancelled</returns> 
            public static bool ForAllPermutation<T>(T[] items, Func<T[], bool> funcExecuteAndTellIfShouldStop)
            {
                int countOfItem = items.Length;
    
                if (countOfItem <= 1)
                {
                    return funcExecuteAndTellIfShouldStop(items);
                }
    
                var indexes = new int[countOfItem];
                for (int i = 0; i < countOfItem; i++)
                {
                    indexes[i] = 0;
                }
    
                if (funcExecuteAndTellIfShouldStop(items))
                {
                    return true;
                }
    
                for (int i = 1; i < countOfItem;)
                {
                    if (indexes[i] < i)
                    { // On the web there is an implementation with a multiplication which should be less efficient.
                        if ((i & 1) == 1) // if (i % 2 == 1)  ... more efficient ??? At least the same.
                        {
                            Swap(ref items[i], ref items[indexes[i]]);
                        }
                        else
                        {
                            Swap(ref items[i], ref items[0]);
                        }
    
                        if (funcExecuteAndTellIfShouldStop(items))
                        {
                            return true;
                        }
    
                        indexes[i]++;
                        i = 1;
                    }
                    else
                    {
                        indexes[i++] = 0;
                    }
                }
    
                return false;
            }
    
            /// <summary>
            /// This function is to show a linq way but is far less efficient
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="list"></param>
            /// <param name="length"></param>
            /// <returns></returns>
            static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length)
            {
                if (length == 1) return list.Select(t => new T[] { t });
    
                return GetPermutations(list, length - 1)
                    .SelectMany(t => list.Where(e => !t.Contains(e)),
                        (t1, t2) => t1.Concat(new T[] { t2 }));
            }
    
            /// <summary>
            /// Swap 2 elements of same type
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="a"></param>
            /// <param name="b"></param>
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
            static void Swap<T>(ref T a, ref T b)
            {
                T temp = a;
                a = b;
                b = temp;
            }
    
            /// <summary>
            /// Func to show how to call. It does a little test for an array of 4 items.
            /// </summary>
            public static void Test()
            {
                ForAllPermutation("123".ToCharArray(), (vals) =>
                {
                    Debug.Print(String.Join("", vals));
                    return false;
                });
    
                int[] values = new int[] { 0, 1, 2, 4 };
    
                Debug.Print("Non Linq");
                ForAllPermutation(values, (vals) =>
                {
                    Debug.Print(String.Join("", vals));
                    return false;
                });
    
                Debug.Print("Linq");
                foreach(var v in GetPermutations(values, values.Length))
                {
                    Debug.Print(String.Join("", v));
                }
    
                // Performance
                int count = 0;
    
                values = new int[10];
                for(int n = 0; n < values.Length; n++)
                {
                    values[n] = n;
                }
    
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Reset();
                stopWatch.Start();
    
                ForAllPermutation(values, (vals) =>
                {
                    foreach(var v in vals)
                    {
                        count++;
                    }
                    return false;
                });
    
                stopWatch.Stop();
                Debug.Print($"Non Linq {count} items in {stopWatch.ElapsedMilliseconds} millisecs");
    
                count = 0;
                stopWatch.Reset();
                stopWatch.Start();
    
                foreach (var vals in GetPermutations(values, values.Length))
                {
                    foreach (var v in vals)
                    {
                        count++;
                    }
                }
    
                stopWatch.Stop();
                Debug.Print($"Linq {count} items in {stopWatch.ElapsedMilliseconds} millisecs");
    
            }
        }
    }
    
Underpinning answered 14/4, 2016 at 21:20 Comment(0)
S
1

Here's my solution in JavaScript (NodeJS). The main idea is that we take one element at a time, "remove it" from the string, vary the rest of the characters, and insert the element at the front.

function perms (string) {
  if (string.length == 0) {
    return [];
  }
  if (string.length == 1) {
    return [string];
  }
  var list = [];
  for(var i = 0; i < string.length; i++) {
    var invariant = string[i];
    var rest = string.substr(0, i) + string.substr(i + 1);
    var newPerms = perms(rest);
    for (var j = 0; j < newPerms.length; j++) {
      list.push(invariant + newPerms[j]);
    }
  }
  return list;
}

module.exports = perms;

And here are the tests:

require('should');
var permutations = require('../src/perms');

describe('permutations', function () {
  it('should permute ""', function () {
    permutations('').should.eql([]);
  })

  it('should permute "1"', function () {
    permutations('1').should.eql(['1']);
  })

  it('should permute "12"', function () {
    permutations('12').should.eql(['12', '21']);
  })

  it('should permute "123"', function () {
    var expected = ['123', '132', '321', '213', '231', '312'];
    var actual = permutations('123');
    expected.forEach(function (e) {
      actual.should.containEql(e);
    })
  })

  it('should permute "1234"', function () {
    // Wolfram Alpha FTW!
    var expected = ['1234', '1243', '1324', '1342', '1423', '1432', '2134', '2143', '2314', '2341', '2413', '2431', '3124', '3142', '3214', '3241', '3412', '3421', '4123', '4132'];
    var actual = permutations('1234');
    expected.forEach(function (e) {
      actual.should.containEql(e);
    })
  })
})
Sigmon answered 13/1, 2017 at 2:55 Comment(0)
G
1

Here is the simplest solution I can think of:

let rec distribute e = function
  | [] -> [[e]]
  | x::xs' as xs -> (e::xs)::[for xs in distribute e xs' -> x::xs]

let permute xs = Seq.fold (fun ps x -> List.collect (distribute x) ps) [[]] xs

The distribute function takes a new element e and an n-element list and returns a list of n+1 lists each of which has e inserted at a different place. For example, inserting 10 at each of the four possible places in the list [1;2;3]:

> distribute 10 [1..3];;
val it : int list list =
  [[10; 1; 2; 3]; [1; 10; 2; 3]; [1; 2; 10; 3]; [1; 2; 3; 10]]

The permute function folds over each element in turn distributing over the permutations accumulated so far, culminating in all permutations. For example, the 6 permutations of the list [1;2;3]:

> permute [1;2;3];;
val it : int list list =
  [[3; 2; 1]; [2; 3; 1]; [2; 1; 3]; [3; 1; 2]; [1; 3; 2]; [1; 2; 3]]

Changing the fold to a scan in order to keep the intermediate accumulators sheds some light on how the permutations are generated an element at a time:

> Seq.scan (fun ps x -> List.collect (distribute x) ps) [[]] [1..3];;
val it : seq<int list list> =
  seq
    [[[]]; [[1]]; [[2; 1]; [1; 2]];
     [[3; 2; 1]; [2; 3; 1]; [2; 1; 3]; [3; 1; 2]; [1; 3; 2]; [1; 2; 3]]]
Gather answered 22/2, 2017 at 19:0 Comment(0)
L
1

Lists permutations of a string. Avoids duplication when characters are repeated:

using System;
using System.Collections;

class Permutation{
  static IEnumerable Permutations(string word){
    if (word == null || word.Length <= 1) {
      yield return word;
      yield break;
    }

    char firstChar = word[0];
    foreach( string subPermute in Permutations (word.Substring (1)) ) {
      int indexOfFirstChar = subPermute.IndexOf (firstChar);
      if (indexOfFirstChar == -1) indexOfFirstChar = subPermute.Length;

      for( int index = 0; index <= indexOfFirstChar; index++ )
        yield return subPermute.Insert (index, new string (firstChar, 1));
    }
  }

  static void Main(){
    foreach( var permutation in Permutations ("aab") )
      Console.WriteLine (permutation);
  }
}
Leporid answered 24/4, 2017 at 7:39 Comment(2)
With so many working solutions already present, you may want to describe what makes your solution stand out from all the other solutions here.Hartle
Avoids duplication when characters are repeated (by chindirala for another answer). For "aab": aab aba baaLeporid
M
1
    //Generic C# Method
            private static List<T[]> GetPerms<T>(T[] input, int startIndex = 0)
            {
                var perms = new List<T[]>();

                var l = input.Length - 1;

                if (l == startIndex)
                    perms.Add(input);
                else
                {

                    for (int i = startIndex; i <= l; i++)
                    {
                        var copy = input.ToArray(); //make copy

                        var temp = copy[startIndex];

                        copy[startIndex] = copy[i];
                        copy[i] = temp;

                        perms.AddRange(GetPerms(copy, startIndex + 1));

                    }
                }

                return perms;
            }

            //usages
            char[] charArray = new char[] { 'A', 'B', 'C' };
            var charPerms = GetPerms(charArray);


            string[] stringArray = new string[] { "Orange", "Mango", "Apple" };
            var stringPerms = GetPerms(stringArray);


            int[] intArray = new int[] { 1, 2, 3 };
            var intPerms = GetPerms(intArray);
Misfit answered 31/12, 2017 at 11:9 Comment(1)
It would be great if you can elaborate a little on how this code works, instead of leaving it here alone.Marino
J
1

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
Jostle answered 22/1, 2021 at 14:13 Comment(0)
M
0

Here is the function which will print all permutations recursively.

public void Permutations(string input, StringBuilder sb)
    {
        if (sb.Length == input.Length)
        {
            Console.WriteLine(sb.ToString());
            return;
        }

        char[] inChar = input.ToCharArray();

        for (int i = 0; i < input.Length; i++)
        {
            if (!sb.ToString().Contains(inChar[i]))
            {
                sb.Append(inChar[i]);
                Permutations(input, sb);    
                RemoveChar(sb, inChar[i]);
            }
        }
    }

private bool RemoveChar(StringBuilder input, char toRemove)
    {
        int index = input.ToString().IndexOf(toRemove);
        if (index >= 0)
        {
            input.Remove(index, 1);
            return true;
        }
        return false;
    }
Minion answered 12/8, 2013 at 7:28 Comment(0)
B
0
class Permutation
{
    public static List<string> Permutate(string seed, List<string> lstsList)
    {
        loopCounter = 0;
        // string s="\w{0,2}";
        var lstStrs = PermuateRecursive(seed);

        Trace.WriteLine("Loop counter :" + loopCounter);
        return lstStrs;
    }

    // Recursive function to find permutation
    private static List<string> PermuateRecursive(string seed)
    {
        List<string> lstStrs = new List<string>();

        if (seed.Length > 2)
        {
            for (int i = 0; i < seed.Length; i++)
            {
                str = Swap(seed, 0, i);

                PermuateRecursive(str.Substring(1, str.Length - 1)).ForEach(
                    s =>
                    {
                        lstStrs.Add(str[0] + s);
                        loopCounter++;
                    });
                ;
            }
        }
        else
        {
            lstStrs.Add(seed);
            lstStrs.Add(Swap(seed, 0, 1));
        }
        return lstStrs;
    }
    //Loop counter variable to count total number of loop execution in various functions
    private static int loopCounter = 0;

    //Non recursive  version of permuation function
    public static List<string> Permutate(string seed)
    {
        loopCounter = 0;
        List<string> strList = new List<string>();
        strList.Add(seed);
        for (int i = 0; i < seed.Length; i++)
        {
            int count = strList.Count;
            for (int j = i + 1; j < seed.Length; j++)
            {
                for (int k = 0; k < count; k++)
                {
                    strList.Add(Swap(strList[k], i, j));
                    loopCounter++;
                }
            }
        }
        Trace.WriteLine("Loop counter :" + loopCounter);
        return strList;
    }

    private static string Swap(string seed, int p, int p2)
    {
        Char[] chars = seed.ToCharArray();
        char temp = chars[p2];
        chars[p2] = chars[p];
        chars[p] = temp;
        return new string(chars);
    }
}
Boswell answered 23/2, 2014 at 3:35 Comment(0)
R
0

Here is a C# answer which is a little simplified.

public static void StringPermutationsDemo()
{
    strBldr = new StringBuilder();

    string result = Permute("ABCD".ToCharArray(), 0);
    MessageBox.Show(result);
}     

static string Permute(char[] elementsList, int startIndex)
{
    if (startIndex == elementsList.Length)
    {
        foreach (char element in elementsList)
        {
            strBldr.Append(" " + element);
        }
        strBldr.AppendLine("");
    }
    else
    {
        for (int tempIndex = startIndex; tempIndex <= elementsList.Length - 1; tempIndex++)
        {
            Swap(ref elementsList[startIndex], ref elementsList[tempIndex]);

            Permute(elementsList, (startIndex + 1));

            Swap(ref elementsList[startIndex], ref elementsList[tempIndex]);
        }
    }

    return strBldr.ToString();
}

static void Swap(ref char Char1, ref char Char2)
{
    char tempElement = Char1;
    Char1 = Char2;
    Char2 = tempElement;
}

Output:

1 2 3
1 3 2

2 1 3
2 3 1

3 2 1
3 1 2
Ringed answered 18/4, 2014 at 4:22 Comment(0)
B
0

Here is one more implementation of the algo mentioned.

public class Program
{
    public static void Main(string[] args)
    {
        string str = "abcefgh";
        var astr = new Permutation().GenerateFor(str);
        Console.WriteLine(astr.Length);
        foreach(var a in astr)
        {
            Console.WriteLine(a);
        }
        //a.ForEach(Console.WriteLine);
    }
}

class Permutation
{
    public string[] GenerateFor(string s)
    {  

        if(s.Length == 1)
        {

            return new []{s}; 
        }

        else if(s.Length == 2)
        {

            return new []{s[1].ToString()+s[0].ToString(),s[0].ToString()+s[1].ToString()};

        }

        var comb = new List<string>();

        foreach(var c in s)
        {

            string cStr = c.ToString();

            var sToProcess = s.Replace(cStr,"");
            if (!string.IsNullOrEmpty(sToProcess) && sToProcess.Length>0)
            {
                var conCatStr = GenerateFor(sToProcess);



                foreach(var a in conCatStr)
                {
                    comb.Add(c.ToString()+a);
                }


            }
        }
        return comb.ToArray();

    }
}
Brodie answered 5/7, 2016 at 21:40 Comment(1)
new Permutation().GenerateFor("aba") outputs string[4] { "ab", "baa", "baa", "ab" }Chrotoem
A
0

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);
            }
        }
    }
}
Assumed answered 24/4, 2022 at 11:10 Comment(0)
G
0

Here's an answer which has the following features:

  • Supports permutation WITH repetition/duplicates

  • Iterative solution (no recursion needed)

  • Short and concise, with no need of special math operators or casting

  • Uses IEnumerable, so you can keep your code neat and tidy

  • Works on ints, but you can easily use string arrays and correspond them appropriately

     static IEnumerable<int[]> permute(int size)
     {
         int[] i = new int[size];
         while (true) {
             yield return i;
             int index = 0;
             while (index < size) {
                 i[index]++;
                 if (i[index] == size) {
                     i[index] = 0;
                     index++;
                 }
                 else break;
             }
             if (index == size) break;
         }
     }
    
     // Example usage:
     static void Main(string[] args)
     {
         foreach (int[] i in permute(3))
         {
             foreach (int j in i) Console.Write(j + " ");
             Console.WriteLine();
         }
     }
    

Output:

0 0 0
1 0 0
2 0 0
0 1 0
1 1 0
2 1 0
0 2 0
1 2 0
2 2 0
0 0 1
1 0 1
2 0 1
0 1 1
1 1 1
2 1 1
0 2 1
1 2 1
2 2 1
0 0 2
1 0 2
2 0 2
0 1 2
1 1 2
2 1 2
0 2 2
1 2 2
2 2 2
Gabelle answered 31/12, 2023 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.