Reverse Alphabet Triangle in JavaScript

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

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 JavaScript 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 (let i = 0; i < rows; i++) picks the starting letter for each row (0-based index).

Inner Loop

Descending letters

for (let code = base + i; code >= base; code--) prints from the current letter down to A.

line vs console.log

Same line / next line

Letters use line += String.fromCharCode(code); end each row with console.log(line).

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 JavaScript you solve it with two nested for loops: the outer loop picks the row index, the inner loop walks letter codes downward with code--, then console.log(line) moves to the next line.

Why it matters?

It teaches reverse iteration with code-- and the inclusive stop at code >= base — skills you reuse in inverted patterns, pyramids, and more advanced letter shapes.

Key Highlights

Row = Descending Run

On row i, print letters from String.fromCharCode("A".charCodeAt(0) + i) down to A.

Descending Inner Loop

for (let code = base + i; code >= base; code--) walks codes downward.

print Then Break

line += String.fromCharCode(code) in the inner loop; console.log(line) 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 String.fromCharCode("A".charCodeAt(0) + i) down to A with line += String.fromCharCode(code), then call console.log(line).

📝 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.

JavaScript
// 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 String.fromCharCode("A".charCodeAt(0) + 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.slice(0, i + 1).split("").reverse().join("")Reverse slice for the whole rowShorter production-style demos

⚡ Quick Reference

GoalPattern
Walk each rowfor (let i = 0; i < rows; i++)
Print current letter down to Afor (let code = base + i; code >= base; code--) { line += String.fromCharCode(code); }
End the rowconsole.log(line)
One-line row shortcutconsole.log(letters.slice(0, i + 1).split("").reverse().join(""))
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.slice(0, i + 1).split("").reverse().join("") shortcut.

Ascending inner (Program 1)
A..end

for (code = base; code <= base + i; code++) — row grows from A upward (AB, ABC)

Descending inner (this page)
end..A

for (let code = base + i; code >= base; code--) — row starts at current letter and counts down to A

letters.slice(0, i + 1).split("").reverse().join("")
whole row

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

Learning tip
loops first

Master descending code-- 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 for (let code = base + i; code >= base; code--) with an immediate visual check.

  3. prompt() input practice

    Combine loops with prompt() 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 inclusive code >= base 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 JavaScript programs — fixed row count, prompt input, and a slice-reverse shortcut. Click View Output to reveal sample console results, or Try it Yourself to run in the browser editor.

📚 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.

JavaScript
const rows = 5;
const base = "A".charCodeAt(0);

for (let i = 0; i < rows; i++) {
  let line = "";
  for (let code = base + i; code >= base; code--) {
    line += String.fromCharCode(code);
  }
  console.log(line);
}
Try it Yourself

How It Works

When i = 0, the inner loop builds A. When i = 2, it builds CBA, and when i = 4 it builds EDCBA. console.log(line) 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 prompt() and convert with parseInt() (validate with Number.isFinite in real apps).

JavaScript
const rowsInput = prompt("Enter the number of rows (max 26):");
let rows = parseInt(rowsInput, 10);
rows = Math.max(1, Math.min(rows, 26));

const base = "A".charCodeAt(0);

for (let i = 0; i < rows; i++) {
  let line = "";
  for (let code = base + i; code >= base; code--) {
    line += String.fromCharCode(code);
  }
  console.log(line);
}
Try it Yourself

How It Works

Same charCodeAt/fromCharCode core as Example 1; only the source of rows changes. The inner loop still counts down to A on every row. Non-numeric input returns NaN with bare parseInt(prompt()) — validate with Number.isFinite for safer labs.

⚡ Shortcut Style

Same shape without an explicit inner letter loop.

Example 3 — letters.slice(0, i + 1) reversed

Slice from the start through index i, then reverse for each row.

JavaScript
const rows = 5;
const clampedRows = Math.max(1, Math.min(rows, 26));
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

for (let i = 0; i < clampedRows; i++) {
  console.log(letters.slice(0, i + 1).split("").reverse().join(""));
}
Try it Yourself

How It Works

letters.slice(0, i + 1).split("").reverse().join("") 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 prompt() when reading input. Set rows (fixed or from user) and base = "A".charCodeAt(0).

Setup
2

Outer loop (rows)

for (let i = 0; i < rows; i++) selects the starting letter index for the current line.

Row
3

Inner loop (letters)

for (let code = base + i; code >= base; code--) prints each letter downward with line += String.fromCharCode(code).

Letters
4

