Reverse Alphabet Triangle in Python

Beginner
⏱️ 8 min read
📚 Updated: Aug 2026
🎯 3 Code Examples
🚀 Live Preview
Nested Loops + range(-1)

What You’ll Learn

The reverse alphabet triangle grows each row by one letter, but every row counts down to A instead of up from it. This tutorial covers the shape rule, descending inner loop, a live preview, algorithm steps, worked Python examples, edge cases, and complexity.

Shape Rule

Current letter down to A

Row 0 prints A, row 1 prints BA, row 2 prints CBA, up to EDCBA for five rows.

Outer Loop

Rows

for i in range(rows): picks the starting letter for each row (0-based index).

Inner Loop

Descending letters

for code in range(base + i, base - 1, -1): prints from the current letter down to A.

print end= vs print()

Same line / next line

Letters use print(..., end=""); end each row with print().

Live Preview

1–26 rows

Pick a row count and draw the reverse alphabet triangle instantly in the browser.

O(n²)

Complexity

Total letters = n(n+1)/2 — same triangular count as Program 1; extra memory stays O(1).

Introduction

A reverse alphabet triangle grows by one letter per row, but each line counts down to A instead of up from it. With five rows the console shows A, BA, CBA, DCBA, EDCBA.

In Python you solve it with two nested for loops: the outer loop picks the row index, the inner loop walks letter codes downward with range(..., -1), then print() moves to the next line.

Why it matters?

It teaches reverse iteration with range(step=-1) and the exclusive stop at base - 1 — skills you reuse in inverted patterns, pyramids, and more advanced letter shapes.

Key Highlights

Row = Descending Run

On row i, print letters from chr(ord('A') + i) down to A.

Descending Inner Loop

range(base + i, base - 1, -1) walks codes downward.

print Then Break

print(chr(code), end="") in the inner loop; print() after.

Compare Program 1

Same outer growth — inner direction flips from ascending to descending.

In short: for each row index i from 0 to rows - 1, print letters from chr(ord('A') + i) down to A with print(chr(code), end=""), then call print().

📝 Problem & Approach

Given a positive integer rows, print a left-aligned reverse alphabet triangle where row i starts at the i-th letter and counts down to A.

Python
# First 5 rows (conceptual shape)
# A
# BA
# CBA
# DCBA
# EDCBA

Inputs & Outputs

ItemTypeDescription
rowsintNumber of triangle lines to print (typically ≥ 1).
Printed outputtextLeft-aligned rows; row i (0-based) has letters from chr(ord('A') + i) down to A.

Minimal workflow

Pseudocode
for i from 0 to rows - 1:
    for code from (A + i) down to A:
        print letter (no newline)
    print newline

Approach comparison

ApproachIdeaBest for
Nested loops (descending inner)Outer rows + inner codes down to ALearning and interviews
letters[i::-1]Reverse slice for the whole rowShorter production-style demos

⚡ Quick Reference

GoalPattern
Walk each rowfor i in range(rows):
Print current letter down to Afor code in range(base + i, base - 1, -1): print(chr(code), end="")
End the rowprint()
One-line row shortcutprint(letters[i::-1])
Ascending variantInner loop up from A — see Program 1

📋 Ascending inner vs descending inner vs slice

Three ways to emit each row — compare inner-loop direction and the letters[i::-1] shortcut.

Ascending inner (Program 1)
A..end

range(base, base + i) — row grows from A upward (AB, ABC)

Descending inner (this page)
end..A

range(base + i, base - 1, -1) — row starts at current letter and counts down to A

letters[i::-1]
whole row

Reverse slice from index i to start — skip the inner loop entirely

Learning tip
loops first

Master descending range(..., -1) before the reverse-slice shortcut

Context

When This Pattern Shows Up

