Python Hollow Diamond Star Pattern

Beginner
8 min read
Updated: Sep 2026
3 programs
Live preview

What Is This Pattern?

A hollow diamond star pattern prints only the outline of a diamond: spaces fill the interior, and stars sit on the diagonals. Half-height rows means 2 * rows - 1 printed lines.

Remember
Rule: upper i = 1..rows, then lower i = rows-1..1
      On each row, print "*" where j == i or k == i

    *
   * *
  *   *
 *     *
*       *
 *     *
  *   *
   * *
    *       ← rows = 5 (9 lines)

Build it by stacking Program 7 (upper hollow V) and Program 8 (lower hollow V), starting the second outer loop at rows - 1 so the waist prints once.

How to Solve It

Print one hollow row with two inner loops, then call that idea twice — ascending, then descending past the waist.

MethodIdeaBest for
Dual outer loopsUpper 1..rows, lower rows-1..1, same j/k bodiesLearning, interviews, clearest stack of P7 + P8
Helper + ternaryOne print_row(i, rows) called from both halvesLess duplication once the geometry clicks

Pseudocode

Pseudocode
printHollowRow(i, rows):
    for j from rows down to 1:
        print "*" if i == j else " " (no newline)
    for k from 2 to rows:
        print "*" if i == k else " " (no newline)
    print newline

for i from 1 to rows:          // upper half
    printHollowRow(i, rows)
for i from rows - 1 down to 1: // lower half (skip waist)
    printHollowRow(i, rows)

Cheat sheet

GoalPattern
Upper halffor i in range(1, rows + 1):
Lower half (no duplicate waist)for i in range(rows - 1, 0, -1):
Left diagonalfor j in range(rows, 0, -1):; star when i == j
Right diagonalfor k in range(2, rows + 1):; star when i == k
End the rowprint() after both inner loops
Filled diamond nextProgram 10

Printing Stars vs Starting a New Line

APIEffectUse for
print("*", end="") / print(" ", end="")Stays on the same lineEach * or space
print()Ends the current lineAfter both j and k loops

Print characters without a newline, then end the row once.

Live Preview

Change the half-height and the hollow diamond updates instantly — including line and outline-star counts.

Whole numbers from 1 to 12. You get 2 * rows - 1 lines. Tap a chip or type a value — the preview redraws as you go.

Live result 5 half · 9 lines · 16 stars
    *    
   * *   
  *   *  
 *     * 
*       *
 *     * 
  *   *  
   * *   
    *    

Worked Walkthrough — rows = 4

Trace each outer value of i. Stars land where j == i (left leg) or k == i (right leg). Spaces show as ·.

HalfiPrinted rowStars
Upper1···*···1
Upper2··*·*··2
Upper3·*···*·2
Upper (waist)4*·····*2
Lower3·*···*·2
Lower2··*·*··2
Lower1···*···1

Lines: 4 + 3 = 7 = 2×4 - 1. Outline stars: 12 = 4×(4 - 1). Width of every line: 7.

Python Programs

Three complete programs: fixed half-height, input(), and a reusable row helper. Use View Output to reveal sample results.

Example 1 — Fixed rows = 5

Upper i = 1..rows, lower i = rows-1..1, same j/k bodies.

Python
rows = 5

# Upper half: i = 1 .. rows
for i in range(1, rows + 1):
    for j in range(rows, 0, -1):
        if i == j:
            print("*", end="")
        else:
            print(" ", end="")
    for k in range(2, rows + 1):
        if i == k:
            print("*", end="")
        else:
            print(" ", end="")
    print()

# Lower half: skip duplicate waist
for i in range(rows - 1, 0, -1):
    for j in range(rows, 0, -1):
        if i == j:
            print("*", end="")
        else:
            print(" ", end="")
    for k in range(2, rows + 1):
        if i == k:
            print("*", end="")
        else:
            print(" ", end="")
    print()

How It Works

1. Set half-height. rows = 5 means 5 upper lines and 4 lower lines (9 total).

2. Upper half grows outward. i runs from 1 to rows. Left loop j and right loop k print * only when they equal i.

3. Lower half mirrors without a second waist. i runs from rows - 1 down to 1 with the same inner logic.

4. Print the row. Bare print() after both inner loops starts the next outline row.

Example 2 — User Input Version

Read the half-height at runtime. Prefer a try / except in real apps (shown in the tip below).

Python
rows = int(input("Enter the number of rows: "))

for i in range(1, rows + 1):
    for j in range(rows, 0, -1):
        print("*" if i == j else " ", end="")
    for k in range(2, rows + 1):
        print("*" if i == k else " ", end="")
    print()

