PHP Inverted Alphabet Triangle Pattern

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

What Is This Pattern?

An inverted alphabet right-angled triangle prints the longest letter run first, then shrinks by one letter each row — still starting from A every time.

Remember
Rule: for end letter $i from last down to A,
      print A through $i

ABCDE
ABCD
ABC
AB
A         ← 5 rows (longest on top)

It is the flip of Program 1: keep the same inner A..$i print, reverse only the outer loop. That mirrors how star Program 2 inverts Program 1. Compare with Program 6, which shrinks from the left instead.

How to Solve It

Two ways to emit the same shape — start with nested letter loops, then optionally shorten with substr.

MethodIdeaBest for
Nested letter loopsOuter = shrinking end; inner = A..endLearning, interviews, exams
substr($letters, 0, $i)Slice shorter prefixes while $i counts downShorter demos once loops click

Pseudocode

Pseudocode
for $end from $lastLetter down to 'A':
    for $ch from 'A' to $end:
        echo $ch
    echo PHP_EOL

Cheat sheet

GoalPattern
Countdown end letterfor ($i = $last; $i >= 'A'; $i--)
Print A..$ifor ($j = 'A'; $j <= $i; $j++) echo $j;
End the rowecho PHP_EOL;
Top letter from rows$top = chr(ord('A') + $rows - 1);
One-line row shortcutecho substr($letters, 0, $i) . PHP_EOL; while $i shrinks
Growing twinfor ($i = 'A'; $i <= $last; $i++) → Program 1

Printing Letters vs Starting a New Line

APIEffectUse for
echoStays on the same lineEach letter
echo PHP_EOLEnds the current lineAfter the inner loop

Print letters without a newline, then end the row once.

Live Preview

Change the row count and the inverted triangle updates instantly — capped at 26 letters (A–Z).

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

Live result 5 rows · 15 letters
ABCDE
ABCD
ABC
AB
A

Worked Walkthrough — $rows = 4

Trace each outer-loop end letter as $i counts down from 'D' to 'A'.

End $iInner $jPrinted rowLetters
'D'A..DABCD4
'C'A..CABC3
'B'A..BAB2
'A'A..AA1

Total letter prints: 4 + 3 + 2 + 1 = 10 = 4×5/2 — same as Program 1, only the print order of rows differs.

PHP Programs

Three complete programs: fixed top letter, CLI input, and a substr shortcut. Use View Output to reveal sample results.

Example 1 — Fixed from 'E' down to 'A'

Hard-coded top letter — outer loop shrinks; inner loop still prints A..$i.

PHP
<?php
for ($i = 'E'; $i >= 'A'; $i--) {
    for ($j = 'A'; $j <= $i; $j++) {
        echo $j;
    }
    echo PHP_EOL;
}

How It Works

1. Outer loop picks the end letter. $i runs from 'E' down to 'A' — longest row first.

2. Inner loop restarts at A. For each $i, $j runs from 'A' to $i, so the row is A..$i.

3. Print letters, then break the line. echo $j stays on the row; echo PHP_EOL after the inner loop starts the next (shorter) row.

When $i = 'E' you get ABCDE; when $i = 'A' you get A.

Example 2 — User Input Version

Read the row count at runtime. Prefer validating with is_numeric and clamp to 26 (shown in the tip below).

PHP
<?php
echo "Enter the number of rows: ";
$rows = (int) trim(fgets(STDIN));
$top = chr(ord('A') + $rows - 1);

for ($i = $top; $i >= 'A'; $i--) {
    for ($j = 'A'; $j <= $i; $j++) {
        echo $j;
    }
    echo PHP_EOL;
}

How It Works

1. Prompt and read. Ask for a row count, then cast the trimmed line to an int.

2. Map rows to a top letter. $top = chr(ord('A') + $rows - 1) — for $rows = 4, $top is 'D'.

3. Same shrink core. Only the source of $top changes — the print logic matches Example 1.

