-3

I am looking for a output below with the input n and with number of loops less than (n*(n+1))/2 ,

Example N = 4,

1

2 3

4 5 6

7 8 9 10

Number of loops should be less than 10. Is this possible???

4 Answers4

2

There's also a solution with only one loop.

Print numbers in order, followed by a space, and if the last number was triangular, then print a newline. Keep track of how many newlines you have, and that's it.

Here's the code:

public static void PrintPyramid(int n)
{
    var i = 0;

    while (n > 0)
    {
        Console.Write(++i);

        if (IsTriangularNumber(i))
        {
            Console.Write(Environment.NewLine);
            n--;
        }
        else
        {
            Console.Write(" ");
        }
    }
}

public static bool IsTriangularNumber(int i)
{
    var n = (int)Math.Sqrt(i*2);

    return n*(n + 1) / 2 == i;
}

And here's how it works: http://ideone.com/Mx7Cel

For faster triangular number tests, see the answers to this question.

Community
  • 1
  • 1
Cristian Lupascu
  • 39,078
  • 16
  • 100
  • 137
  • Isn't this giving me the same number of loops as fubo's solution. I'm still hitting the loop (n*(n+1))/2 number of times – Arjun Palwai Aug 13 '15 at 12:41
  • 1
    @ArjunPalwai I don't know what is your definition of loop. For me, it's a code construct that executes a block of code (possibly) multiple times. In the code above, the `while` is the only loop. I doubt it's possible to solve the problem with less than that. – Cristian Lupascu Aug 13 '15 at 12:44
  • 1
    @w0lf Technically you could read the prereq *literally* and do some loop unrolling... :-) – xanatos Aug 13 '15 at 12:57
2

By cheating it is easy:

public static void PrintPyramid(int n)
{
    int i = 1;
    int row = 1;
    int maxNumberInRow = 1;

    int cycles = 0;

    while (row <= n)
    {
        cycles++;

        if (i == maxNumberInRow)
        {
            Console.Write(i);
            Console.Write(" ");
            i++;
        }
        else
        {
            Console.Write(i);
            Console.Write(" ");
            i++;

            Console.Write(i);
            Console.Write(" ");
            i++;
        }

        if (i > maxNumberInRow)
        {
            Console.WriteLine();
            row++;
            maxNumberInRow += row;
        }
    }

    Console.WriteLine();
    Console.WriteLine("Cycles: {0}", cycles);
}

I did a little loop unrolling, doing up to two numbers in the same cycle. For n == 4, it is 6 full cycles.

Note that if we want to play the semantic game, a partial loop unrolling is enough:

public static void PrintPyramid3(int n)
{
    if (n >= 1)
    {
        Console.Write("1");
        Console.Write(" ");
        Console.WriteLine();
    }

    int i = 2;
    int row = 2;
    int maxNumberInRow = 3;
    int cycles = 0;

    while (row <= n)
    {
        cycles++;

        Console.Write(i);
        i++;

        if (i > maxNumberInRow)
        {
            Console.WriteLine();
            row++;
            maxNumberInRow += row;
        }
        else
        {
            Console.Write(" ");
        }
    }

    Console.WriteLine();
    Console.WriteLine("Cycles: {0}", cycles);
}

The first row is "outside" the loop, so for n == 4, only 9 cycles are necessary.

Based on this code, it is easy to partially loop unroll the first x cases and do the remaining cases in a loop.

Ok... I was kidding... It is possible to do it in a totally loopless way...

public static void PrintPyramid(int n)
{
    PrintPyramidRecursive(n, 1, 1, 1);
}

private static void PrintPyramidRecursive(int n, int i = 1, int row = 1, int maxNumberInRow = 1)
{
    Console.Write(i);
    Console.Write(" ");
    i++;

    if (i > maxNumberInRow)
    {
        Console.WriteLine();
        row++;
        maxNumberInRow += row;

        if (row > n)
        {
            return;
        }
    }

    PrintPyramidRecursive(n, i, row, maxNumberInRow);
}

You only need to use recursion! :-) :-) :-)

This one is a little more devious: no (apparent) cycles and no recursion:

public static void PrintPyramid5(int n)
{
    int i = 1;
    int row = 1;
    int maxNumberInRow = 1;

    ManualResetEvent mre = new ManualResetEvent(false);
    Timer t = null;

    TimerCallback tc = x =>
    {
        Console.Write(i);
        Console.Write(" ");
        i++;

        if (i > maxNumberInRow)
        {
            Console.WriteLine();
            row++;
            maxNumberInRow += row;

            if (row > n)
            {
                t.Dispose();
                mre.Set();
            }
        }
    };

    t = new Timer(tc, null, 0, 1);

    mre.WaitOne();
}

Simply put, the printing method is called by a Timer :-) So the loop is in the operating system. The printing method (tc) will clearly be called 10 times for n == 4.

xanatos
  • 109,618
  • 12
  • 197
  • 280
1

You could pretend that string.Join() and Enumerable.Range() don't do any looping internally, and do it like this:

int n = 4;

for (int i = 1, j = 1; i <= n; ++i, j += i-1)
    Console.WriteLine(string.Join(" ", Enumerable.Range(j, i).Select(x => x.ToString("00"))));

The for loop therefore only loops once per line rather than once per output number. But it's a cheat, because string.Join() and Enumerable.Range() do loop internally.

As per xanatos's suggestion, here's a version with no explicit loops at all:

Console.WriteLine(
    string.Join("\n", Enumerable.Range(1, n).Select(i => 
        string.Join(" ", Enumerable.Range((i*(i-1))/2+1, i).Select(x => 
            x.ToString("00"))))));

This is a curiosity only, of course. ;)

Finally, here's a variant of xanatos's recursive solution:

private static string Triangular(int max, int row, int rowEnd, int number)
{
    if (row == max)
        return "";
    else if (number <= rowEnd)
        return number.ToString("00") + " " + Triangular(max, row, rowEnd, number + 1);
    else
        return "\n" + Triangular(max, row + 1, rowEnd + row + 1, number);
}

Which you'd use like this:

Console.WriteLine(Triangular(n, 1, 1, 1));
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • 1
    The semantic game :-) Offloading the loop to someone else :-) :-) At this point you shoud cheat with both hands and replace the `for` cycle with another `Enumerable.Range` and say that you can do it in a loopless way! :-) – xanatos Aug 13 '15 at 13:15
0

here i did your homework

public static void PrintPyramid(int n)
{
    int t = 1;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j <= i; j++)
        {
            Console.Write(t);
            t++;
        }
        Console.WriteLine();
    }
}
fubo
  • 44,811
  • 17
  • 103
  • 137
  • Hi buddy. Thanks for the help, but unfortunately my homework still remains. I already know how to do the same with number of loops = (n*(n+1))/2 I was wondering if we can optimize the same while reducing the number of loops. – Arjun Palwai Aug 13 '15 at 12:32