Search code examples
c#recursionpermutationyield

Yield return in recursion doesn't return value even after ".ToList()" call


When I make a call to generation permutations, 2nd GeneratePermutations(list, startCount, permutationCount) do yield return 6 times (yield return permutationList;). But for some reason, result in the first GetPermutations doesn't contain anything even though I did called .ToList() on the result.

Does this have anything to do recursion?

Test.cs

IEnumerable<int[]> actual = _sut.GetPermutations(3).ToList();

Perm.cs

public class Perm
{
    public IEnumerable<int[]> GetPermutations(int permutationCount)
    {
        int[] permutationList = Enumerable.Range(1, permutationCount).ToArray();
        IEnumerable<int[]> result = GeneratePermutations(permutationList, 0, permutationCount - 1).ToList();

        // Doesn't contain any value!
        return result;
    }

    // http://stackoverflow.com/a/756083/4035
    private IEnumerable<int[]> GeneratePermutations(int[] permutationList, int startCount, int permutationCount)
    {
        if (startCount == permutationCount)
        {
            // Does return 6 times here.
            yield return permutationList;
        }
        else
        {
            for (int i = startCount; i <= permutationCount; i++)
            {
                Swap(ref permutationList, startCount, i);
                GeneratePermutations(permutationList, startCount + 1, permutationCount).ToList();
                Swap(ref permutationList, startCount, i);
            }

        }
    }

    // http://stackoverflow.com/a/2094316/4035
    public static void Swap(ref int[] list, int index1, int index2)
    {
        int tmp = list[index1];
        list[index1] = list[index2];
        list[index2] = tmp;
    }
}

Solution

  • Your problem is, that you never return the results of your recursive calls and that you work with the same array all the time. This would be the fastest fix for your code (not the best, but I'm sure you'll figure it out from here):

    IEnumerable<int[]> perms = GeneratePermutations(
        new List<int>(permutationList).ToArray(), 
        startCount + 1, permutationCount);
    
    foreach(int[] perm in perms)
        yield return perm;
    

    btw: you can make the entire class static and generic

    Proof on dotNetFiddle