Click here to Skip to main content
15,887,596 members
Articles / Programming Languages / C#

A C# List Permutation Iterator

Rate me:
Please Sign up or sign in to vote.
4.71/5 (5 votes)
14 Nov 2009CPOL 54.1K   16   13
An iterator in C# which iterates over all permutations of a given IList.

Introduction

In this article, I will present a compact, easy to use method for iterating over all permutations of a given sequence. The iteration modifies the internal order of the sequence, visiting all permutations, and eventually restoring the original order (if the enumeration process is followed through).

Using the code

The implementation of the iterator is recursive; the recursion terminal condition is when the list has only one element, in which case, it is simply returned. In the recursive case, we iterate (n) times doing a recursive call to permutate the list's first (n-1) elements, and performing a rotate-right after each iteration.

Since each full enumeration eventually restores the sequence to its original order, the rotate-right is guaranteed to position a different element at the end of the sequence each time.

C#
public static void RotateRight(IList sequence, int count)
{
    object tmp = sequence[count-1];
    sequence.RemoveAt(count - 1);
    sequence.Insert(0, tmp);
}

public static IEnumerable<IList> Permutate(IList sequence, int count)
{
    if (count == 1) yield return sequence;
    else
    {
        for (int i = 0; i < count; i++)
        {
            foreach (var perm in Permutate(sequence, count - 1))
                yield return perm;
            RotateRight(sequence, count);
        }
    }
}

Here is how we use this code to permutate a list of integers:

C#
static void PermutateIntegersTest()
{
    List<int> seq = new List<int>() { 1, 2, 3, 4 };
    foreach (var permu in Permutate(seq, seq.Count))
    {
        foreach (var i in permu)
            Console.Write(i.ToString() + " ");
        Console.WriteLine();
    }
}

Or to permutate a string:

C#
using System.Linq; // For the ToList() and ToArray() extension methods.

static void PermutateStringTest()
{
    string a = "word";
    foreach (List<char> perm in Permutate(a.ToCharArray().ToList(), a.Length))
    {
        string s = new string(perm.ToArray());
        Console.Write(s + "\t");
    }
    Console.WriteLine();
}

Remember that this implementation actually modifies the order of items in the sequence, and if that is not desired, a copy of the sequence must be made before the iteration is started.

That's it, enjoy.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Israel Israel
Software developer since 1984, currently specializing in C# and .NET.

Comments and Discussions

 
QuestionHow to find every permutations of a List<Vector2> object and then a specific permutation? Pin
Member 132872312-Jul-17 13:50
Member 132872312-Jul-17 13:50 
I have an object of type List <vector2> called markerPositions which contains coordinates for a polygon on a map. The outline of the polygon is drawn in order of placement of the markers. So the shape of the polygon depends on the order. I am trying to find a shape that has no intersecting lines. I am assuming that the shape with the greatest area will have no intersecting lines since the angles of the joints at each marker will be the most obtuse. So I would like to find every permutation for the order in which the Vector2's occur in the list so that I can find the order which produces the shape with the largest area and then re-order the list to that order. Here is what I have so far, but it is not working...

//  Get every permutation of the order of markers in markerPositions
           int index = 0;
           int largestAreaIndex = 0;
           float area = 0f;
           float largestArea = area;

           foreach (List<Vector2> perm in Permutate( markerPositions, markerPositions.Count - 1 ))
           {
               // Get the area for each polygon order of the current permutation and determine the largest one.


               Debug.Log ("Current Index is " + index);

               area = Math.Abs( markerPositions.Take( markerPositions.Count -1 )
                   .Select((p, i) => ( markerPositions[i + 1].x   - p.x) * ( markerPositions[i + 1].y + p.y))
                   .Sum() / 2);

               Debug.Log ("Area: " + area + " km^2");

               if ( area > largestArea)
               {
                   // Store the largest area
                   largestArea = area;
                   Debug.Log ("Largest Area so far is: " + largestArea + " km^2");

                   //store the index for the largest area
                   largestAreaIndex = index;
                   Debug.Log ("LargestAreaindex is: " +  largestAreaIndex);
               }


               Debug.Log ("Current Polygon Area: is " + area + " km^2. Largest possible Polygon area so far is "+ largestArea +" with index at " +  largestAreaIndex);


               index ++ ;

           }


           // Now just go to the pemuation at largestAreaindex

           int targetIndex = 0;

           foreach (List<Vector2> perm in Permutate( markerPositions, largestAreaIndex ) )
           {

               Debug.Log ("targetIndex is " + targetIndex );

               if (targetIndex >= largestAreaIndex ) {
                       return;
                   }

               targetIndex ++;
           }

           Debug.Log ("DONE: targetIndex is " + targetIndex + " which should match largestAreaIndex which is: " + largestAreaIndex);


The first loop seems to work but the second returns the order back to the original order of the list so in the end it is as if I hadn't permutated the list at all.

What am I doing wrong?

Thanks!

modified 3-Jul-17 21:36pm.

GeneralMy vote of 5 Pin
Andira Muttakim12-Jan-14 3:47
professionalAndira Muttakim12-Jan-14 3:47 
GeneralPermutate() arguments Pin
Seth Morris21-Nov-09 23:02
Seth Morris21-Nov-09 23:02 
GeneralRecursion Pin
PIEBALDconsult19-Nov-09 10:32
mvePIEBALDconsult19-Nov-09 10:32 
GeneralRe: Recursion Pin
Aviad P.20-Nov-09 8:41
Aviad P.20-Nov-09 8:41 
GeneralRe: Recursion Pin
George I. Birbilis31-Oct-11 4:54
George I. Birbilis31-Oct-11 4:54 
GeneralRe: Recursion Pin
George I. Birbilis31-Oct-11 5:06
George I. Birbilis31-Oct-11 5:06 
GeneralRe: Recursion Pin
Mr.PoorEnglish9-Oct-13 11:20
Mr.PoorEnglish9-Oct-13 11:20 
GeneralRe: Recursion Pin
George I. Birbilis13-Mar-14 21:41
George I. Birbilis13-Mar-14 21:41 
GeneralRe: Recursion Pin
George I. Birbilis13-Mar-14 21:49
George I. Birbilis13-Mar-14 21:49 
GeneralSimilar to C++ STL Pin
Fredrik B17-Nov-09 3:01
Fredrik B17-Nov-09 3:01 
GeneralNeeds More Pin
#realJSOP15-Nov-09 1:36
mve#realJSOP15-Nov-09 1:36 
GeneralRe: Needs More Pin
Aviad P.15-Nov-09 2:07
Aviad P.15-Nov-09 2:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.