Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate permutations using polymorphic method

The instructions :

Please write a piece of code that takes as an input a list in which each element is another list containing an unknown type and which returns a list of all possible lists that can be obtained by taking one element from each of the input lists.

For example:

[[1, 2], [3, 4]], should return: [[1, 3], [1, 4], [2, 3], [2, 4]].

[['1'], ['2'], ['3', '4' ]], should return [['1', '2', '3'], ['1', '2', '4']].

My code:

public static void Main(string[] args)
{
     //Create a list of lists of objects.
       var collections = new List<List<object>>();
       collections.Add(new List<object> { 1, 5, 3 });
       collections.Add(new List<object> { 7, 9 });
       collections.Add(new List<object> { "a", "b" });

     //Get all the possible permutations
       var combinations = GetPermutations(collections);

     //Loop through the results and display them in console
       foreach (var result in combinations)
       {
           result.ForEach(item => Console.Write(item + " "));
           Console.WriteLine();
       }

        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
}

private static List<List<object>> GetPermutations(List<List<object>> collections)
{
        List<List<object>> permutations = new List<List<object>>();

       //Check if the input list has any data, else return the empty list.
        if (collections.Count <= 0)
            return permutations;

       //Add the values of the first set to the empty List<List<object>>
       //permutations list
        foreach (var value in collections[0])
            permutations.Add(new List<object> { value });


       /* Skip the first set of List<List<object>> collections as it was
        * already added to the permutations list, and loop through the
        * remaining sets. For each set, call the AppendValues function
        * to append each value in the set to the permuations list.
        * */
        foreach (var set in collections.Skip(1))
             permutations = AppendNewValues(permutations, set);

        return permutations;
}

private static List<List<object>> AppendNewValues(List<List<object>> permutations, List<object> set)
{
        //Loop through the values in the set and append them to each of the
        //list of permutations calculated so far.
        var newCombinations = from additional in set
                              from value in permutations
                              select new List<object>(value) { additional };

        return newCombinations.ToList();
}

How could I make it work with polymorphic method that returns a generic list?

like image 498
NomadTraveler Avatar asked May 06 '15 02:05

NomadTraveler


People also ask

How do you generate all permutations of a number?

Heap's algorithm is used to generate all permutations of n objects. The idea is to generate each permutation from the previous permutation by choosing a pair of elements to interchange, without disturbing the other n-2 elements.

How do you find the permutation of numbers in C++?

All permutations of an array using STL in C++ Approach: The next possible permutation of the array can be found using next_permutation() function provided in STL. Syntax: bool next_permutation (BidirectionalIterator first, BidirectionalIterator last);

How do you find the permutation of an array in Java?

You take first element of an array (k=0) and exchange it with any element (i) of the array. Then you recursively apply permutation on array starting with second element. This way you get all permutations starting with i-th element.


2 Answers

Please write a piece of code that takes as an input a list in which each element is another list containing an unknown type and which returns a list of all possible lists that can be obtained by taking one element from each of the input lists.

I would have asked for clarification, something like "You mean a generic method then?"

In speaking of polymorphism, they were likely being able to write just one method and call it form any arbitrary type, something like:

public static IList<IList<T>> GetPermutations<T>(IList<IList<T>> inputLists) {
    if (inputLists.Count < 2) {
        // special case. 
    }

    return _permutationHelper(0, inputLists);
}

private static IList<IList<T>> _permutationHelper<T>(int i, IList<IList<T>> inputLists) {
    IList<IList<T>> returnValue = new List<IList<T>>();
    if (i == inputLists.Count) {
        returnValue.Add(new List<T>());
    } else {
        foreach (var t in inputLists[i]) {
            foreach (var list in _permutationHelper(i + 1, inputLists)) {
                list.Add(t);
                returnValue.Add(list);
            }
        }
    }

    return returnValue;
}

It is true that your implementation would allow arbitrary types at run time, but it loses type safety. Given that it's an implementation in C#, type safety being a requirement is a safe guess - but it doesn't hurt to ask either.

Another thing of note - they could have just said they were looking for the Cartesian product of the given lists.

like image 96
jdphenix Avatar answered Oct 19 '22 04:10

jdphenix


All I can think of is that they were not trying to mix different types in the lists(like you implemented), the types of all lists would be the same and they wanted you to write a Generic Class that would handle the problem for different types of lists, resulting in something like this:

static void Main(string[] args)
{
    var intCollections = new List<List<int>>();
    intCollections.Add(new List<int> { 1, 5, 3 });
    intCollections.Add(new List<int> { 7, 9 });

    var stringCollections = new List<List<String>>();
    stringCollections.Add(new List<String> { "a", "b" });
    stringCollections.Add(new List<String> { "c","d", "e" });
    stringCollections.Add(new List<String> { "g", "f" });

    //here you would have the "polymorphism", the same signature for different Lists types

    var intCombinations = GetPermutations(intCollections);
    var stringCombinations = GetPermutations(stringCollections);

    foreach (var result in intCombinations)
    {
        result.ForEach(item => Console.Write(item + " "));
        Console.WriteLine();
    }

    Console.WriteLine();

    foreach (var result in stringCombinations)
    {
        result.ForEach(item => Console.Write(item + " "));
        Console.WriteLine();
    }

    Console.WriteLine("Press any key to exit.");
    Console.ReadKey();
}

//This would be your generic implementation, basically changing from object to T and adding <T> after method

private static List<List<T>> GetPermutations<T>(List<List<T>> collections)
{
    List<List<T>> permutations = new List<List<T>>();

    //Check if the input list has any data, else return the empty list.
    if (collections.Count <= 0)
        return permutations;

    //Add the values of the first set to the empty List<List<object>>
    //permutations list
    foreach (var value in collections[0])
        permutations.Add(new List<T> { value });


    /* Skip the first set of List<List<object>> collections as it was
        * already added to the permutations list, and loop through the
        * remaining sets. For each set, call the AppendValues function
        * to append each value in the set to the permuations list.
        * */
    foreach (var set in collections.Skip(1))
        permutations = AppendNewValues(permutations, set);

    return permutations;
}

private static List<List<T>> AppendNewValues<T>(List<List<T>> permutations, List<T> set)
{
    //Loop through the values in the set and append them to each of the
    //list of permutations calculated so far.
    var newCombinations = from additional in set
                            from value in permutations
                            select new List<T>(value) { additional };

    return newCombinations.ToList();
} 

This generic implementation, comparing to yours, have the advantage of type Safety, it makes sure you will not mix different object types.

like image 44
Rodrigo López Avatar answered Oct 19 '22 03:10

Rodrigo López