C# Number Triangle Pattern (Diagonal Fill)

Beginner
5 min read
Updated: Sep 2026
3 programs
Live preview

What Is This Pattern?

A column-wise number triangle fills a 2D array down each column with increasing numbers, then prints row by row. That fill order creates jumps like 2 6 and 3 7 10 instead of consecutive digits.

Remember
Rule: fill  col outer, row = col..rows → tri[row,col] = num++
      print row outer, col = 1..row

1
2 6
3 7 10
4 8 11 13
5 9 12 14 15     ← rows = 5

In C# use int[,] tri = new int[rows + 1, rows + 1], fill with col outer, then print with row outer using Console.Write and WriteLine().

How to Solve It

Store values in a 2D array so fill order and print order can differ. Fill with col outer; print with row outer.

MethodIdeaBest for
2D array + column fillFill col outer, print row outerLearning, interviews, exams
Rows inputSame logic with a user-chosen heightPractice / demos

Pseudocode

Pseudocode
create tri[rows+1, rows+1]
num = 1
for col from 1 to rows:
    for row from col to rows:
        tri[row, col] = num
        num = num + 1
for row from 1 to rows:
    for col from 1 to row:
        print tri[row, col] (space between values)
    print newline

Cheat sheet

GoalPattern
Store cellsint[,] tri = new int[rows + 1, rows + 1];
Fill column-wisefor (col = 1; col <= rows; col++) for (row = col; row <= rows; row++) tri[row, col] = num++;
Print row-wisefor (row = 1; row <= rows; row++) for (col = 1; col <= row; col++)
Space betweenif (col < row) Console.Write(" ");
Total cellsrows * (rows + 1) / 2

Write vs WriteLine

APIEffectUse for
Console.WriteStays on the same lineEach cell value and spaces between cells
Console.WriteLineEnds the current lineAfter each printed row

Live Preview

Change the row count and the column-wise triangle updates instantly — capped at 9 for readable demos.

Whole numbers from 1 to 9. Tap a chip or type a value — the preview redraws as you go.

Live result rows = 5 · 15 cells
1
2 6
3 7 10
4 8 11 13
5 9 12 14 15

Worked Walkthrough — Fill for rows = 5

Trace how column-wise fill produces the jumps you see when printing row 2 and row 3.

ColumnRows filledValues assigned
11..51 2 3 4 5
22..56 7 8 9
33..510 11 12

Printed row 2 = tri[2, 1], tri[2, 2] → 2 6. Total cells = n(n+1)/2 → O(n²).

C# Programs

Three complete programs: fixed rows = 5, user-input rows, and a compact rows = 3 demo. Use View Output for sample results.

Example 1 — Fixed rows = 5

Hard-coded height — fill with col outer, then print with row outer.

C#
using System;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int rows = 5;
            int[,] tri = new int[rows + 1, rows + 1];
            int col, row, num = 1;

            for (col = 1; col <= rows; col++)
                for (row = col; row <= rows; row++)
                    tri[row, col] = num++;

            for (row = 1; row <= rows; row++)
            {
                for (col = 1; col <= row; col++)
                {
                    Console.Write(tri[row, col]);
                    if (col < row)
                        Console.Write(" ");
                }
                Console.WriteLine();
            }
        }
    }
}

How It Works

1. Fill column-wise. Column 1 gets 1–5; column 2 gets 6–9; column 3 gets 10–12; and so on.

2. Print row-wise. Row 2 reads tri[2, 1] and tri[2, 2] → 2 6.

3. Spaces. Print a space between cells with if (col < row), then WriteLine() after each row.

Example 2 — User Input (rows)

Read the row count, allocate the array, and run the same fill/print logic.

C#
using System;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int rows, col, row, num;

            Console.Write("Enter the number of rows: ");
            if (!int.TryParse(Console.ReadLine(), out rows) || rows < 1)
            {
                Console.WriteLine("Please enter a positive whole number.");
                return;
            }

            int[,] tri = new int[rows + 1, rows + 1];
            num = 1;

            for (col = 1; col <= rows; col++)
                for (row = col; row <= rows; row++)
                    tri[row, col] = num++;

            for (row = 1; row <= rows; row++)
            {
                for (col = 1; col <= row; col++)
                {
                    Console.Write(tri[row, col]);
                    if (col < row)
                        Console.Write(" ");
                }
                Console.WriteLine();
            }
        }
    }
}