4. Safer input tip. Prefer:

Safer input
$raw = trim(fgets(STDIN));
if (!is_numeric($raw)) {
    echo "Enter a whole number from 1 to 26." . PHP_EOL;
    exit;
}
$rows = (int) $raw;
if ($rows < 1 || $rows > 26) {
    echo "Enter a whole number from 1 to 26." . PHP_EOL;
    exit;
}

Example 3 — substr($letters, 0, $i)

Build each shrinking prefix in one call — same shape, no explicit inner letter loop.

PHP
<?php
$rows = 5;
$letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

for ($i = $rows; $i >= 1; $i--) {
    echo substr($letters, 0, $i) . PHP_EOL;
}

How It Works

1. Count length down. $i runs from $rows down to 1.

2. Slice the prefix. substr($letters, 0, $i) is ABCDE, then ABCD, and so on.

3. Learn loops first. Use Examples 1–2 when you need to show nested bounds; treat this as a polish shortcut afterward.

Edge Cases & Pitfalls

Check these before calling the solution done.

$i++

Growing triangle by mistake

If you increment $i from 'A' to $top, you reprint Program 1. Use $i-- from $top down to 'A'.

Stop at B

Missing final A

Stopping before 'A' drops the tip row. The condition must be $i >= 'A'.

PHP_EOL inside

Column of letters

If echo PHP_EOL is inside the inner loop, each letter lands on its own line. Use echo for letters; break the row only after the inner loop.

$rows > 26

Past Z

chr(ord('A') + $rows - 1) leaves A–Z when $rows > 26. Clamp or reject in interactive programs.

$rows = 1

Single A

Output is just A — longest and shortest coincide. A good sanity check.

Bad input

Use is_numeric

Bare (int) fgets(STDIN) turns letters into 0 — validate before the outer loop.

Time and Space Complexity

ProgramTimeExtra space
Nested loops (Examples 1–2)O(rows²)O(1)
substr (Example 3)O(rows²)O(rows) per temporary row string

Total letters = n + (n - 1) + … + 1 = n(n + 1)/2 — still quadratic in n. Same totals as Program 1.

Key Takeaways

  • Rule: countdown end letter $i; print A through $i each row.
  • Flip of Program 1: same inner loop — only reverse the outer loop.
  • Break the row: call echo PHP_EOL only after the inner loop.
  • Complexity: O(n²) time; O(1) extra space for nested loops.

One line: for $i from the top letter down to 'A', print A through $i, then echo PHP_EOL.

Frequently Asked Questions

The outer loop counts down so the first row prints the most letters and each next row prints one fewer. The inner loop still prints from A up to the current bound.
Because the inner loop always starts at A. That resets the sequence each row, producing ABCDE then ABCD and so on.
Program 1 grows row length (A, AB, ABC). This pattern shrinks it (ABCDE, ABCD, ABC). Only the outer loop direction changes; the inner loop is the same A..i print.
Program 4 grows while printing backward (A, BA, CBA). This pattern shrinks while printing forward from A (ABCDE, ABCD, ABC).
echo stays on the same line. echo PHP_EOL ends the current line. Letters use echo; the row break uses echo PHP_EOL after the inner loop.
O(n²) for n rows, because total printed characters are n(n+1)/2.
Yes. Keep a string of A–Z and print substr($letters, 0, $i) while $i counts down from $rows to 1. Nested letter loops are better for learning; substr is a handy shortcut later.
Use trim(fgets(STDIN)) and check is_numeric($input) before casting to int, then clamp rows between 1 and 26 so bad input does not walk past Z.

Did you know?

This is the inverted twin of Program 1: same inner A..$i print, only the outer loop shrinks. For 5 rows: ABCDE, ABCD, ABC, AB, A. Total letters still equal n(n+1)/2.

Next: Increasing Start Letter

Keep a fixed end letter and move the start letter right each row.

Program 6 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