A mirrored number pattern prints left digits 1..i and right digits i..1 inside two fixed-width loops — spaces fill unused columns so both halves stay aligned.
Remember
Rule: for i = 1..rows
left = j if j <= i else space (j = 1..rows)
right = space if k > i else k (k = rows..1)
1 1
12 21
123 321
1234 4321
1234554321 ← rows = 5
Unlike Program 27’s tight palindrome, this version keeps a shrinking gap — a natural step after the 0-centered mirror in Program 28.
Approach
How to Solve It
Walk i from 1 to rows; fill a left half of width rows, then a right half of width rows.
Method
Idea
Best for
Two fixed loops
Left digits/spaces + right spaces/digits
Learning, interviews
input() rows
Same loops; conditional expressions
Interactive practice
Compact rows = 3
Same structure; easier to trace by hand
Paper walkthrough
Pseudocode
Pseudocode
for i from 1 to rows:
for j from 1 to rows:
print j if j <= i else " " (same line)
for k from rows down to 1:
print " " if k > i else k (same line)
print newline
Cheat sheet
Goal
Pattern
Set rows
rows = 5
Outer loop
for i in range(1, rows + 1):
Left half
print(j if j <= i else " ", end="")
Right half
print(" " if k > i else k, end="")
End row
print()
if/else form
if j <= i: print(j, end="") else: print(" ", end="")
User input
rows = int(input("Enter rows: "))
Printing Numbers vs Starting a New Line
API
Effect
Use for
print(j, end="") / print(" ", end="")
Stays on the same line
Each digit or space
print()
Ends the current line
After both halves
Glue characters with end="", then break once with print(). Putting print() inside an inner loop prints one character per line.
Try it
Live Preview
Change the row count and the spaced mirror updates instantly.
Whole numbers from 1 to 9. Tap a chip or type a value — the preview redraws as you go.
Live resultrows = 5 · width = 10
1 1
12 21
123 321
1234 4321
1234554321
Trace
Worked Walkthrough — rows = 3
Trace each outer i, the left half, the right half, and the printed row.
i
Left j=1..3
Right k=3..1
Printed row
1
1 + 2 spaces
2 spaces + 1
1 1
2
12 + 1 space
1 space + 21
12 21
3
123
321
123321
Gap spaces between digit groups = 2 * (rows - i) — zero when i = rows.
Code
Python Programs
Three complete programs: fixed rows = 5, input() rows, and compact rows = 3. Use View Output for sample results.
Example 1 — Fixed rows = 5
Hard-coded row count — left loop j = 1..5, right loop k = 5..1, with if/else for digits vs spaces.
Python
for i in range(1, 6):
for j in range(1, 6):
if j <= i:
print(j, end="")
else:
print(" ", end="")
for k in range(5, 0, -1):
if k > i:
print(" ", end="")
else:
print(k, end="")
print()
Output
1 1
12 21
123 321
1234 4321
1234554321
How It Works
1. Outer loop.i runs from 1 to 5 — how many digit columns are active on each side.
2. Left half. For j = 1..5, print j when j <= i, else a space.
3. Right half. For k = 5..1, print a space when k > i, else print k; then print() ends the row.
Example 2 — input() Rows
Read the row count at runtime; use conditional expressions in both inner loops.
Python
rows = int(input("Enter rows: "))
if rows < 1:
print("Please enter a positive integer.")
else:
for i in range(1, rows + 1):
for j in range(1, rows + 1):
print(j if j <= i else " ", end="")
for k in range(rows, 0, -1):
print(" " if k > i else k, end="")
print()
Output (when user enters 4)
Enter rows: 4
1 1
12 21
123 321
12344321
How It Works
1. Read and validate. Parse the answer; reject non-positive input.
2. Same shape. Both inner loops still run rows times — only the bound changes.
3. Safer input tip. Bare int(input()) raises ValueError on letters. Prefer:
Safer input
raw = input("Enter 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 — Compact rows = 3
Same if/else structure with a smaller row count — easy to trace on paper.
Python
rows = 3
for i in range(1, rows + 1):
for j in range(1, rows + 1):
if j <= i:
print(j, end="")
else:
print(" ", end="")
for k in range(rows, 0, -1):
if k > i:
print(" ", end="")
else:
print(k, end="")
print()
Output
1 1
12 21
123321
How It Works
1. Same structure. Outer and both inner loops match Example 1.
2. Only rows changes. Width is 3 per half — final row is 123321 with no gap.
3. Trace first. Walk i = 1, 2, 3 on paper before scaling to 5 or more.
Edge Cases & Pitfalls
Check these before calling the solution done.
no spaces
Missing filler spaces
Printing only digits collapses the gap — the right half slides left and the mirror no longer looks centered.
wrong bound
Inner loop to i only
Both loops must run to rows, not i. Stopping early removes the alignment spaces.
print() inside
Vertical output
If print() is inside either inner loop, each character lands on its own line. Call it only after both halves.
rows = 1
Smallest mirror
Output is 11 — left prints 1, right prints 1, no gap.
flip test
Swapped conditions
Using j > i for digits on the left (or k <= i for spaces on the right) breaks the shape.
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)
n rows, each with two loops of width n → O(n²).
Remember
Key Takeaways
Rule: left 1..i (pad spaces), right i..1 (pad spaces).
Fixed width: both inner loops always run rows times.
end= vs print(): characters stay on the line; print() advances after each row.
Complexity:O(n²) for n rows.
One line: grow digits from both sides while spaces shrink the middle gap until the last row joins.
Frequently Asked Questions
Spaces keep the left and right halves aligned so the pattern looks symmetric. Without them, the right half shifts left each row.
The right loop runs k from rows down to 1. When k > i it prints a space; otherwise it prints k — building i..1 on the right.
Both inner loops always run rows times. Extra positions are filled with spaces so columns stay aligned.
Program 27 prints a tight palindrome with no alignment spaces. Program 29 uses fixed-width loops and spaces for a symmetric spaced mirror.
When i equals rows, both halves fill all columns — 12345 on the left and 54321 on the right meet with no space between.
Replace 5 with rows in both inner loop bounds — see Example 2.
O(n²) for n rows because each row runs two inner loops of width n.
Use try/except ValueError around int(input()) or check the raw string with .isdigit() before converting so bad input does not crash the script.
Yes — print(j if j <= i else " ", end="") compacts the if/else logic in Python.
🤔
Did you know?
This pattern prints an increasing left half (1..i), then a mirrored right half (i..1). Spaces in the fixed-width loops keep both halves aligned until the final row joins without a gap.