New line

console.log(line) 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 Loops

Clearest visual proof that a descending loop must use code >= base so the final letter A is included.

Example: change >= to > 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 line += String.fromCharCode(code)/console.log(line) 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 "A".charCodeAt(0) 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 Number.isFinite checks and positive-row validation.

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

Pro Tip: when an interviewer asks for patterns, explain why the condition is code >= base — that detail separates a working reverse row from a missing A.

Advantages

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

  1. 1. Teaches code--

    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.slice(0, i + 1).split("").reverse().join("") 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. Validate prompt() input

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

  3. 3. Keep console.log(line) Outside

    Only call console.log(line) after the inner loop finishes the row.

  4. 4. Use base = "A".charCodeAt(0)

    Prefer "A".charCodeAt(0) over hardcoded 65 — clearer intent and easier to switch to lowercase.

  5. 5. Dry-Run One Small n

    Trace rows = 3 on paper — confirm for (let code = base + i; code >= base; code--) includes A.

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

Common Pitfalls

Mistakes that commonly break reverse alphabet triangle patterns.

  1. 1. console.log(line) Inside the Inner Loop

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

    → Use line += String.fromCharCode(code) for letters; console.log(line) only after the inner loop.

  2. 2. Stopping Before A

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

    → For this shape, keep for (let code = base + i; code >= base; code--) so A is included.

  3. 3. Ascending Inner Loop by Mistake

    for (code = base; code <= base + i; code++) 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 "A".charCodeAt(0)

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

    → Always set base = "A".charCodeAt(0) and derive codes from base + i.

  5. 5. Blind parseInt(prompt())

    Non-numeric input yields NaN with bare parseInt(prompt()).

    → Check with Number.isFinite and clamp the range.

  6. 6. Forgetting the Row Break

    Omitting console.log(line) 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

parseInt(prompt()) can yield NaN — validate with Number.isFinite 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 = "a".charCodeAt(0) with the same logic
  • Output becomes a, ba, cba, …

3. Safe input loop

  • Use Number.isFinite until rows >= 1
  • Clamp to 26 for A–Z demos

4. Slice-only version

  • Rewrite Example 1 using only letters.slice(0, i + 1).split("").reverse().join("")
  • Confirm output matches the nested-loop version

Notes

  • Inclusive stop. for (let code = base + i; code >= base; code--) includes A because the condition keeps running while code >= base.
  • 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.slice(0, i + 1).split("").reverse().join("") (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 inclusive code >= base stop, and O(n²) intuition. Master the classic two-loop version, then optionally shorten rows with letters.slice(0, i + 1).split("").reverse().join("").

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

Row i prints from String.fromCharCode("A".charCodeAt(0) + i) down to A — keep line += String.fromCharCode(code) for letters, console.log(line) for the break, and validate row counts when reading input.

💡 Best Practices

✅ Do

  • Explain outer = start letter index, inner = descending codes before coding
  • Use for (let code = base + i; code >= base; code--) so every row ends at A
  • Prefer base = "A".charCodeAt(0) 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 (for (code = base; code <= base + i; code++))
  • Use code > base instead of >= — that skips A
  • Call console.log(line) inside the inner letter loop
  • Hardcode 65 instead of "A".charCodeAt(0)
  • 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

for (let i = 0; i < rows; i++) 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 "A".charCodeAt(0) + i down to "A".charCodeAt(0) using for (let code = base + i; code >= base; code--), so row 0 is A, row 1 is BA, row 2 is CBA, and so on.
Stopping with code > base skips A on every row. Using code >= base includes the final letter A.
line += String.fromCharCode(code) builds the full row string. console.log() inside the inner loop would log one letter per line. Log once after the inner loop finishes.
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 code--).
O(n²) where n is the number of rows. Total logged characters equal 1+2+…+n = n(n+1)/2 — same triangular count as Program 1.
Yes. Keep letters = "ABCDEFG..." and console.log(letters.slice(0, i + 1).split("").reverse().join("")) for each row index i. Nested charCode loops teach the bounds; slice plus reverse is a compact shortcut.
Use parseInt with Number.isFinite after prompt(), then clamp rows between 1 and 26 so letter codes stay within A–Z.
Letter codes walk past Z and log unexpected characters. Clamp to 26 for A–Z demos, or define a clear error/wrap policy.

Did you Know? 🔊

Row index i (0-based) logs letters from String.fromCharCode("A".charCodeAt(0) + i) down to A using for (let code = base + i; code >= base; code--). 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