The problem involved determining lexicographical permutations which is a fairly common task when you want to test code. The reason for this is if you want to test a method with a range of values you can produce permutations of an original list and pass in each one, lexicographical simply means they are in order. For example, the list [0, 1, 2] can be arranged in the following permutations:
0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0
Initially I struggled to come up with a solution to this spending ages trying to figure out how to determine the next permutation in order. The answer came from the elegantly titled "Algorithm L". To summarise what it does I'll try and show an example in action, so first we start with our initial permutation.
1 2 3 4 5
First we start from the second to last index (in this case index 3 because indexes are zero based and the number there is 4) and work our way backwards until we find an index where it's value is less than the one after it which in this case is the same index we started at.
Index | 0 | 1 | 2 | 3 | 4 |
Value | 1 | 2 | 3 | 4 | 5 |
^ |
Index | 0 | 1 | 2 | 3 | 4 |
Value | 1 | 2 | 3 | 4 | 5 |
^ |
1 2 3 5 4
If we repeated the process again from this permutation we would do something like this:
Index | 0 | 1 | 2 | 3 | 4 |
Value | 1 | 2 | 3 | 5 | 4 |
j | m |
Index | 0 | 1 | 2 | 3 | 4 |
Value | 1 | 2 | 4 | 5 | 3 |
Index | 0 | 1 | 2 | 3 | 4 |
Value | 1 | 2 | 4 | 3 | 5 |
Implementing this in Python was easy but I wanted to play with Generics in C# so I decided to implement it in that language.
Generics are a way in which we can write a class to work on different data types without implementing the code with 1 certain type, for instance if we create a method that sorted arrays we could write something like:
public void Sort(int[] arrayOfValues) { ... }
Which would work great but if we then wanted to sort an array of doubles or characters we would have to re-implement the method for different types so we end up with SortInt(), SortDouble() and so forth. Whilst this may be okay for a couple of types if we wanted to sort other types and custom types then re-writing this code becomes a lot of work, makes maintenance harder and introduces a greater chance of error. This is where generics comes in, instead of the method signature used above we can instead write it as follows:
public void Sort
When we call this method we then define the type of data we are working like so:
int[] myIntArray = new int[] { 1, 2, 3, 4 };As you can see the method call is identical except that we are specifying the data type we intend to work with, the magic part here is the <T> after the method name, this indicates that we are using a generic type called T and we can use it in the method like we would a normal type.
char[] myCharArray = new char[] { 'a', 'b', 'c', 'd' };
Sort(myIntArray);
Sort(myCharArray);
public void PrintValuesNow one problem we will encounter with the Sort() method we described above is that we cannot compare generic types as we can't guarantee that they will be comparable, to get around this we add a constraint to the method like so:(T[] arrayOfValues)
{
foreach (T value in arrayOfValues)
{
Console.WriteLine(value);
}
}
public void Sort
This instructs the system to only accept types which implement IComparable, with this guarantee in place we can now compare values in the method:
public void Sort(T[] arrayOfValues) where T: IComparable
{
...
if (arrayOfValues[a].CompareTo(arrayOfValues[b]) > 0)
{
T holder = arrayOfValues[a];
arrayOfValues[a] = arrayOfValues[b];
arrayOfValues[b] = holder;
}
...
}
Using this we can implement our next_permutation algorithm in C# and enable it to work with any types (restricted to comparable types of course) we choose. Unfortunately I don't have the code to hand at the moment so I'll post it up for all to see and criticise (be kind please) tomorrow.
This has taken up quite a lot of space for now so I'll save the post on Linq for another day, but not to long away I promise as I want to post about it before I go for the next big C++ push.
No comments:
Post a Comment
Note: only a member of this blog may post a comment.