Python Number Triangle Pattern (Reverse Descending)
Beginner
5 min read
Updated: Sep 2026
3 programs
Live preview
Definition
What Is This Pattern?
A reverse descending triangle shortens each row from the top — 54321, 4321, 321, 21, 1 — with digits counting down on every line.
Remember
Rule: for i = rows down to 1
print digits i..1
54321
4321
321
21
1 ← rows = 5
After Program 2’s left-shifted i..n rows, this one flips both loops downward so each row reads in reverse.
Approach
How to Solve It
Count i down from rows; on each row, print digits from i down to 1.
Method
Idea
Best for
Nested loops
Outer i = rows..1; inner j = i..1
Learning, interviews
input() rows
Same loops; read rows at runtime
Interactive practice
Spaced digits
print(j, end=" ")
Readable output
Pseudocode
Pseudocode
for i from rows down to 1:
for j from i down to 1:
print j (same line)
print newline
Cheat sheet
Goal
Pattern
Set size
rows = 5
Outer loop
for i in range(rows, 0, -1):
Inner loop
for j in range(i, 0, -1): print(j, end="")
End row
print()
Digits printed
i..1 (length i)
Spaced
print(j, end=" ")
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
Glue digits with end="", then break once with print(). Putting print() inside the inner loop prints one digit per line.
Try it
Live Preview
Change the row count and the reverse descending triangle updates instantly.
Whole numbers from 1 to 9. Tap a chip or type a value — the preview redraws as you go.
Live resultrows = 5 · digits = 15
54321
4321
321
21
1
Trace
Worked Walkthrough — rows = 3
Trace each outer value of i and the digits printed from i down to 1.
i
Digits i..1
Printed row
3
3 2 1
321
2
2 1
21
1
1
1
As i falls, the inner loop starts lower — one fewer digit each row.
Code
Python Programs
Three complete programs: fixed rows = 5, input() rows, and spaced digits. Use View Output for sample results.
Example 1 — Fixed rows = 5
Hard-coded height — outer shrinks the row; inner prints digits in reverse.
Python
rows = 5
for i in range(rows, 0, -1):
for j in range(i, 0, -1):
print(j, end="")
print()
Output
54321
4321
321
21
1
How It Works
1. Outer loop.i runs from 5 down to 1 — the starting digit and row length.
2. Inner loop.j runs from i down to 1, so print(j, end="") builds i..1.
3. Newline.print() after the inner loop ends the row and starts the next one.
Example 2 — input() Rows
Read rows at runtime with input() and int().
Python
rows = int(input("Enter the number of rows: "))
if rows < 1:
print("Please enter a positive integer.")
else:
for i in range(rows, 0, -1):
for j in range(i, 0, -1):
print(j, end="")
print()
Output (when user enters 4)
Enter the number of rows: 4
4321
321
21
1
How It Works
1. Read and validate. Parse the answer; reject non-positive values before looping.
2. Same loops. Only the source of rows changes — still print i..1 on each row.
3. Safer input tip. Bare int(input()) raises ValueError on letters. Prefer:
Safer input
raw = input("Enter the number of rows: ").strip()
try:
rows = int(raw)
except ValueError:
print("Please enter a positive integer.")
raise SystemExit(1)
if rows < 1:
print("Please enter a positive integer.")
raise SystemExit(1)
Example 3 — Spaced Digits
Keep rows = 5 but print a space after each digit.
Python
rows = 5
for i in range(rows, 0, -1):
for j in range(i, 0, -1):
print(j, end=" ")
print()
Output
5 4 3 2 1
4 3 2 1
3 2 1
2 1
1
How It Works
1. Same structure. Outer and inner bounds match Example 1.
2. Only end= changes. Use print(j, end=" ") instead of print(j, end="").
3. Same shape. Values and row count stay the same — only spacing differs.
Edge Cases & Pitfalls
Check these before calling the solution done.
print() inside
Vertical digits
If print() is inside the inner loop, each digit lands on its own line. Use end=""; call bare print() only after the inner loop.
j++
Ascending by mistake
Using for j in range(1, i + 1) with a descending outer loop yields 12345, 1234, … — not this pattern.
print(i)
Repeated digit
Printing i instead of j repeats the row digit, not a countdown.
rows = 1
Single digit
Output is just 1 on one line.
rows ≤ 0
Empty output
The outer loop never runs. Guard input() with rows >= 1.
input()
Catch ValueError
Letters crash bare int(input()) — wrap in try/except and require rows >= 1.
Analysis
Time and Space Complexity
Program
Time
Extra space
Examples 1–3
O(n²)
O(1)
Total digits = n + (n−1) + … + 1 = n(n+1)/2 → O(n²).
Remember
Key Takeaways
Rule: outer i = rows..1; inner prints i..1.
Both count down: outer shrinks the row; inner reverses the digits.
end= vs print(): digits stay on the line; print() advances after each row.
Complexity:O(n²) for n rows.
One line: shrink the outer count while the inner loop prints each row backwards from i to 1.
Frequently Asked Questions
The inner loop runs for j in range(i, 0, -1), so each row prints i, i-1, ..., 1.
Because rows = 5 and the outer loop starts with i = rows via range(rows, 0, -1). The first row prints from 5 down to 1.
Program 2 prints i..rows (left-shifted ascending). Program 3 prints i..1 (reverse descending) with a shrinking outer loop.
Keep the descending outer loop but change the inner loop to for j in range(1, i + 1) (ascending).
Replace 5 with rows in the outer bound — see Example 2.
Use print(j, end=" ") instead of print(j, end="") — see Example 3.
O(n²) for n rows. Total prints are n + (n-1) + ... + 1 = n(n+1)/2.
Use try/except ValueError around int(input()) or check the raw string with .isdigit() before converting so bad input does not crash the script.
Only one row prints — a single 1.
🤔
Did you know?
This pattern prints each row in descending order from i down to 1. The outer loop shrinks the row length while the inner loop counts downward — producing 54321, 4321, 321, and so on.