Python Descending Number Triangle Pattern (Left-Aligned)
Beginner
5 min read
Updated: Sep 2026
3 programs
Live preview
Definition
What Is This Pattern?
A left-aligned descending number triangle starts every row at rows and counts down to the current i, so each line gets shorter from the right.
Remember
Rule: print rows..i (no leading spaces)
54321
5432
543
54
5 ← 5 rows
Follows the reverse descending triangle in Program 3; next is the ascending number triangle in Program 5.
Approach
How to Solve It
One nested-loop idea: ascending outer bound, descending inner digits — tight digits with end="", then bare print().
Method
Idea
Best for
rows..i loops
Start each row at rows; stop at i
Learning, interviews, exams
User-input rows
Same logic with a variable height
Practice / demos
Pseudocode
Pseudocode
for i from 1 to rows:
for j from rows down to i:
print j
print newline
Cheat sheet
Goal
Pattern
Raise the stop value
for i in range(1, rows + 1):
Print rows..i
for j in range(rows, i - 1, -1): print(j, end="")
Spaced digits
print(j, end=" ")
End the row
print()
Printing Numbers vs Starting a New Line
API
Effect
Use for
print(j, end="")
Stays on the same line
Each digit
print()
Ends the current line
After the inner loop
Print digits without a newline, then end the row once.
Try it
Live Preview
Change the row count and the shrinking descending triangle updates instantly.
Whole numbers from 1 to 9 (keeps digits single-width). Tap a chip or type a value — the preview redraws as you go.
Live result5 rows · 15 digits
54321
5432
543
54
5
Trace
Worked Walkthrough — rows = 4
Trace how the stop value i shortens each row while every line still starts at 4.
i
Digits j
Printed row
1
4 3 2 1
4321
2
4 3 2
432
3
4 3
43
4
4
4
Row length is rows - i + 1. The first digit is always rows.
Code
Python Programs
Three complete programs: fixed rows = 5, input() variant, and a compact rows = 3 demo. Use View Output to reveal sample results.
Example 1 — Fixed rows = 5
Ascending outer loop; each row prints from 5 down to the current i.
Python
rows = 5
for i in range(1, rows + 1):
for j in range(rows, i - 1, -1):
print(j, end="")
print()
Output
54321
5432
543
54
5
How It Works
1. Outer loop.i grows from 1 to 5 — the inner stop value rises, so rows get shorter.
2. Inner loop.j always starts at 5 and counts down to i — every row begins with 5.
3. Newline. Bare print() after the digits starts the next shorter row.
Example 2 — User Input Rows
Read rows with input(), validate, then use the same rows..i logic.
Python
try:
rows = int(input("Enter rows: "))
except ValueError:
print("Please enter a positive whole number.")
raise SystemExit(1)
if rows < 1:
print("Please enter a positive whole number.")
raise SystemExit(1)
for i in range(1, rows + 1):
for j in range(rows, i - 1, -1):
print(j, end="")
print()
Output (when user enters 4)
Enter rows: 4
4321
432
43
4
How It Works
1. Prompt and validate. Catch ValueError; require rows >= 1 before printing.
2. Same core.rows..i matches Example 1 — only rows comes from the user.
3. Safer input tip. Cap demos for readable single-digit output:
Safer input tip
if rows < 1 or rows > 9:
print("Enter a whole number from 1 to 9.")
raise SystemExit(1)
Example 3 — Compact rows = 3
Same structure with only three rows — easy to confirm every line still starts at rows.
Python
rows = 3
for i in range(1, rows + 1):
for j in range(rows, i - 1, -1):
print(j, end="")
print()
Output
321
32
3
How It Works
1. Same rules. Outer raises i; inner prints from 3 down to i.
2. Quick check. The last row is a single 3.
3. Scale up next. Once the small demo is clear, use Examples 1–2 for five rows or user input.
Edge Cases & Pitfalls
Check these before calling the solution done.
wrong twin
Use Program 3’s outer loop
for i in range(rows, 0, -1) with j = i..1 prints 4321, 321… Keep ascending i and inner rows..i.
full line
Loop j down to 1 every row
That reprints 54321 five times. Stop at range(rows, i - 1, -1).
print() inside
Broken rows
If bare print() sits inside the inner loop, you get one digit per line. Call it only after the loop.
extra spaces
Accidental spacing
Default print(j) adds a newline. Use end="" for tight digits (or end=" " only if you want spaces).
rows = 1
Single digit
Output is just 1. A good sanity check for input validation.
input()
Catch ValueError
Bare int(input()) crashes on non-numeric text — wrap it in try/except ValueError.
Analysis
Time and Space Complexity
Program
Time
Extra space
Fixed / input (Examples 1–2)
O(n²)
O(1)
Compact rows = 3 (Example 3)
O(n²)
O(1)
Row lengths are n + (n−1) + … + 1 = n(n+1)/2 → O(n²) time. Only a few loop variables are needed.
Remember
Key Takeaways
Rule: every row prints rows..i — always starts at rows.
Shrink: raise i each row so the stop value climbs and the line shortens.
end="" vs print(): digits stay on the line; bare print() advances after each row.
Complexity:O(n²) time; O(1) extra space.
One line: for each i from 1 to rows, print rows..i with no leading spaces.
Frequently Asked Questions
A left-aligned descending triangle: for rows=5 you get 54321 / 5432 / 543 / 54 / 5 — every row starts at rows and stops at i.
Because the inner loop always begins at rows (the maximum digit) and counts down. Only the stopping point i changes per row.
Row i prints rows - i + 1 digits — the inner loop runs from j = rows down to i.
Program 3 prints i..1 with a descending outer loop (4321, 321, …). Program 4 prints rows..i with an ascending outer loop — every row starts at rows.
No — digits are left-aligned with no leading spaces. Each row begins flush left at the maximum digit.
Use print(j, end=" ") instead of print(j, end="").
Use try/except ValueError around int(input()) and require rows >= 1 — see Example 2.
O(n²) for n rows because total prints are 1 + 2 + … + n = n(n+1)/2.
🤔
Did you know?
Each row starts at rows and counts down to i. Row i prints rows - i + 1 digits — total prints = n(n+1)/2; output is left-aligned with no leading spaces.