How It Works

1. Validate rows. TryParse rejects non-numeric input; require rows >= 1 before allocating.

2. Same core. Fill and print logic matches Example 1 — only rows comes from the user.

3. Readable demos. Cap practice runs at rows ≤ 9 so the console stays easy to scan.

Example 3 — Compact rows = 3

Same fill/print structure with only six cells — easy to trace on paper.

C#
using System;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int rows = 3;
            int[,] tri = new int[rows + 1, rows + 1];
            int col, row, num = 1;

            for (col = 1; col <= rows; col++)
                for (row = col; row <= rows; row++)
                    tri[row, col] = num++;

            for (row = 1; row <= rows; row++)
            {
                for (col = 1; col <= row; col++)
                {
                    Console.Write(tri[row, col]);
                    if (col < row)
                        Console.Write(" ");
                }
                Console.WriteLine();
            }
        }
    }
}

How It Works

1. Six cells. Column 1 gets 1–3; column 2 gets 4–5; column 3 gets 6.

2. Trace on paper. Confirm row 2 prints 2 4 — not consecutive — because of column-wise fill.

Edge Cases & Pitfalls

Check these before calling the solution done.

row outer fill

Consecutive instead of jumps

If you fill with row outer, you get 1, 2 3, 4 5 6… Keep col outer for the column-wise pattern.

0-based mix

Off-by-one indexing

These demos use 1-based tri[row, col]. Mixing 0-based loops with 1-based storage leaves holes or overwrites.

row = 1..rows fill

Upper triangle unused

During fill, start at row = col, not row = 1 — cells above the diagonal are never printed.

WriteLine

Broken rows

If WriteLine sits inside the print inner loop, each value lands on its own line. Call it only after the row finishes.

rows = 1

Single cell

Output is just 1 — a good sanity check for input validation.

Bad input

Convert.ToInt32 throws

Prefer int.TryParse so non-numeric input does not crash before the array is created.

Time and Space Complexity

ProgramTimeExtra space
Fixed / compact (Examples 1, 3)O(n²)O(n²) array
User input (Example 2)O(n²)O(n²) array

Fill and print each touch n(n+1)/2 cells. The 2D array uses O(n²) space (only the lower triangle is used).

Key Takeaways

  • Fill ≠ print: column-wise fill creates the jumps; row-wise print shows the triangle.
  • Fill bound: for each col, assign row = col..rows with num++.
  • Write vs WriteLine: values and spaces stay on the line; WriteLine advances after each row.
  • Next step: Program 56 prints a centered palindromic number pyramid.

One line: fill tri[row, col] = num++ column-wise, then print tri[row, col] row-wise.

Frequently Asked Questions

Because the triangle is filled column-wise: after finishing column 1 (1..5), the next available number is 6 for column 2.
Column-wise filling creates the distinctive jumps (6, 10, 13). Row-wise printing displays the familiar triangle shape.
For rows=5: 1; 2 6; 3 7 10; 4 8 11 13; 5 9 12 14 15 — numbers increase within each column during fill.
Program 54 uses diagonal conditions with spaces. Program 55 uses a 2D array filled column-wise then printed row-wise.
Not strictly, but it keeps fill order and print order separate — much clearer for beginners.
Yes. Loop rows first and you get the standard 1, 2 3, 4 5 6 triangle — compare both approaches.
O(n²) for n rows because total filled/printed values equal n(n+1)/2.
For rows=n, the largest number is n(n+1)/2 — the triangular number of cells.
Prefer int.TryParse(Console.ReadLine(), out rows) so bad input does not throw FormatException.
One row prints a single 1 — fill and print loops each run once.

Did you know?

Numbers are filled column-wise into a 2D array — column 1 gets 1..n, column 2 gets the next block, and so on — then printed row-wise. Total values = n(n+1)/2, so O(n²).

Next: Palindromic Number Pyramid

Continue with a centered pyramid of palindromic rows like 1, 121, 12321.

Program 56 tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful