Mixed Alphabet Pattern (Descending Prefix + Ascending Suffix) in JavaScript

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

What You’ll Learn

Each row stitches together a descending prefix from the row start letter down to A and an ascending suffix from B up to a shrinking end letter: ABCDE, BABCD, CBABC, DCBAB, EDCBA for five rows. Two inner loops per row teach opposite directions on the same line. Compare with Program 26 (cyclic rotation). Includes a live preview, worked JavaScript examples, edge cases, and complexity.

Mixed Rule

Descend then ascend

Every row prints exactly rows letters: prefix down to A, suffix up from B.

Prefix Loop

start → A

for (let code = start; code >= base; code--) appends the descending part.

Suffix Loop

B → end

for (let code = base + 1; code <= end; code++) fills the ascending tail - skips A.

charCodeAt / fromCharCode

Letter codes

base = "A".charCodeAt(0), top = base + rows - 1, start = base + r, end = top - r.

Live Preview

1–26 rows

Pick a row count and draw the mixed alphabet pattern in the browser instantly.

O(n²)

Complexity

n rows × n letters per row = total characters; extra memory stays O(1).

Introduction

A mixed alphabet pattern prints fixed-width rows where each line begins with a descending run from the row start letter down to A, then continues with an ascending run from B to a shrinking end letter. Row 1 is pure ascending; the last row is pure descending.

In JavaScript you solve it with an outer loop over row index r, two inner loops (descending prefix then ascending suffix), and charCodeAt(0)/String.fromCharCode() - or build each row in an array and console.log(row.join("")) for clarity.

Why it matters?

It teaches opposite loop directions on one row - descending then ascending - and the subtle rule of skipping A in the suffix so the join point is not duplicated. The same split appears in palindrome builders and symmetric string patterns.

Key Highlights

Fixed Width

Every row prints exactly rows letters - prefix plus suffix always sum to rows.

Shrinking End

end = top - r shrinks each row so the suffix gets shorter as the prefix grows.

Skip A in Suffix

Suffix starts at B (base + 1) - never duplicate A at the join.

Not Program 26

Program 26 wraps cyclically - BCDEA. Here row 2 is BABCD, not BCDEA.

In short: set base = "A".charCodeAt(0) and top = base + rows - 1, loop r from 0 to rows - 1, compute start = base + r and end = top - r, append descending prefix, ascending suffix from B, then console.log(line) for the newline.

📝 Problem & Approach

Given a positive integer rows, print rows lines of exactly rows uppercase letters each. Row 1 descends from A only in the prefix then ascends to the top; each next row starts one letter later and ends one letter earlier.

JavaScript
// First 5 rows
# ABCDE
# BABCD
# CBABC
# DCBAB
# EDCBA

Inputs & Outputs

ItemTypeDescription
rowsintNumber of rows and width of each row. Clamp to 1–26 for A–Z demos.
Printed outputtextFixed-width uppercase rows: descending prefix + ascending suffix - no spaces between letters.

Minimal workflow

Pseudocode
base = "A".charCodeAt(0)
top = base + rows - 1
for r from 0 to rows-1:
    start = base + r
    end = top - r
    line = ""
    append letters start..A (descending)
    append letters B..end (ascending)
    console.log(line)

Approach comparison

ApproachIdeaBest for
Two inner loopsDescend start..base + ascend (base+1)..endLearning charCodeAt/fromCharCode and opposite loop directions
Join arrayBuild row in an array, console.log(row.join(""))Clearer debugging and row inspection
Program 26 contrastSee Program 26 (ABCDE, BCDEA, …)Cyclic rotation with wrap-around

⚡ Quick Reference

GoalPattern
Bound the alphabetbase = "A".charCodeAt(0); top = base + rows - 1
Outer loop (row index)for (let r = 0; r < rows; r++)
Row boundsstart = base + r; end = top - r
Prefix (descending)for (let code = start; code >= base; code--) line += String.fromCharCode(code)
Suffix (ascending)for (let code = base + 1; code <= end; code++) line += String.fromCharCode(code)
End the rowconsole.log(line)
List join variantrow.push(String.fromCharCode(code)); console.log(row.join(""))

📋 Descending Prefix vs Ascending Suffix vs Join List

Three ways to think about the same mixed rows - pick based on what you are learning.

Prefix loop
for (code = start; code >= base; code--)
start..A

Prints from the row start letter down to A - row 1 prefix is just A.

Suffix loop
for (code = base+1; code <= end; code++)
B..end

Fills the ascending tail from B - skips A to avoid duplication at the join.

Join array
row.push(...)
row.join("")

Collect letters in an array, then print one string - easier to inspect each row while debugging.