for i in range(rows - 1, 0, -1):
    for j in range(rows, 0, -1):
        print("*" if i == j else " ", end="")
    for k in range(2, rows + 1):
        print("*" if i == k else " ", end="")
    print()

How It Works

1. Prompt and read. input() returns a string; int(...) converts it to a whole number.

2. Same dual-half core. Only the source of rows changes — the print logic matches Example 1 (ternaries shorten the if/else).

3. Safer input tip. int(input()) raises ValueError on letters. Prefer:

Safer input
raw = input("Enter the number of rows: ").strip()
try:
    rows = int(raw)
except ValueError:
    print("Enter a positive whole number.")
    raise SystemExit
if rows < 1:
    print("Enter a positive whole number.")
    raise SystemExit

Example 3 — Helper Function

Extract one row printer so the diamond reads as “upper, then lower.”

Python
def print_row(i, rows):
    for j in range(rows, 0, -1):
        print("*" if i == j else " ", end="")
    for k in range(2, rows + 1):
        print("*" if i == k else " ", end="")
    print()

rows = 5

for i in range(1, rows + 1):
    print_row(i, rows)

for i in range(rows - 1, 0, -1):
    print_row(i, rows)

How It Works

1. One row recipe. print_row owns the j/k diagonal logic and the row break.

2. Call it twice. Upper half walks i up; lower half walks i down from rows - 1.

3. Same shape, less copy-paste. Learn the expanded loops first (Example 1), then refactor when the geometry feels familiar.

Edge Cases & Pitfalls

Check these before calling the solution done.

Lower starts at rows

Double waist

If the second outer loop starts at i = rows, the widest line prints twice. Use range(rows - 1, 0, -1).

k from 1

Extra center column

Right loop must start at k = 2. Starting at 1 overlaps the left half’s last column and skews the diamond.

print() inside

Broken outline

If bare print("*") sits inside j or k, the outline collapses into a column. Use end="" for characters; print() only after both inner loops.

Proportional font

Looks skewed in the IDE

Spaces and stars need a monospace font. Proportional fonts make diagonals look uneven.

rows = 1

Single star

Upper prints one line; lower never runs. Output is just * — a good sanity check.

Bad input

Catch ValueError

int(input()) throws on letters — prefer try / except ValueError.

Time and Space Complexity

ProgramTimeExtra space
Dual loops (Examples 1–2)O(rows²)O(1)
Helper function (Example 3)O(rows²)O(1)

Lines printed = 2n - 1. Each line walks about 2n - 1 positions across the two inner loops, so work is still quadratic in n. Outline stars grow as 4(n - 1) for n ≥ 2 (and 1 when n = 1).

Key Takeaways

  • Compose halves: upper 1..rows then lower rows-1..1 — Programs 7 + 8 with one seam fix.
  • Diagonal rule: star only when i == j or i == k; everything else is a space.
  • Break the row: print(..., end="") for characters; bare print() after both inner loops.
  • Complexity: O(n²) time; O(1) extra space.

One line: print hollow rows for i = 1..rows, then again for i = rows-1..1, starring only the diagonals.

Frequently Asked Questions

Two sequential outer loops share the same inner structure. The first runs i from 1 to rows (upper half). The second runs i from rows minus 1 down to 1 (lower half). On each row, j and k print stars when they equal i.
The first part already prints the widest row when i equals rows. Starting the second part at rows again would duplicate that waist line. rows minus 1 mirrors the upper half without a double middle.
Yes, by mapping a loop index to an effective row i or by branching on upper vs lower half. Splitting into two loops matches Programs 7 and 8 mentally and keeps each block easy to read.
rows + (rows - 1) = 2 * rows - 1 lines. Each line is also 2 * rows - 1 characters wide.
print("*", end="") stays on the same line. print() ends the current line. Stars and spaces use end=""; the row break uses print() after both inner loops.
With n rows, about 2n - 1 printed lines, each with Theta(n) work across two inner loops, giving O(n²).
Program 9 draws only the outline (hollow). Program 10 fills every star in a solid diamond using spaces and 2*i-1 star runs.
Wrap int(input()) in try/except ValueError, or check that the raw string is digits, and require rows >= 1.

Did you know?

This hollow diamond is a direct composition: Program 7’s upper half plus Program 8’s lower half with the duplicate middle row removed by starting the second phase at rows - 1. Total printed lines = 2 * rows - 1.

Next: Filled Diamond

Same half-stacking idea, but with solid centered star runs instead of a hollow outline.

Program 10 tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

12 people found this page helpful