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

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 Python 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 code in range(start, base - 1, -1): prints the descending part.

Suffix Loop

B → end

for code in range(base + 1, end + 1): fills the ascending tail — skips A.

ord() / chr()

Letter codes

base = ord('A'), 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 Python you solve it with an outer loop over row index r, two inner loops (descending prefix then ascending suffix), and ord()/chr() — or build each row in a list and print(''.join(row)) 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 = ord('A') and top = base + rows - 1, loop r from 0 to rows - 1, compute start = base + r and end = top - r, print descending prefix, ascending suffix from B, then print() 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.

Python
# 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 = ord('A')
top = base + rows - 1
for r from 0 to rows-1:
    start = base + r
    end = top - r
    print letters start..A (descending)
    print letters B..end (ascending)
    print newline

Approach comparison

ApproachIdeaBest for
Two inner loopsDescend range(start, base-1, -1) + ascend range(base+1, end+1)Learning ord/chr and opposite loop directions
Join listBuild row in a list, print(''.join(row))Clearer debugging and row inspection
Program 26 contrastSee Program 26 (ABCDE, BCDEA, …)Cyclic rotation with wrap-around

⚡ Quick Reference

GoalPattern
Bound the alphabetbase = ord('A'); top = base + rows - 1
Outer loop (row index)for r in range(rows):
Row boundsstart = base + r; end = top - r
Prefix (descending)for code in range(start, base - 1, -1): print(chr(code), end="")
Suffix (ascending)for code in range(base + 1, end + 1): print(chr(code), end="")
End the rowprint()
List join variantrow.append(chr(code)); print(''.join(row))

📋 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
range(start, base-1, -1)
start..A

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

Suffix loop
range(base+1, end+1)
B..end

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

Join list
row.append(...)
''.join(row)

Collect letters in a list, 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 Python programs — fixed five rows with dual inner loops, console input, and a list-join variant for clarity. Click View Output to reveal sample console results.

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

Python
rows = 5
rows = max(1, min(rows, 26))

base = ord('A')
top = base + rows - 1

for r in range(rows):  # 0..4
    start = base + r          # A, B, C, D, E
    end = top - r             # E, D, C, B, A

    # Descending prefix: start..A
    for code in range(start, base - 1, -1):
        print(chr(code), end="")

    # Ascending suffix: B..end (skip A)
    for code in range(base + 1, end + 1):
        print(chr(code), end="")

    print()

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 prints descending from start to A; the second prints 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. Wrap int(input()) in try/except ValueError in real apps.

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

base = ord('A')
top = base + rows - 1

for r in range(rows):
    start = base + r
    end = top - r

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

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

    print()

How It Works

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

⚡ List Join Variant

Build each row in a list, then print with ''.join(row).

Example 3 — ''.join(row) Variant

Collect letters in a list for clearer row inspection — same logic, easier debugging.

Python
rows = 5
rows = max(1, min(rows, 26))

base = ord('A')
top = base + rows - 1

for r in range(rows):
    start = base + r
    end = top - r
    row = []

    for code in range(start, base - 1, -1):
        row.append(chr(code))

    for code in range(base + 1, end + 1):
        row.append(chr(code))

    print(''.join(row))

How It Works

Each loop appends characters to row instead of printing immediately. ''.join(row) concatenates without spaces — identical output to Examples 1 and 2, but you can inspect row before printing during debugging.

🧠 How the Algorithm Prints Rows

1

Set up bounds

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

base / top
2

Outer loop (row index)

for r in range(rows): walks each row from 0 to rows - 1, computing start and end.

r = 0..n-1
3

Prefix + suffix loops

First inner loop prints start down to A; second prints B up to end with print(chr(...), end="").

Two loops
4

New line

print() 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 range(start, base-1, -1) and ascending range(base+1, end+1) 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; list-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 int(input()) in try/except

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

  3. 3. Clamp rows early

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

  4. 4. Suffix starts at B

    range(base + 1, end + 1) — 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 code in range(base + 1, end + 1):.

  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 code in range(start, base - 1, -1):.

  4. 4. Blind int(input())

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

    → Wrap int(input()) in try/except ValueError 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 try/except ValueError before clamping rows.

Case

Lowercase variant

Same loops work with base = ord('a') 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 ''.join(row)
  • 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: range(start, base - 1, -1). Suffix loop: range(base + 1, end + 1).
  • ''.join(row) 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 direct-print version, then try the list-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 = ord('A'), 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 print(chr(...), end="") in loops; print() 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 print() 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 list

''.join(row)

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 prints the descending prefix from start down to A. The second prints the ascending suffix from B to end — skipping A avoids duplicating the letter at the join point.
A is already printed 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.
print(chr(code), end="") keeps letters on the same row with no space between them. print() ends the row after both inner loops finish.
O(n²) where n is rows. There are n rows and each row prints n characters.
Use a try/except ValueError around int(input()), or check raw.isdigit() before converting, 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