Program 26 contrast
forward + wrap
BCDEA

Program 26 wraps cyclically - row 2 is BCDEA, not BABCD.

Context

When This Pattern Shows Up

Reach for mixed prefix/suffix loops when each row combines a descending run with an ascending tail on fixed-width lines.

  1. After Program 26

    Program 26 wraps cyclically - BCDEA. This pattern descends then ascends - BABCD.

  2. Opposite directions

    Practice descending and ascending ranges on the same row before tackling palindromes.

  3. Join-list clarity

    Building rows in a list mirrors real string assembly in larger programs.

  4. Gateway to Program 31

    Next pattern in the alphabet series builds on symmetric row ideas.

  5. Not a UI layout tool

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

Key benefit: one program that proves you can split a row into a descending prefix and ascending suffix - a pattern used in palindromes and symmetric string builders far beyond alphabet demos.

🔮 Live Preview

Choose a row count between 1 and 26 and draw the mixed alphabet pattern in the browser.

Try 5 (ABCDE through EDCBA) or 3 (ABC, BAB, CBA). Up to 26 rows use A–Z.

Live result
Press "Draw pattern".

Examples Gallery

Three complete JavaScript programs - fixed five rows with dual inner loops, prompt input, and an array-join variant for clarity. Click View Output to reveal sample console results, or Try it Yourself to run in the browser editor.

📚 Getting Started

Print five mixed rows with descending prefix and ascending suffix loops.

Example 1 — Fixed rows = 5

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

JavaScript
let rows = 5;
rows = Math.max(1, Math.min(rows, 26));

const base = "A".charCodeAt(0);
const top = base + rows - 1;

for (let r = 0; r < rows; r++) {  // 0..4
  const start = base + r;          // A, B, C, D, E
  const end = top - r;             // E, D, C, B, A
  let line = "";

  // Descending prefix: start..A
  for (let code = start; code >= base; code--) {
    line += String.fromCharCode(code);
  }

  // Ascending suffix: B..end (skip A)
  for (let code = base + 1; code <= end; code++) {
    line += String.fromCharCode(code);
  }

  console.log(line);
}
Try it Yourself

How It Works

The outer loop walks row index r from 0 to 4. For each row, start = base + r sets the prefix start and end = top - r shrinks the suffix bound. The first inner loop appends descending from start to A; the second appends ascending from B to end. When end is below B, the suffix loop is empty and the row is pure descending - that is how EDCBA appears.

📈 Practical Variant

Let the user choose the height at runtime.

Example 2 — User Input Version

Read rows and clamp to 1–26. Validate parseInt(prompt()) with Number.isFinite in real apps.

JavaScript
let rows = parseInt(prompt("Enter number of rows (1-26):"), 10);
if (!Number.isFinite(rows)) {
  console.log("Please enter a whole number.");
} else {
  rows = Math.max(1, Math.min(rows, 26));

  const base = "A".charCodeAt(0);
  const top = base + rows - 1;

  for (let r = 0; r < rows; r++) {
    const start = base + r;
    const end = top - r;
    let line = "";

    for (let code = start; code >= base; code--) {
      line += String.fromCharCode(code);
    }
    for (let code = base + 1; code <= end; code++) {
      line += String.fromCharCode(code);
    }

    console.log(line);
  }
}
Try it Yourself

How It Works

Same dual-loop core as Example 1; only the row count comes from prompt. Three rows use letters A–C with width 3 on every line - row 2 is BAC, not cyclic BCA.

⚡ Array Join Variant

Build each row in an array, then log with row.join("").

Example 3 — row.join("") Variant

Collect letters in an array for clearer row inspection - same logic, easier debugging.

JavaScript
let rows = 5;
rows = Math.max(1, Math.min(rows, 26));

const base = "A".charCodeAt(0);
const top = base + rows - 1;

for (let r = 0; r < rows; r++) {
  const start = base + r;
  const end = top - r;
  const row = [];

  for (let code = start; code >= base; code--) {
    row.push(String.fromCharCode(code));
  }
  for (let code = base + 1; code <= end; code++) {
    row.push(String.fromCharCode(code));
  }

  console.log(row.join(""));
}
Try it Yourself

How It Works

The start/end logic is identical; only formatting changes. row.join("") builds the full string once after both halves finish.

🧠 How the Algorithm Prints Rows

1

Set up bounds

Clamp rows, then set base = "A".charCodeAt(0) and top = base + rows - 1 for the alphabet window.

base / top
2

Outer loop (row index)

for (let r = 0; r < rows; r++) walks each row from 0 to rows - 1, computing start and end.

