PHP Number Triangle Pattern (Left-Shifted)

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

What Is This Pattern?

A left-shifted descending number triangle starts each row at $i and prints through $rows, so the left edge moves right as the row shortens.

Remember
Rule: for i = 1..n, print j = i..n

12345
2345
345
45
5   ← 5 rows

In PHP the outer loop picks the row start $i, the inner loop prints $j from $i to $rows with echo $j, then echo PHP_EOL ends the row. Program 1 is the twin that shrinks from the right (12345, 1234, 123…).

How to Solve It

Outer loop from 1 to $rows. Inner loop from current $i to $rows. End each row with echo PHP_EOL.

MethodIdeaBest for
Nested loopsOuter picks start $i; inner prints $i..$rowsLearning, interviews, exams
String concatBuild each row, then echo onceLeaner demos once loops click

Pseudocode

Pseudocode
for i from 1 to rows:
    for j from i to rows:
        print j (no newline)
    print newline

Cheat sheet

GoalPattern
Pick row startfor ($i = 1; $i <= $rows; $i++)
Print $i..$rowsfor ($j = $i; $j <= $rows; $j++) echo $j;
End the rowecho PHP_EOL;
String form$row .= $j; then echo $row . PHP_EOL;
Program 1 twinfor ($i = $rows; $i >= 1; $i--) with $j = 1..$i

Printing Numbers vs Starting a New Line

APIEffectUse for
echo $jStays on the same lineEach digit in the run
echo PHP_EOLEnds the current lineAfter the inner loop

Print all digits without a newline, then end the row once.

Live Preview

Change the row count and the left-shifted triangle updates instantly — capped at 9 so every digit stays a single character.

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

Live result 5 rows · 15 digits
12345
2345
345
45
5

Worked Walkthrough

Trace $rows = 4 — each outer-loop value of $i, the inner range, and the printed row.

$iInner $jLengthPrinted row
11..441234
22..43234
33..4234
44..414

Total digits are 4+3+2+1 = 10 — the triangular number n(n+1)/2.

PHP Programs

Three complete programs: fixed height, CLI input, and a string-concatenation shortcut. Use View Output for sample results.

Example 1 — Fixed $rows = 5

Outer loop picks start $i; inner loop prints $i..$rows.

PHP
<?php
$rows = 5;

for ($i = 1; $i <= $rows; $i++) {
    for ($j = $i; $j <= $rows; $j++) {
        echo $j;
    }
    echo PHP_EOL;
}
?>

How It Works

1. Outer picks the start. $i runs from 1 to $rows — that value is where each row begins.

2. Inner prints the run. $j goes from $i to $rows with echo $j (no spaces).

3. End the row. echo PHP_EOL; after the inner loop starts the next shorter row.

Example 2 — User Input

Read the row count from the CLI. Prefer is_numeric in real apps (shown in the tip below).

PHP
<?php
echo "Enter the number of rows: ";
$rows = (int) trim(fgets(STDIN));

for ($i = 1; $i <= $rows; $i++) {
    for ($j = $i; $j <= $rows; $j++) {
        echo $j;
    }
    echo PHP_EOL;
}
?>

How It Works

1. Read rows. Ask for a row count, then trim(fgets(STDIN)) and cast to int.

2. Same nested loops. Four rows start at 1234 and end at 4.

3. Safer input tip. Bare (int) casts turn letters into 0. Prefer:

Safer input
echo "Enter the number of rows: ";
$input = trim(fgets(STDIN));
if (!is_numeric($input) || (int) $input < 1) {
    echo "Enter a positive whole number." . PHP_EOL;
    exit(1);
}
$rows = (int) $input;

Example 3 — String Concatenation

Build each row as a string, then print once — same shape, different output style.

PHP
<?php
$rows = 5;

for ($i = 1; $i <= $rows; $i++) {
    $row = "";
    for ($j = $i; $j <= $rows; $j++) {
        $row .= $j;
    }
    echo $row . PHP_EOL;
}
?>

How It Works

1. Same bounds. Outer and inner ranges match Example 1.

2. Append, then echo. $row .= $j builds the line; echo $row . PHP_EOL prints it once.

3. Same shape. Identical output to Example 1 — keep the nested-loop version for exams that expect two loops.

Edge Cases & Pitfalls

Check these before calling the solution done.

wrong twin

for ($j = 1; $j <= $i; $j++)

That reprints Program 1 / Program 5 shapes. Keep the inner start at $i for this left-shift.

PHP_EOL inside

echo PHP_EOL inside the inner loop

That puts each digit on its own line. Print digits without a newline; call echo PHP_EOL only after the row finishes.

rows = 1

Single digit

Output is just 1 — a good sanity check.

rows ≤ 0

Empty output

The outer loop never runs. Validate and prompt again for clearer UX.

multi-digit

$rows > 9

echo 10 prints two characters. Labs usually stick to 1–9 for a clean single-digit look.

spaces

Do not add spaces between digits

The classic sample is concatenated (2345), not spaced (2 3 4 5).

Time and Space Complexity

ProgramTimeExtra space
Nested loops (Examples 1–2)O(n²)O(1)
String concatenation (Example 3)O(n²)O(1) beyond the row string

There are n rows printing n+(n-1)+…+1 digits, so total work is n(n+1)/2.

Key Takeaways

  • Rule: for each $i from 1 to $rows, print digits $i..$rows.
  • Inner start: $j = $i is what shifts the left edge right each row.
  • echo vs PHP_EOL: digits stay on the line; echo PHP_EOL advances after each row.
  • Next step: Program 3 reverses the digit order on each shrinking row.

One line: for each start $i, print $i..$rows with echo $j, then echo PHP_EOL.

Frequently Asked Questions

The inner loop starts at $j = $i, not $j = 1. When $i increases (1, 2, 3, ...), each row begins at that value and prints until $rows.
Because each next row starts at a higher $i, numbers below $i are not printed anymore — the triangle shifts left visually.
echo $j stays on the same line. echo PHP_EOL ends the current line. Digits use echo; the row break uses echo PHP_EOL after the inner loop.
Program 1 counts the outer loop down and prints 1..$i (12345, 1234, 123…). Program 2 counts up and prints $i..$rows (12345, 2345, 345…) — same total prints, different shape.
Yes. Append each digit to a string with $row .= $j, then echo the row with PHP_EOL — same shape with a different output style.
O(n²) for n rows because total prints are n+(n-1)+…+1 = n(n+1)/2.
Use trim(fgets(STDIN)) and check is_numeric($input) before casting to int so bad input does not produce unexpected results.
The outer loop never runs, so nothing is printed. Validate and prompt again if you want a clear user message.

Did you know?

Each row starts at $i and prints through $rows, so the left edge shifts right each line — still O(n²) total prints for n rows.

Next: Reverse Descending Triangle

Continue with rows that count down instead of up.

Program 3 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.

12 people found this page helpful