A bidirectional number triangle prints a repeated digit on each shrinking row — digits rise (1, 2, 3) then mirror down (2, 1).
Remember
Rule: row i repeats val, length = rows − i + 1
val = i if i < rows − 1
else rows + 1 − i
11111
2222
333
22
1 ← rows = 5
Shrinking length plus a mapped digit — a clear follow-up after the centered pyramid in Program 24.
Approach
How to Solve It
Outer i = 1..rows; pick the row digit; inner j = i..rows repeats that digit.
Method
Idea
Best for
if/else mapping
Rise then rows + 1 - i
Learning, interviews
input() + expression
Same loops; generalize for any rows
Interactive practice
Spaced digits
print(val, end=" ")
Readable output
Pseudocode
Pseudocode
for i from 1 to rows:
if i < rows - 1:
val = i
else:
val = rows + 1 - i
for j from i to rows:
print val (same line, no spaces)
print newline
Cheat sheet
Goal
Pattern
Set rows
rows = 5
Outer loop
for i in range(1, rows + 1):
Pick digit
val = i if i < rows - 1 else rows + 1 - i
Shrink row
for j in range(i, rows + 1): print(val, end="")
End row
print()
Spaced
print(val, end=" ")
Printing Numbers vs Starting a New Line
API
Effect
Use for
print(val, end="")
Stays on the same line, no space
Each repeated 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 bidirectional triangle updates instantly.
Whole numbers from 1 to 9. Tap a chip or type a value — the preview redraws as you go.
Live result5 rows · 15 digits
11111
2222
333
22
1
Trace
Worked Walkthrough — rows = 4
Trace each i, the mapped digit, and how many times it repeats.
i
val
Repeats
Printed row
1
1 (i < 3)
4×
1111
2
2 (i < 3)
3×
222
3
2 (4 + 1 − 3)
2×
22
4
1 (4 + 1 − 4)
1×
1
The switch happens when i >= rows − 1 — that is when the digit starts mirroring down.
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 — if/else picks the digit; the inner loop shrinks each row.
Python
rows = 5
for i in range(1, rows + 1):
for j in range(i, rows + 1):
if i < 4:
print(i, end="")
else:
print(rows + 1 - i, end="")
print()
Output
11111
2222
333
22
1
How It Works
1. Outer rows.i runs from 1 to 5 — one row per value.
2. Shrink. Inner j starts at i, so row length is rows − i + 1.
3. Map digit. When i < 4, print i; otherwise print rows + 1 − i (gives 2, then 1).
Example 2 — input() Rows
Read the row count at runtime; a conditional expression generalizes the digit mapping for any size.
Python
rows = int(input("Enter rows: "))
for i in range(1, rows + 1):
val = i if i < rows - 1 else rows + 1 - i
for j in range(i, rows + 1):
print(val, end="")
print()
Output (when user enters 4)
Enter rows: 4
1111
222
22
1
How It Works
1. Read rows. Convert the prompt answer with int().
2. General mapping.i if i < rows - 1 else rows + 1 - i replaces the hard-coded i < 4.
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("Enter a positive whole number.")
raise SystemExit(1)
if rows < 1:
print("Enter a positive whole number.")
raise SystemExit(1)
Example 3 — Spaced Digits
Keep rows = 5 but print a space after each digit for easier reading.
Python
rows = 5
for i in range(1, rows + 1):
val = i if i < rows - 1 else rows + 1 - i
for j in range(i, rows + 1):
print(val, end=" ")
print()
Output
1 1 1 1 1
2 2 2 2
3 3 3
2 2
1
How It Works
1. Same structure. Outer loop, mapping, and shrinking inner loop match Example 2.
2. Only end= changes. Use end=" " instead of end="".
3. Same shape. Row lengths and digit values are unchanged — only spacing differs.
Edge Cases & Pitfalls
Check these before calling the solution done.
j = 1
Rows do not shrink
Starting the inner loop at range(1, rows + 1) keeps every row length rows. Use range(i, rows + 1).
hard 4
Hard-coded threshold
i < 4 only fits rows = 5. Prefer i < rows - 1 for other sizes.
print() inside
Vertical digits
If print() is inside the inner loop, each digit lands on its own line.
rows = 1
Single digit
Output is just 1 — the mirror branch still yields rows + 1 - i = 1.
rows ≤ 0
Empty output
The outer loop never runs. Guard interactive 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: shrink with j = i..rows; map digit up then down.
Mapping:val = i if i < rows - 1 else rows + 1 - i.
end= vs print(): digits stay on the line; print() advances after each row.
Complexity:O(n²) for n rows.
One line: shrink the row from the left, and flip the printed digit after the peak with rows + 1 − i.
Frequently Asked Questions
For i = 5 and rows = 5, the condition i < rows - 1 is false, so the program uses rows + 1 - i, which equals 1.
Because the inner loop runs from j = i to rows. As i increases, the inner loop executes fewer times.
Digits rise (1, 2, 3) on early rows then mirror down (2, 1) on the last rows via the rows + 1 - i mapping.
print(val, end="") repeats the digit on the same line. print() ends the row after the inner loop finishes.
A single inner loop with a digit mapping keeps the shrinking row logic in one place.
Use val = i if i < rows - 1 else rows + 1 - i (see Example 2).
O(n²) for n rows because total prints are triangular (n + (n-1) + … + 1).
Use try/except ValueError around int(input()) so bad input does not crash the script.
Only one row prints — a single 1.
🤔
Did you know?
This pattern prints repeated digits per row. The inner loop runs from j = i to rows, shrinking each row. The row digit is i for the first half, then switches to rows + 1 - i to produce 22 and 1.