Reach for this pattern when teaching descending inner loops or contrasting with Program 1’s ascending rows.

  1. Descending inner-loop practice

    Natural follow-up after Program 1 — same outer growth, inner loop counts down with step -1.

  2. Nested-loop warm-up

    Practice range(base + i, base - 1, -1) with an immediate visual check.

  3. CLI I/O practice

    Combine loops with input() for a flexible row count.

  4. Gateway to variants

    Leads to Program 3’s fixed-top rows and Program 5’s decreasing width pattern.

  5. Not a UI layout tool

    This is a console teaching pattern — not how you build modern app screens.

Key benefit: one small program that locks in reverse inner loops, the exclusive base - 1 stop, and O(n²) thinking.

🔮 Live Preview

Choose a row count between 1 and 26 and draw the reverse alphabet triangle in the browser.

Try 5, 7, or 10. Cap is 26 letters (A–Z).

Live result
Press "Draw pattern".

Examples Gallery

Three complete Python programs — fixed row count, CLI input, and a letters[i::-1] shortcut. Click View Output to reveal sample console results.

📚 Getting Started

Print five rows with classic nested loops — each row counts down to A.

Example 1 — Fixed rows = 5

Hard-coded height — ideal for first demos and screenshots.

Python
rows = 5

base = ord('A')

for i in range(rows):
    for code in range(base + i, base - 1, -1):
        print(chr(code), end="")
    print()

How It Works

When i = 0, the inner loop prints A. When i = 2, it prints CBA, and when i = 4 it prints EDCBA. print() after the inner loop starts the next row.

📈 Practical Variant

Let the user choose the height at runtime.

Example 2 — User Input Version

Read the row count with input() and convert with int() (wrap in try/except ValueError in real apps).

Python
rows = int(input("Enter the number of rows (max 26): "))
rows = max(1, min(rows, 26))

base = ord('A')

for i in range(rows):
    for code in range(base + i, base - 1, -1):
        print(chr(code), end="")
    print()

How It Works

Same ord/chr core as Example 1; only the source of rows changes. The inner loop still counts down to A on every row. Non-numeric input raises ValueError with bare int(input()) — use try/except for safer labs.

⚡ Shortcut Style

Same shape without an explicit inner letter loop.

Example 3 — letters[i::-1]

Reverse-slice from index i to the start of the alphabet string for each row.

Python
rows = 5
rows = max(1, min(rows, 26))
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

for i in range(rows):
    print(letters[i::-1])

How It Works

letters[i::-1] returns letters from index i down to index 0 — exactly the reverse row shape. Great once you understand the nested-loop idea; keep the two-loop version for exams that ask you to show descending bounds.

🧠 How the Algorithm Prints Rows

1

Set up

Use input() when reading input. Set rows (fixed or from CLI) and base = ord('A').

Setup
2

Outer loop (rows)

for i in range(rows): selects the starting letter index for the current line.

Row
3

Inner loop (letters)

for code in range(base + i, base - 1, -1): prints each letter downward with print(chr(code), end="").

Letters
4

New line

print() ends the row so the next outer iteration starts fresh.

Break
=

Reverse alphabet triangle complete

Total letters: 1+2+…+n = n(n+1)/2O(n²) time, O(1) extra memory.

🔎 Worked Walkthrough — rows = 5

Trace each outer-loop index and see what the descending inner loop prints down to A.

Row index iInner code rangePrinted rowLetters this row
0A..AA1
1B..ABA2
2C..ACBA3
3D..ADCBA4
4E..AEDCBA5

Total letter prints: 1 + 2 + 3 + 4 + 5 = 15 = 5×6/2.

Use Cases

Where this reverse triangle (and its descending inner loop) shows up beyond the homework prompt.

1. Teaching Descending range()

Clearest visual proof that range(start, stop, -1) needs an exclusive stop one below the last value.

Example: change stop from base - 1 to base and watch A disappear.

2. Contrast with Program 1

Same growing row width — only inner direction changes from ascending to descending.

Example: side-by-side output of AB vs BA on row 2.

3. Console Formatting Drills

Practice character loops with step -1 and print(..., end="")/print() without complex math.

Example: accidentally use an ascending inner loop and get Program 1’s shape.

