Shape Rule
Fixed start, shrinking stop
Row 1 prints 54321, row 2 prints 5432, shrinking until a single 5 — every row starts at rows.

The left-aligned descending number triangle prints 54321, 5432, 543, 54, 5 — a natural step after the reverse descending triangle in Program 3. This tutorial covers a fixed inner start with shrinking stop, nested loops, a live preview, algorithm steps, worked Python examples, edge cases, and complexity.
Fixed start, shrinking stop
Row 1 prints 54321, row 2 prints 5432, shrinking until a single 5 — every row starts at rows.
0..rows-1
for i in range(0, rows): changes the inner loop’s stop point each row.
rows..i descending
for j in range(rows, i, -1): always starts at rows and counts down.
Same line / next line
Digits use print(j, end=""); end each row with print().
3–9 rows
Pick a row count and draw the left-aligned descending triangle in the browser.
Complexity
Total digit prints = n(n+1)/2; extra memory stays O(1).
A left-aligned descending number triangle prints every row starting from rows and counting down, but each next row stops earlier. With rows = 5, the output is 54321, 5432, 543, 54, 5.
In Python the outer loop runs i = 0..rows-1, the inner loop prints j from rows down to i+1 via range(rows, i, -1), then print() moves to the next line.
It teaches fixed-start inner loops with a changing stop — a key step after Program 3’s reverse descending rows.
Inner loop always begins at rows.
Outer loop changes where the inner loop stops.
Program 3 shifts the start each row; Program 4 keeps the same first digit.
Follow Program 3; continue to Program 5 (ascending triangle) next.
In short: for each i from 0 to rows-1, print j from rows down to i+1, then print().
Given a positive integer rows (e.g. 5), print a left-aligned descending triangle: each row starts at rows and counts down, with the outer loop shortening the stop point each line.
# rows = 5 (conceptual shape)
# 54321
# 5432
# 543
# 54
# 5 | Item | Type | Description |
|---|---|---|
rows | int | Maximum digit and number of triangle lines. |
i | int | Outer loop — row index from 0 to rows-1; controls inner stop. |
j | int | Inner loop — descending from rows down to i+1. |
for i from 0 to rows-1:
for j from rows down to i+1:
print j
print newline | Approach | Idea | Best for |
|---|---|---|
| Nested loops | 54321, 5432, … | Learning and interviews |
| User-input rows | int(input(...)) | Flexible console programs |
| Spaced output | print(j, end=" ") | Easier reading per row |
| Goal | Pattern |
|---|---|
| Walk rows | for i in range(0, rows): |
| Print digits rows..i+1 | for j in range(rows, i, -1): print(j, end="") |
| End the row | print() |
| Spaced digits | print(j, end=" ") |
| User input | int(input(...)) |
| Program 3 contrast | for i in range(rows, 0, -1): with j = i..1 |
Same left-aligned descending triangle — different ways to control rows and formatting.
i = 0..rows-1Changes inner stop each line
j = rows..i+1Fixed start, descending digits
i = 0Longest row on top
range stopRemember range stop is exclusive
Reach for this pattern when teaching fixed-start inner loops and shrinking row lengths.
Natural follow-up — every row keeps the same starting digit while the stop point shrinks.
Outer/inner bound practice with an immediate visual check.
Combine loops with input() for a flexible row count.
Compare Program 3 (reverse descending) and Program 5 (ascending triangle) next.
This is a console teaching pattern — not how you build modern app screens.
Key benefit: one small program that locks in nested loops, output sequencing, and O(n²) thinking.
Choose a row count between 3 and 9 and draw the left-aligned descending triangle in the browser.
Three complete Python programs — fixed rows, user input, and spaced output variant. Click View Output to reveal sample console results.
Print five rows of the left-aligned descending triangle with nested loops.
rows = 5Hard-coded row count — ideal for first demos and screenshots.
rows = 5
for i in range(0, rows):
for j in range(rows, i, -1):
print(j, end="")
print() When i = 0, the inner loop prints 5, 4, 3, 2, 1 — output 54321. When i = 4, only one digit prints — output 5. The outer loop increases i each row, shortening the inner loop.
Read the row count with input() instead of hard-coding 5.
Read rows with input() and int() (wrap in try/except ValueError in real apps).
rows = int(input("Enter the number of rows: "))
for i in range(0, rows):
for j in range(rows, i, -1):
print(j, end="")
print() Same fixed-start inner-loop core as Example 1; only the source of rows changes from a literal to user input. Non-numeric input raises ValueError with bare int(input()) — use try/except for safer labs.
Add a space between digits for easier reading on each row.
Keep rows = 5 but print each digit followed by a space.
rows = 5
for i in range(0, rows):
for j in range(rows, i, -1):
print(j, end=" ")
print() Only the print statement changes — print(j, end=" ") instead of print(j, end=""). Loop bounds stay the same as Example 1.
No imports needed for fixed rows; use input() when reading. Set rows = 5 and loop variables i, j.
for i in range(0, rows): — ascending outer loop changes the inner stop each row.
for j in range(rows, i, -1): — always starts at rows and counts down.
print() ends the row after the inner loop finishes.
Each row starts at rows — O(n²) time, O(1) extra memory.
rows = 5Trace each outer-loop value of i, the inner-loop range, digit count, and full row output.
i | Inner loop (j) | Prints | Row output |
|---|---|---|---|
0 | 5, 4, 3, 2, 1 | 5 | 54321 |
1 | 5, 4, 3, 2 | 4 | 5432 |
2 | 5, 4, 3 | 3 | 543 |
3 | 5, 4 | 2 | 54 |
4 | 5 | 1 | 5 |
Prints per row = rows - i — total prints = n(n+1)/2 for n rows.
Where this tiny pattern (and its loop structure) shows up beyond the homework prompt.
Clearest visual proof that outer and inner bounds interact.
Example: flip j-- to j++ and watch digit order change.
Foundation for inverted, pyramid, diamond, and hollow variants.
Example: continue to Program 5 for an ascending number triangle.
Practice print vs row newline without complex math.
Example: put print() inside the inner loop by mistake.
Add spaces between digits once the two-loop structure works.
Example: use print(j, end=" ") between digits on each row.
Triangular totals make O(n²) concrete for beginners.
Example: count printed digits for rows = 5 — total is 15 (5+4+3+2+1).
Pair the pattern with input() return checks and positive-row checks.
Example: reject rows <= 0 and re-prompt.
Pro Tip: when an interviewer asks for patterns, explain the outer/inner roles first — then write the loops. The story matters as much as the code.
Why this pattern earns a permanent spot in beginner Python courses.
Wrong bounds show up immediately as a broken staircase.
Only loops and console output — no arrays or math libraries.
Invert, center, hollow, or change the fill character with small edits.
Streaming output needs no storage beyond loop counters.
Pro Tip: trace i and j on paper for rows = 3 before coding — watch how each row shortens by one digit.
Small habits that keep number-pattern code clean.
Outer loop uses range(0, rows); inner loop uses range(rows, i, -1) — the stop value is not included.
try/except ValueErrorUse try/except ValueError so bad input does not crash when converting rows.
Only call print() after the inner loop finishes the row.
for j in range(rows, i, -1): always begins at rows — only the stop changes.
Trace i = 0, 1, 2 on paper before coding the full rows = 5 demo.
Pro Tip: if the output is a vertical list of single digits per line, you almost certainly put print() inside the inner loop.
Mistakes that commonly break left-aligned descending number triangles.
Each digit lands on its own line — you get a column, not a triangle.
→ Use print(j, end="") for digits; print() only after the inner loop.
range(rows, 0, -1) on every row prints a full rectangle — the stop must change with i.
→ Keep for j in range(rows, i, -1): so each row shortens correctly.
for i in range(rows, 0, -1): with range(i, 0, -1) gives Program 3’s shape, not this one.
→ Use for i in range(0, rows): with range(rows, i, -1).
Omitting print() glues every digit onto one endless line.
→ Always end the row after the inner loop.
int(input())Letters or empty input raise ValueError with bare int(input()).
→ Catch ValueError and re-prompt on failure.
Check these inputs before calling the solution done.
Output is just the digit rows on one line.
Outer loop never runs — print nothing or show a message.
rows < 0Treat as invalid; re-prompt instead of silent empty output.
Two rows: 21 and 2.
Bare int(input()) raises ValueError on bad input — use try/except first.
Each row prints rows - i digits — total work grows as n(n+1)/2.
Try these variations to lock in the pattern.
print(j, end=" ") between digitsi = 0..rows-1. Inner loop: j = rows..i+1 via range(rows, i, -1).print(j, end="") stays on the line; print() advances — mix them carefully.rows > 0 for interactive programs; rows = 1 should print a single digit matching rows.rows — compare with Program 3 where the start digit shifts each row.Quick Takeaway: outer loop i = 0..rows-1, inner loop range(rows, i, -1) with print(j, end=""), then print().
| Program | Time | Extra space |
|---|---|---|
| Nested loops (Examples 1–3) | O(n²) | O(1) |
| Smaller demo (Example 3) | O(n²) | O(1) |
The left-aligned descending number triangle is a compact nested-loop lesson: a fixed inner start at rows with a shrinking stop on each row. Master the fixed-rows version, then try user input and spaced output.
Practice the three examples above, then continue to Program 5 for the ascending number triangle.
Every row starts at rows — keep print(j, end="") for digits and print() for the break.
for i in range(0, rows): in the outer loopfor j in range(rows, i, -1): always starts at rowsprint(j, end="") for digits and print() after each rowrows ≥ 1 for interactive programsint(input()) in try/except ValueErrorprint() inside the inner digit looprange(rows, 0, -1) for the outer loop (that is Program 3)range() stop is exclusiverows = 1 edge casePrint the pattern the beginner-friendly way.
Every row starts at rows
Definitionrange(0, rows)
Coderange(rows, i, -1)
CodeEnds each row
ShapeO(n²) time
AnalysisEach row starts at rows and counts down to a shrinking limit. Row i prints rows - i digits — total prints = n(n+1)/2; output is left-aligned with no leading spaces.
Move on to the ascending number triangle in the Python number-pattern series.
12 people found this page helpful