4
\$\begingroup\$

The original idea is to print the following numbers:

7, 1, 2, 3, 4, 5, 6

So some number x followed by everything in the range 1 to (x - 1). The key is to skip 0.

I have two versions of this. The first is a pretty straightforward for loop with modular arithmetic, skipping 0:

for (int i = 7; i <= 14; i++)
{
    int result = i % 8;

    if (result == 0)
        continue;
    else
        Console.WriteLine(result);
}

The second (and, as a disclaimer, I will almost certainly not be using this in actual production code, I wrote it more for my own learning), is based on closures:

static void Main(string[] args)
    {
        Func<int> counterFunction = RollAround(1, 8);

        for (int i = 0; i < 7; i++)
            Console.WriteLine(counterFunction());

        Console.ReadLine();
    }

    private static Func<int> RollAround(int min, int max)
    {
        int counter = max - 1;

        return () =>
        {
            int result = counter % max;

            while (result < min)
            {
                counter++;
                result = counter % max;
            }

            counter++;

            return result;
        };
    }

I'm curious if people had feedback on how these can be improved. The first one is probably "more important" in that it's intended for production code, but I'm curious about the second one as well just for my own learning (especially since I'm admittedly a bit rusty on closures).

\$\endgroup\$
3
\$\begingroup\$

The first is a pretty straightforward for loop with modular arithmetic, skipping 0:

The problem in this code is that you are mixing output with the algorithm logic.

The second (and, as a disclaimer, I will almost certainly not be using this in actual production code, I wrote it more for my own learning), is based on closures:

I vouch for your decision. This code while might be interesting it has a behaviour that is hard to follow. You basically implemented something that looks like an IEnumerable. However in this code you return a function and what that function does is not documented. You don't know how many times you have to call it.

The solution is then resolving the first problem while using the IEnumerable mechanism that is understood by everyone and has a more comprehensible use:

public static IEnumerable<int> RollAround(int n)
{
    if(n < 1)
    {
        throw new ArgumentException("n must be greater or equal to 1", nameof(n));
    }

    var elems = new[] { n };
    return elems.Concat(Enumerable.Range(1, n - 1));
}

static void Main(string[] args)
{
    foreach(var elem in RollAround(3)){
        Console.WriteLine(elem);     
    }
}
\$\endgroup\$
2
\$\begingroup\$

You can also achieve a good performing solution with yield

public static IEnumerable<int> RollAround(int n)
{
    yield return n;
    for (int i = 1; i < n; i++) { yield return i; }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.