r = 0..n-1
3

Prefix + suffix loops

First inner loop appends start down to A; second appends B up to end with line += String.fromCharCode(...).

Two loops
4

New line

console.log(line) ends the row after both inner loops finish; the outer loop advances r to the next row.

Break
=

Pattern complete

Total characters: n × n = n²O(n²) time, O(1) extra memory (loop version).

🔎 Worked Walkthrough — rows = 5

Trace each outer-loop value of r and see how the prefix and suffix combine into each printed row.

rstartendPrefixSuffixFull row
0'A''E'ABCDEABCDE
1'B''D'BABCDBABCD
2'C''C'CBABCCBABC
3'D''B'DCBABDCBAB
4'E''A'EDCBA(empty)EDCBA

Total character prints: 5 × 5 = 25 = for n = 5 rows.

Use Cases

Where this tiny pattern (and its prefix/suffix split) shows up beyond the homework prompt.

1. Contrast with Program 26

Program 26 wraps cyclically - BCDEA. This descends then ascends - BABCD.

Example: side-by-side ABCDE/BCDEA vs ABCDE/BABCD.

2. Opposite range practice

Reinforce descending for (code = start; code >= base; code--) and ascending for (code = base + 1; code <= end; code++) on the same row.

Example: trace prefix and suffix for row 2 (r=1) on paper before coding.

3. Palindrome prep

Descend then ascend on one line mirrors half-palindrome construction.

Example: row 3 prefix CBA + suffix BC forms CBABC - almost symmetric.

4. Number mixed rows

Swap letters for digits 1..n with the same prefix + suffix logic.

Example: rows=3 gives 123, 212, 321.

5. Complexity intuition

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

Example: 5 rows → 25 characters printed.

6. Interview warm-up

Classic nested-loop question that tests prefix/suffix bounds and the skip-A rule.

Example: explain why row 5 is EDCBA without running code.

Pro Tip: say “descend from start to A, ascend from B to end” before coding - that story prevents duplicating A or skipping the descending loop.

Advantages

Why this pattern earns a spot after the rotation pattern from Program 26.

  1. 1. Teaches Opposite Directions

    Two inner loops run descending then ascending on the same row - a core loop skill.

  2. 2. Fixed-Width Rows

    Every line has the same length - prefix and suffix always sum to rows.

  3. 3. Two Implementations

    Direct print version for learning; array-join version for clearer debugging.

  4. 4. O(1) Extra Memory

    Streaming output needs no storage beyond loop counters (join variant uses O(n) per row).

Pro Tip: when end is below B, the suffix loop is empty and the row is pure descending - that is how EDCBA appears on the last line.

Usage Tips

Small habits that keep mixed alphabet pattern code clean.

  1. 1. Name start and end

    Use start = base + r and end = top - r - keep r and code for loop variables.

  2. 2. Wrap parseInt(prompt(), 10) in Number.isFinite

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

  3. 3. Clamp rows early

    rows = Math.max(1, Math.min(rows, 26)) keeps demos inside A–Z.

  4. 4. Suffix starts at B

    for (let code = base + 1; code <= end; code++) - never start the suffix at A or you duplicate the join letter.

  5. 5. Dry-Run rows = 3

    Trace ABC, BAC, CBA on paper before coding larger demos.

Pro Tip: if rows look like Program 26 (BCDEA, CDEBA), you likely used forward + wrap instead of descend + ascend.

Common Pitfalls

Mistakes that commonly break mixed alphabet patterns.

  1. 1. Duplicating A in the middle

    Starting the suffix at A gives BAA, CABA - double A at the join.

    → Suffix must start at B: for (let code = base + 1; code <= end; code++).

  2. 2. Wrong end bound

    Using end = top or end = top + r keeps the suffix too long - rows exceed width rows.

    → Use end = top - r so prefix and suffix lengths always sum to rows.

  3. 3. Skipping the descending loop

    Only the ascending suffix prints BCD, CD, D - rows are too short and miss the descending prefix.

    → Always run the prefix loop first: for (let code = start; code >= base; code--).

  4. 4. Blind parseInt(prompt())

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

    → Validate parseInt(prompt()) with Number.isFinite and validate range.

  5. 5. Confusing with Program 26

    Program 26 wraps cyclically - row 2 is BCDEA, not BABCD.

    → Here prefix descends and suffix ascends - no cyclic wrap between the two parts.

Edge Cases

Check these inputs before calling the solution done.

rows = 1

Single letter

Output is just A on one line - prefix is A, suffix loop empty because end is below B.

rows = 0

Empty pattern

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

rows = 26

Full alphabet

26 rows of width 26 - last row is pure descending from Z down to A.