4. Character Substitution

Swap to lowercase or digits once the descending letter loop works.

Example: print lowercase edcba with ord('a') as base.

5. Complexity Intuition

Triangular totals make O(n²) concrete for beginners.

Example: count printed letters for n = 10 → 55.

6. Input Validation Labs

Pair the pattern with try/except ValueError and positive-row checks.

Example: reject rows <= 0 and re-prompt.

Pro Tip: when an interviewer asks for patterns, explain why the inner stop is base - 1 — that detail separates a working reverse row from a missing A.

Advantages

Why this reverse triangle earns a spot in beginner Python pattern courses.

  1. 1. Teaches range(step=-1)

    Wrong stop values show up immediately — rows missing A or printing extra codes.

  2. 2. Minimal Concepts

    Only loops and console output — no arrays or math libraries.

  3. 3. Easy to Contrast

    Flip inner direction to recover Program 1; compare with Program 3’s fixed-top rows and Program 5’s shrinking width.

  4. 4. O(1) Extra Memory

    Streaming output needs no storage beyond loop counters.

Pro Tip: learn the nested-loop version first; treat letters[i::-1] as a polish shortcut afterward.

Usage Tips

Small habits that keep alphabet-pattern code clean.

  1. 1. Name Bounds Clearly

    Use rows (or n) and keep i/j for row/column — or rename to row/col.

  2. 2. Wrap int(input()) in try/except

    Avoid crashes when the user types letters instead of a number.

  3. 3. Keep print() Outside

    Only call print() after the inner loop finishes the row.

  4. 4. Use base = ord('A')

    Prefer ord('A') over hardcoded 65 — clearer intent and easier to switch to lowercase.

  5. 5. Dry-Run One Small n

    Trace rows = 3 on paper — confirm range(base + i, base - 1, -1) includes A.

Pro Tip: if the output is a vertical list of single letters, you almost certainly put print() inside the inner loop.

Common Pitfalls

Mistakes that commonly break reverse alphabet triangle patterns.

  1. 1. print() Inside the Inner Loop

    Each letter lands on its own line — you get a column, not a triangle.

    → Use print(..., end="") for letters; print() only after the inner loop.

  2. 2. Wrong Stop in range()

    Using base as the stop skips A; using base - 2 may print unwanted characters below A.

    → For this shape, keep range(base + i, base - 1, -1) so A is included.

  3. 3. Ascending Inner Loop by Mistake

    range(base, base + i) prints Program 1’s shape (AB, not BA).

    → Use step -1 and start at base + i, not at base.

  4. 4. Hardcoded 65 Instead of ord('A')

    Magic ASCII numbers work but obscure intent and break when switching to lowercase.

    → Always set base = ord('A') and derive codes from base + i.

  5. 5. Blind int(input())

    Non-numeric input raises ValueError with bare int(input()).

    → Wrap in try/except ValueError and validate range.

  6. 6. Forgetting the Row Break

    Omitting print() after the inner loop glues every letter onto one endless line.

    → Always end the row after the inner loop.

Edge Cases

Check these inputs before calling the solution done.

rows = 1

Single letter

Output is just A on one line.

rows = 0

Empty pattern

Outer loop never runs — print nothing or show a message.

Negative

rows < 0

Treat as invalid; re-prompt instead of silent empty output.

Large n

Many rows

Output grows as n²/2 characters — fine for labs, noisy for huge n.

Bad input

Non-numeric input

int(input()) raises ValueError — validate first.

Fill char

Not only uppercase

Same loops work with #, digits, or letters.

🎯 Practice Problems

Try these variations to lock in the reverse pattern.

1. Compare with Program 1

  • Print both shapes side by side for rows = 5
  • Spot ascending vs descending inner loops

2. Print lowercase rows

  • Use base = ord('a') with the same logic
  • Output becomes a, ba, cba, …

3. Safe input loop

  • Use try/except ValueError until rows >= 1
  • Clamp to 26 for A–Z demos

