S3Q2 · Numeric Palindrome Hourglass¶
⚡ Quick Reference
Type: Full I/O - pattern printing
Core idea: build each row as a palindrome 1..k..1, center it with n-k leading spaces.
n = int(input())
def make_row(k):
nums = list(range(1, k + 1)) + list(range(k - 1, 0, -1))
return " " * (n - k) + " ".join(map(str, nums))
for k in range(n, 0, -1): # top half: n down to 1
print(make_row(k))
for k in range(2, n + 1): # bottom half: 2 up to n
print(make_row(k))
Key rules:
- Row k palindrome: 1 2 ... k ... 2 1 (length 2k-1 numbers)
- Leading spaces = n - k (widest row has 0 padding)
- Top half: k = n, n-1, ..., 1
- Bottom half: k = 2, 3, ..., n (mirrors top, excludes middle)
- Total rows: 2n - 1
Problem Statement¶
Problem (I/O type)
Read n. Print a numeric palindrome hourglass with 2n-1 rows. Top half narrows from k=n to k=1; bottom half widens from k=2 to k=n.
Example - n = 3:
3
1 2 3 2 1
1 2 1
1
1 2 1
1 2 3 2 1
Deriving the pattern¶
Each row with parameter k has:
- Content: numbers 1, 2, ..., k, ..., 2, 1 - a palindrome of 2k-1 numbers
- Width: 2k-1 characters (spaces between numbers)
- Leading spaces: n - k (to center within the widest row of width 2n-1)
n=3, k=3: spaces=0, row = "1 2 3 2 1"
n=3, k=2: spaces=1, row = " 1 2 1" (1 leading space)
n=3, k=1: spaces=2, row = " 1" (2 leading spaces)
Hourglass structure:
Top half: k = n → n-1 → ... → 1 (narrows downward)
Bottom half: k = 2 → 3 → ... → n (widens downward, skips k=1)
Tracing n = 4¶
k |
Leading spaces | Row content |
|---|---|---|
| 4 | 0 | 1 2 3 4 3 2 1 |
| 3 | 1 | · 1 2 3 2 1 |
| 2 | 2 | · · 1 2 1 |
| 1 | 3 | · · · 1 ← middle |
| 2 | 2 | · · 1 2 1 |
| 3 | 1 | · 1 2 3 2 1 |
| 4 | 0 | 1 2 3 4 3 2 1 |
Total: 2×4 - 1 = 7 rows ✓
Solution approaches¶
n = int(input())
def make_row(k):
# Build palindrome list: [1, 2, ..., k, ..., 2, 1]
ascending = list(range(1, k + 1))
descending = list(range(k - 1, 0, -1))
nums = ascending + descending
# Center with leading spaces
padding = " " * (n - k)
return padding + " ".join(str(x) for x in nums)
# Top half: widest to narrowest
for k in range(n, 0, -1):
print(make_row(k))
# Bottom half: second narrowest to widest (skip k=1)
for k in range(2, n + 1):
print(make_row(k))
n = int(input())
max_width = 2 * (2 * n - 1) - 1 # max chars including spaces between
def make_row(k):
nums = list(range(1, k + 1)) + list(range(k - 1, 0, -1))
row = " ".join(map(str, nums))
return row.rjust(len(row) + (n - k)) # right-pad equivalent
for k in range(n, 0, -1):
print(make_row(k))
for k in range(2, n + 1):
print(make_row(k))
n = int(input())
make_row = lambda k: (
" " * (n - k) +
" ".join(map(str, list(range(1, k+1)) + list(range(k-1, 0, -1))))
)
rows = list(range(n, 0, -1)) + list(range(2, n + 1))
print("\n".join(map(make_row, rows)))
Lambda builds each row; the rows list defines the hourglass order. "\n".join(map(...)) prints all in one call.
Key takeaways¶
Palindrome row: range(1,k+1) + range(k-1,0,-1)
Concatenating ascending and descending ranges builds the palindrome without repeating the peak. range(k-1, 0, -1) starts just below the peak and goes down to 1.
Leading spaces = n - k
The widest row (k=n) needs 0 spaces; the narrowest (k=1) needs n-1 spaces. The formula n - k gives the correct padding for any row.
Bottom half skips k=1 (middle row)
The bottom loop starts at k=2, not k=1. The middle row (k=1) is printed once by the top half. Starting the bottom at k=2 avoids duplicating it.