rows > 26

Past Z

Clamp to 26 or define a wrap/error policy before printing.

Bad input

Non-numeric input

Use Number.isFinite before clamping rows.

Case

Lowercase variant

Same loops work with base = "a".charCodeAt(0) and lowercase output.

🎯 Practice Problems

Try these variations to lock in the pattern.

1. Compare with Program 26

  • Program 26: ABCDE, BCDEA, CDEBA (cyclic wrap)
  • This pattern: ABCDE, BABCD, CBABC (descend + ascend)
  • See Program 26

2. Implement join-list form

  • Rewrite Example 1 using row.append and row.join("")
  • Verify identical output for rows=5

3. Number mixed rows

  • Print 123, 212, 321 for rows=3
  • Same prefix + suffix logic with ints

4. Continue to Program 31

  • Next pattern in the series - Alphabet X
  • Builds on symmetric row ideas
  • See Program 31

Notes

  • Square count. Total characters for n rows is - each row prints n letters.
  • Prefix loop: for (code = start; code >= base; code--). Suffix loop: for (code = base + 1; code <= end; code++).
  • row.join("") after building in a list is equivalent to the direct-print version - use whichever fits your lesson.
  • Clamp to 26 rows for A–Z demos; row 26 prefix starts at Z and suffix is empty - pure descending line.

Quick Takeaway: outer loop sets r, compute start and end, print descending prefix, ascending suffix from B, then break the line - that is the whole mixed alphabet pattern.

⏱️ Time and Space Complexity

ProgramTimeExtra space
Two inner loops (Examples 1–2)O(rows²)O(1)
Join variant (Example 3)O(rows²)O(rows) for the row list per line
Wrap Up

🎉 Conclusion

The mixed alphabet pattern teaches opposite loop directions on one row - descending prefix from the start letter to A, then ascending suffix from B to end. Master the line-building version, then try the array-join variant for clearer debugging.

Practice the three examples above, then continue to Program 31 in the alphabet pattern series.

Set start and end each row, run prefix then suffix loops, clamp rows to 26, and compare with Program 26 to see the difference from cyclic rotation.

💡 Best Practices

✅ Do

  • Set base = "A".charCodeAt(0), top = base + rows - 1
  • Compute start = base + r and end = top - r each row
  • Run prefix loop then suffix loop on every row
  • Start suffix at B (base + 1) - never duplicate A
  • Use line += String.fromCharCode(...) in loops; console.log(line) after both
  • Clamp rows to 1–26 for A–Z demos

❌ Don’t

  • Start the suffix at A - duplicates the join letter
  • Use wrong end bound - rows will be too long or too short
  • Skip the descending prefix loop
  • Confuse this with Program 26’s cyclic BCDEA rows
  • Call console.log(line) inside the letter loops
  • Let rows exceed 26 without a defined policy

Key Takeaways

Knowledge Unlocked

Five things to remember about this mixed alphabet pattern

Print the mixed rows the beginner-friendly way.

5
Core concepts
↓A 02

Prefix loop

start down to A

Code
B→ 03

Suffix loop

B up to end

Code
[] 04

Join array

row.join("")

Alt
O 05

Complexity

O(n²) time

Analysis

❓ Frequently Asked Questions

Each row combines a descending prefix from the row start letter down to A with an ascending suffix from B up to a shrinking end letter. Row 1 is ABCDE; row 2 is BABCD; row 5 is EDCBA.
Program 26 rotates fixed-width rows with wrap-around (ABCDE, BCDEA, CDEBA). Here the prefix descends and the suffix ascends without cyclic wrap - BABCD not BCDEA.
The first loop appends the descending prefix from start down to A. The second appends the ascending suffix from B to end - skipping A avoids duplicating the letter at the join point.
A is already appended as the last character of the descending prefix (except row 1 where start is A). Starting the suffix at B prevents AA, BA becoming BAA, etc.
Each row uses letters A through the (rows)th letter. With rows > 26 you would need characters beyond Z unless you define a wrap policy.
line += String.fromCharCode(code) stays on the same row with no newline between letters. console.log(line) ends the row after both inner loops finish.
O(n^2) where n is rows. There are n rows and each row prints n characters.
Use parseInt(prompt(), 10) and check Number.isFinite, then clamp rows between 1 and 26.

Did you Know? 🔊

Each row uses two passes: a descending prefix from the row start letter down to A, then an ascending suffix from B up to end = top - r. Row 1 is pure ascending ABCDE; the last row is pure descending EDCBA.

Continue to Program 31

Next up: the Alphabet X pattern - build on symmetric row ideas from this tutorial.

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