A shifting-start alphabet pattern keeps a fixed end letter while each new row drops the leading letter — so rows shrink from ABCDE to E.
Remember
Rule: end fixed; start = A+i; print start..end
ABCDE
BCDE
CDE
DE
E ← 5 rows, every row ends at E
Compare Program 5 (fixed start A, shrinking end: ABCDE…A) and Program 3 (start moves back, end fixed, rows grow). Program 7 counts down instead (EDCBA to A).
Approach
How to Solve It
Fix end from the row count. For each row, move start forward and print start..end.
Method
Idea
Best for
Nested ord/chr
start = base + i, range(start, end + 1)
Learning, interviews, exams
String slice
print(letters[i:rows])
Compact shortcut once the idea clicks
Pseudocode
Pseudocode
base = 'A'
end = base + rows - 1
for i from 0 to rows - 1:
start = base + i
for code from start to end: // inclusive
print code
print newline
Cheat sheet
Goal
Pattern
Fixed end
end = ord("A") + rows - 1
Walk rows
for i in range(rows):
Row start
start = ord("A") + i
Print start..end
for code in range(start, end + 1):
Include end
Use end + 1 as exclusive stop
End the row
print()
Slice shortcut
print(letters[i:rows])
vs Program 5
Here end is fixed; Program 5 shrinks the end
Printing Letters vs Starting a New Line
API
Effect
Use for
print(chr(code), end="")
Stays on the same row
Each letter from start to end
print()
Ends the current row
After the inner loop
Print letters without a newline, then end the row once.
Try it
Live Preview
Change the row count and the shifting-start pattern updates instantly — every row still ends at the same letter.
Whole numbers from 1 to 10. Size 5 means end letter E. Tap a chip or type a value — the preview redraws as you go.
Live result5 rows · end E
ABCDE
BCDE
CDE
DE
E
Trace
Worked Walkthrough — rows = 3
end = C. Start moves A → B → C while the right edge stays fixed.
i
Start..end
Printed row
0
A..C
ABC
1
B..C
BC
2
C..C
C
Total letters are n+(n-1)+…+1 = n(n+1)/2 → O(n²).
Code
Python Programs
Three complete programs: fixed height, row-count input(), and a slice shortcut. Use View Output for sample results.
Example 1 — Fixed rows = 5
Fix the end letter; move the start forward each row.
Python
rows = 5
base = ord("A")
end = base + rows - 1 # E when rows = 5
for i in range(rows):
start = base + i
for code in range(start, end + 1):
print(chr(code), end="")
print()
Output
ABCDE
BCDE
CDE
DE
E
How It Works
1. Fix the right edge.end is E for 5 rows — every row finishes there.
2. Move the start. When i = 2, start is C and the row is CDE.
3. Include the end.range(start, end + 1) prints through E; without +1 the last letter is dropped.
Example 2 — Row Count Input
Read how many rows to print. Cap at 26 so letters stay in A–Z.
Python
raw = input("Enter the number of rows (max 26): ").strip()
try:
rows = int(raw)
except ValueError:
print("Please enter a whole number.")
raise SystemExit(1)
rows = max(1, min(rows, 26))
base = ord("A")
end = base + rows - 1
for i in range(rows):
start = base + i
for code in range(start, end + 1):
print(chr(code), end="")
print()
Output (when user enters 4)
ABCD
BCD
CD
D
How It Works
1. Validate rows. Parse an integer, then clamp to 1..26.
2. Same fixed end. Four rows end at D; the last row is a single D.
Example 3 — letters[i:rows]
Slice from index i through rows — no inner letter loop.
Python
rows = 5
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for i in range(rows):
print(letters[i:rows])
Output
ABCDE
BCDE
CDE
DE
E
How It Works
1. One slice.letters[i:rows] is start..end (BCDE when i = 1 and rows = 5).
2. Same shape. Identical output to Example 1 — keep the nested-loop version for exams that ask for ord/chr bounds.
Edge Cases & Pitfalls
Check these before calling the solution done.
drop end
range(start, end)
range stops before the end value, so you lose the last letter. Use end + 1.
wrong shrink
Shrinking the end instead
That is Program 5 (ABCDE, ABCD, …). Here the start moves; the end stays fixed.
newline early
Bare print() inside the inner loop
Use end="" for letters; call bare print() only after the run finishes.
rows > 26
End past Z
Cap rows at 26 so ord("A") + rows - 1 stays in A–Z.
rows = 1
Single A
Start and end are both A — a good sanity check.
Bad input
Non-integer rows
Catch ValueError from int(...) before computing end.
Analysis
Time and Space Complexity
Program
Time
Extra space
Nested loops (Examples 1–2)
O(n²)
O(1)
Slice shortcut (Example 3)
O(n²)
O(n) per row for the slice string
There are n rows printing n+(n-1)+…+1 letters, so total work is n(n+1)/2.
Remember
Key Takeaways
Rule: fixed end; row i prints (A+i)..end.
Inclusive end: use range(start, end + 1).
Contrast: Program 5 shrinks the end; this pattern shifts the start.
Next step: Program 7 prints decreasing reverse rows (EDCBA to A).
One line: for each i, print letters from A+i through a fixed end letter.
Frequently Asked Questions
The outer loop walks i from 0 to rows-1. Each row sets start = ord('A') + i and end = ord('A') + rows - 1. The inner loop prints from start through end, so row 0 is ABCDE, row 1 is BCDE, and the last row is a single E.
For rows = 5, end is the code for E — the last letter on every row. The first row spans A through E; each next row drops the leading letter but keeps the same end letter.
range stops before its end value. range(start, end + 1) includes the final letter on each row. Forgetting +1 drops the last character (e.g. E on the last row).
Program 5 keeps start at A and shrinks the end each row (ABCDE, ABCD, ...). This pattern keeps a fixed end and shifts the start right each row (ABCDE, BCDE, ...).
O(n²) where n is the number of rows. Total printed characters equal n+(n-1)+...+1 = n(n+1)/2 — same triangular count as Programs 1 and 5.
Yes. Keep letters = "ABCDEFG..." and print(letters[i:rows]) for each row index i. Nested ord/chr loops teach the bounds; slicing is a compact shortcut.
Use try/except ValueError around int(input()), 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?
Each row prints from a row-specific start letter through a fixed end: end = ord('A') + rows - 1. Row i uses start = ord('A') + i, so rows shrink from ABCDE to E. Compare Program 5 (fixed start A, shrinking end) and Program 3 (fixed top letter rows).