PHP 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 " "
    for k from 2 to rows:
        print "*" if i == k else " "
    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 = 1; $i <= $rows; $i++)
Lower half (no duplicate waist)for ($i = $rows - 1; $i >= 1; $i--)
Left diagonal$j from $rows down to 1; star when $i == $j
Right diagonal$k from 2 to $rows; star when $i == $k
End the rowecho PHP_EOL; after both inner loops
Filled diamond nextProgram 10

Printing Stars vs Starting a New Line

APIEffectUse for
echo "*" / echo " "Stays on the same lineEach * or space
echo PHP_EOLEnds the current lineAfter both $j and $k loops

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 ·.

Half$iPrinted 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.

PHP Programs

Three complete programs: fixed half-height, CLI 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.

PHP
<?php
$rows = 5;

// Upper half: i = 1 .. rows
for ($i = 1; $i <= $rows; $i++) {
    for ($j = $rows; $j >= 1; $j--) {
        if ($i == $j)
            echo "*";
        else
            echo " ";
    }
    for ($k = 2; $k <= $rows; $k++) {
        if ($i == $k)
            echo "*";
        else
            echo " ";
    }
    echo PHP_EOL;
}

// Lower half: skip duplicate waist
for ($i = $rows - 1; $i >= 1; $i--) {
    for ($j = $rows; $j >= 1; $j--) {
        if ($i == $j)
            echo "*";
        else
            echo " ";
    }
    for ($k = 2; $k <= $rows; $k++) {
        if ($i == $k)
            echo "*";
        else
            echo " ";
    }
    echo PHP_EOL;
}
?>

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. Break the line. echo PHP_EOL after both inner loops starts the next outline row.

Example 2 — User Input Version

Read the half-height from the CLI. Prefer is_numeric in real apps (shown in the tip below).

PHP
<?php
echo "Enter the number of rows: ";
$rows = (int) trim(fgets(STDIN));

for ($i = 1; $i <= $rows; $i++) {
    for ($j = $rows; $j >= 1; $j--)
        echo ($i == $j ? "*" : " ");
    for ($k = 2; $k <= $rows; $k++)
        echo ($i == $k ? "*" : " ");
    echo PHP_EOL;
}

for ($i = $rows - 1; $i >= 1; $i--) {
    for ($j = $rows; $j >= 1; $j--)
        echo ($i == $j ? "*" : " ");
    for ($k = 2; $k <= $rows; $k++)
        echo ($i == $k ? "*" : " ");
    echo PHP_EOL;
}
?>

How It Works

1. Prompt and read. Ask for a half-height, then trim(fgets(STDIN)) and cast to int.

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. Bare (int) casts turn letters into 0. Prefer:

Safer input
echo "Enter the number of rows: ";
$input = trim(fgets(STDIN));
if (!is_numeric($input) || (int) $input < 1) {
    echo "Enter a positive whole number." . PHP_EOL;
    exit(1);
}
$rows = (int) $input;

Example 3 — Helper Function

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

PHP
<?php
function print_row($i, $rows) {
    for ($j = $rows; $j >= 1; $j--)
        echo ($i == $j ? "*" : " ");
    for ($k = 2; $k <= $rows; $k++)
        echo ($i == $k ? "*" : " ");
    echo PHP_EOL;
}

$rows = 5;

for ($i = 1; $i <= $rows; $i++)
    print_row($i, $rows);

for ($i = $rows - 1; $i >= 1; $i--)
    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 $rows - 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.

PHP_EOL inside

Broken outline

If echo PHP_EOL sits inside $j or $k, the outline collapses into a column. Call it only after both inner loops.

Proportional font

Looks skewed in the IDE

Spaces and stars need a monospace font (console default is fine). Proportional fonts make diagonals look uneven.

rows = 1

Single star

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

rows ≤ 0

Empty output

Neither outer loop runs. Validate and re-prompt for interactive programs.

Bad input

Use is_numeric

Bare (int) casts turn letters into 0 — prefer is_numeric and require $rows >= 1.

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: call echo PHP_EOL only 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.
echo stays on the same line. echo PHP_EOL ends the current line. Stars and spaces use echo; the row break uses echo PHP_EOL 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.
Use trim(fgets(STDIN)) and check is_numeric($input) before casting to int so bad input does not produce unexpected results.

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