4. Slice-only version

  • Rewrite Example 1 using only letters[i::-1]
  • Confirm output matches the nested-loop version

Notes

  • Exclusive stop. range(base + i, base - 1, -1) includes A because range stops before base - 1.
  • Program 1 vs this page. Same row width growth — Program 1 inner loop ascends from A; here it descends to A.
  • Validate rows > 0 for interactive programs; rows = 1 should print a single A.
  • Program 3 keeps a fixed top letter per row; Program 5 shrinks row width — both differ from this descending-inner pattern.

Quick Takeaway: outer loop picks the start letter, inner loop counts down to A with step -1, then break the line — that is the whole pattern.

⏱️ Time and Space Complexity

ProgramTimeExtra space
Nested loops (Examples 1–2)O(rows²)O(1)
letters[i::-1] (Example 3)O(rows²)O(rows) per row string (temporary)
Wrap Up

🎉 Conclusion

The reverse alphabet triangle is a focused nested-loop exercise with lasting payoff: descending inner bounds, the exclusive base - 1 stop, and O(n²) intuition. Master the classic two-loop version, then optionally shorten rows with letters[i::-1].

Practice the three examples above, then continue to Program 5 for the decreasing-width pattern (ABCDE down to A).

Row i prints from chr(ord('A') + i) down to A — keep print(..., end="") for letters, print() for the break, and validate row counts when reading input.

💡 Best Practices

✅ Do

  • Explain outer = start letter index, inner = descending codes before coding
  • Use range(base + i, base - 1, -1) so every row ends at A
  • Prefer base = ord('A') over hardcoded ASCII values
  • Validate rows ≥ 1 and clamp to 26 for A–Z demos
  • State O(n²) time when asked about complexity

❌ Don’t

  • Use an ascending inner loop by mistake (range(base, base + i))
  • Set the range stop to base — that skips A
  • Call print() inside the inner letter loop
  • Hardcode 65 instead of ord('A')
  • Skip the rows = 1 edge case

Key Takeaways

Knowledge Unlocked

Five things to remember about this reverse alphabet pattern

Print each row from the current letter down to A.

5
Core concepts
02

Outer loop

range(rows) picks start

Code
03

Inner loop

Step -1 down to A

Code
04

Stop at base-1

Includes letter A

Bounds
O 05

Complexity

O(n²) time

Analysis

❓ Frequently Asked Questions

The outer loop picks the row index i (0-based). The inner loop walks letter codes from ord('A') + i down to ord('A') using range(base + i, base - 1, -1), so row 0 is A, row 1 is BA, row 2 is CBA, and so on.
range stops before its end value. Using base - 1 as the exclusive stop ensures the last printed code is base (letter A). Stopping at base would skip A on every row.
print(chr(code), end="") stays on the same line. print() ends the current line. Letters use end=""; the row break uses print() after the inner loop.
Program 1 ascends from A on every row (inner loop goes up). This pattern starts at the current row letter and counts down to A (inner loop goes down with step -1).
O(n²) where n is the number of rows. Total printed characters equal 1+2+…+n = n(n+1)/2 — same triangular count as Program 1.
Yes. Keep letters = "ABCDEFG..." and print(letters[i::-1]) for each row index i. Nested ord/chr loops teach the bounds; reverse slicing is a compact shortcut.
Use a try/except ValueError around int(input()), or check raw.isdigit() before converting, then clamp rows between 1 and 26 so letter codes stay within A–Z.
Letter codes walk past Z and print unexpected characters. Clamp to 26 for A–Z demos, or define a clear error/wrap policy.

Did you Know? 🔊

Row index i (0-based) prints letters from chr(ord('A') + i) down to A using range(base + i, base - 1, -1). Total letters for n rows is still n(n+1)/2 — compare Program 1 (ascending from A each row) and Program 5 (decreasing row width from ABCDE to A).

Continue to Program 5

Shrink each row from ABCDE down to A — the decreasing alphabet pattern.

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