Mirror Diagonal Diamond in JavaScript

Beginner
⏱️ 10 min read
📚 Updated: Sep 2026
🎯 3 Code Examples
🚀 Live Preview
Symmetry + Nested Loops

What You’ll Learn

Program 54 prints a mirror diagonal diamond pattern: the top half matches Program 53’s V-shape, then a second outer loop mirrors it downward to form a full diamond — a natural step after Program 53’s mirror diagonal pattern. This tutorial covers two outer loops, i === j and i === k conditions, a live preview, worked JavaScript examples, edge cases, and complexity.

Shape Rule

Full diamond

Top half grows from 1 to rows; bottom half mirrors from rows-1 back to 1 — total 2n-1 lines.

Top Outer Loop

i = 1..rows

for (let i = 1; i <= rows; i++) logs the upper V-half — same logic as Program 53.

Bottom Outer Loop

i = rows-1..1

for (let i = rows - 1; i >= 1; i--) mirrors the top half without duplicating the peak row.

Left Diagonal

i === j

line += (i === j ? i : " ") — digit on the main diagonal each row.

Right Diagonal

i === k

line += (i === k ? i : " ") — mirrored diagonal; right loop starts at rows-1.

O(n²)

Complexity

About 2n-1 lines, each scanning 2n-1 positions — total work grows as O(n²).

Introduction

A mirror diagonal diamond pattern extends Program 53’s V-shape: print the top half from 1 to rows, then mirror the same row logic from rows-1 back to 1. With rows = 5, you get nine lines ending with 1 1 at the bottom.

In JavaScript, use two outer loops — top and bottom — each with left (i === j) and right (i === k) inner loops, appending spaces elsewhere before console.log(line).

Why it matters?

It bridges Program 53’s single V-half to full symmetry — teaching how to mirror loop ranges without duplicating the peak row.

Key Highlights

Top half

i = 1..rows — same as Program 53.

Bottom half

i = rows-1..1 — mirrors without duplicating the peak.

vs Program 53

Program 53 stops at the V tip; Program 54 adds a second outer loop to complete the diamond.

Series Foundation

Follow Program 53; continue to Program 55 next.

In short: top loop for (let i = 1; i <= rows; i++), bottom loop for (let i = rows - 1; i >= 1; i--), each row uses i === j and i === k, then console.log(line).

📝 Problem & Approach

Given row count rows = 5, print a mirror diagonal diamond — top half grows to rows, bottom half mirrors back to 1.

JavaScript
// rows = 5
// 1       1
//  2     2
//   3   3
//    4 4
//     5
//    4 4
//   3   3
//  2     2
// 1       1

Inputs & Outputs

ItemTypeDescription
rowsnumberPeak row of the diamond (total lines = 2n-1).
i (top outer)numberRuns 1 to rows for the upper half.
i (bottom outer)numberRuns rows-1 down to 1 for the lower half.
j (left)numberScans 1..rows; appends digit when i === j.
k (right)numberScans rows-1..1; appends digit when i === k.
Total linesnumber2 * rows - 1 lines for a complete diamond.

Minimal workflow

Pseudocode
for i from 1 to rows:
    line = ""
    append digit when i === j or space (left loop)
    append digit when i === k or space (right loop)
    console.log(line)
for i from rows - 1 down to 1:
    same row logic (mirror bottom half)

Approach comparison

ApproachIdeaBest for
Two outer loopsTop 1..rows, bottom rows-1..1Learning symmetry and loop bounds
Reuse row logicSame inner loops in both outer loopsDRY diamond construction
User-input rowsparseInt(prompt())Flexible diamond size
Compact tracerows = 3 on paper firstQuick dry-runs (5 lines total)
Extract row methodPrintRow(i, rows) called twiceCleaner code after mastering loops

⚡ Quick Reference

GoalPattern
Top outer loopfor (let i = 1; i <= rows; i++)
Bottom outer loopfor (let i = rows - 1; i >= 1; i--)
Left halffor (let j = 1; j <= rows; j++) line += (i === j ? i : " ");
Right halffor (let k = rows - 1; k >= 1; k--) line += (i === k ? i : " ");
End rowconsole.log(line);
Program 53 contrastProgram 53 prints top V-half only; Program 54 adds bottom mirror loop

📋 Fixed Rows vs User Input vs Compact Trace

Same diamond — three ways to set row count and trace the symmetry.

Fixed rows
rows = 5

Hard-coded peak for demos (9 lines)

User input
parseInt(prompt())

Read peak row from console

Compact trace
rows = 3

5-line diamond for paper tracing

Top half
i = 1..rows

Upper V — same as Program 53

Bottom half
i = rows-1..1

Mirror without duplicating peak

Context

When This Pattern Shows Up

Reach for this pattern when teaching symmetry, mirrored loop ranges, and completing a V-shape into a diamond.

  1. Post Program 53 exercise

    Natural follow-up after Program 53’s V-half — adds the bottom mirror loop to complete the diamond.

  2. Symmetry drills

    Teaches why the bottom loop starts at rows-1 — a pattern used in many diamond and pyramid programs.

  3. Two outer loops

    About 2n-1 lines, each scanning 2n-1 positions — concrete O(n²) complexity.

  4. Gateway to Program 55

    Compare this number diamond with the next pattern in the series.

  5. Not a UI layout tool

    This is a console teaching pattern — not how you build modern app screens.

Key benefit: one small program that locks in symmetry, mirrored loop bounds, and O(n²) thinking.

🔮 Live Preview

Choose peak row count between 3 and 9 and draw the full mirror diagonal diamond in the browser.

Try 4, 5, or 7. Max up to 9 in this preview.

Live result
Press "Draw pattern".

Examples Gallery

Three complete JavaScript programs — fixed rows, user input, and a compact trace demo. Click View Output to reveal sample console results, or Try it Yourself to run in the browser.

📚 Getting Started

Print a full mirror diagonal diamond with peak row 5 — top V-half plus mirrored bottom half.

Example 1 — Fixed rows = 5

Hard-coded peak row — top loop 1..rows, bottom loop rows-1..1, same inner diagonal logic each row.

JavaScript
const rows = 5;

for (let i = 1; i <= rows; i++) {
  let line = "";

  for (let j = 1; j <= rows; j++) {
    line += (i === j ? i : " ");
  }

  for (let k = rows - 1; k >= 1; k--) {
    line += (i === k ? i : " ");
  }

  console.log(line);
}

for (let i = rows - 1; i >= 1; i--) {
  let line = "";

  for (let j = 1; j <= rows; j++) {
    line += (i === j ? i : " ");
  }

  for (let k = rows - 1; k >= 1; k--) {
    line += (i === k ? i : " ");
  }

  console.log(line);
}
Try it Yourself

How It Works

The first outer loop logs rows 1 through 5 (Program 53’s V-half). The second outer loop logs rows 4 down to 1, reusing the same inner loops — nine lines total without duplicating row 5.

📈 User Input

Read peak row count with prompt() and Number.isFinite validation.

Example 2 — User Input Rows

Read rows with prompt() and validate the result.

JavaScript
const rowsInput = prompt("Enter the number of rows:");
const rows = parseInt(rowsInput, 10);

if (!Number.isFinite(rows) || rows < 1) {
  console.log("Please enter a positive integer.");
} else {
  for (let i = 1; i <= rows; i++) {
    let line = "";

    for (let j = 1; j <= rows; j++) {
      line += (i === j ? i : " ");
    }

    for (let k = rows - 1; k >= 1; k--) {
      line += (i === k ? i : " ");
    }

    console.log(line);
  }

  for (let i = rows - 1; i >= 1; i--) {
    let line = "";

    for (let j = 1; j <= rows; j++) {
      line += (i === j ? i : " ");
    }

    for (let k = rows - 1; k >= 1; k--) {
      line += (i === k ? i : " ");
    }

    console.log(line);
  }
}
Try it Yourself

How It Works

Same two-outer-loop diamond core as Example 1; only the source of rows changes from a literal to user input.

⚡ Compact Trace

Smaller peak row for quick tracing on paper or in interviews.

Example 3 — Compact rows = 3

Use rows = 3 to trace top loop, bottom loop, and symmetry before scaling to 5 rows.

JavaScript
const rows = 3;

for (let i = 1; i <= rows; i++) {
  let line = "";

  for (let j = 1; j <= rows; j++) {
    line += (i === j ? i : " ");
  }

  for (let k = rows - 1; k >= 1; k--) {
    line += (i === k ? i : " ");
  }

  console.log(line);
}

for (let i = rows - 1; i >= 1; i--) {
  let line = "";

  for (let j = 1; j <= rows; j++) {
    line += (i === j ? i : " ");
  }

  for (let k = rows - 1; k >= 1; k--) {
    line += (i === k ? i : " ");
  }

  console.log(line);
}
Try it Yourself

How It Works

Five lines total — top 3 rows plus bottom 2 — let you trace both outer loops on paper before running the full rows = 5 demo.

🧠 How the Algorithm Prints Rows

1

Set peak row

const rows = 5; — the diamond will have 2*rows-1 = 9 lines.

Setup
2

Print top half

for (let i = 1; i <= rows; i++) — same V-half logic as Program 53.

Top
3

Place diagonals each row

Left loop i === j, right loop i === k — spaces fill all other columns.

Diagonals
4

Mirror bottom half

for (let i = rows - 1; i >= 1; i--) reuses the same inner loops — skips the peak row.

Bottom
=

Mirror diagonal diamond complete

2n-1 lines, each about 2n-1 characters — O(n²) time, O(1) extra memory.

🔎 Worked Walkthrough — rows = 5

Trace each line’s outer-loop phase, diagonal positions, and full output.

LinePhaseiRow output
1Top11 1
2Top22 2
3Top33 3
4Top44 4
5Top (peak)55
6Bottom44 4
7Bottom33 3
8Bottom22 2
9Bottom11 1

The bottom loop starts at i = rows - 1 so line 5 (the peak) is not printed twice.

Use Cases

Where this tiny pattern (and its loop structure) shows up beyond the homework prompt.

1. Teaching Nested Loops

Two outer loops mirror the same row logic — top then bottom.

Example: trace lines 1–9 in the walkthrough table.

2. Symmetry Drills

The bottom loop starting at rows-1 is a classic symmetry trick used in many diamond patterns.

Example: line 5 is the peak; lines 6–9 mirror lines 4–1.

3. Output Formatting Drills

Practice line += (i === j ? i : " ") vs console.log(line) with two inner loops per row.

Example: put console.log(line) inside the inner loop by mistake.

4. Diamond Line Count

Total lines = 2n-1 — links symmetry to loop-bound formulas.

Example: Peak row 10 produces 19 lines total.

5. Complexity Intuition

Growing inner bound makes O(n²) concrete — count prints for n rows.

Example: Peak row 5 produces 9 lines — see the walkthrough table.

6. Input Validation Labs

Pair the pattern with Number.isFinite and positive-row checks after parseInt(prompt()).

Example: reject rows <= 0 and re-prompt.

Pro Tip: when an interviewer asks for patterns, explain outer/inner roles first — then write the loops. The story matters as much as the code.

Advantages

Why this pattern earns a permanent spot in beginner JavaScript courses.

  1. 1. Instant Visual Feedback

    Starting the bottom loop at rows duplicates the peak row immediately.

  2. 2. Real Math Connection

    Two outer loops teach real symmetry — not abstract loop drill.

  3. 3. Easy to Extend

    Change rows, use fixed-width format, or switch to full rectangular table.

  4. 4. O(1) Extra Memory

    Streaming output needs no storage beyond loop counters.

Pro Tip: trace rows = 3 on paper — 5 lines total, peak at line 3.

Usage Tips

Small habits that keep number-pattern code clean.

  1. 1. Left loop j = 1..rows

    Scan all columns in the left half — append digit only when i === j.

  2. 2. Validate with Number.isFinite

    Avoid crashes when the user types letters instead of a number.

  3. 3. console.log After Both Inner Loops

    Only call console.log(line) after both inner loops finish the row.

  4. 4. Right loop k = rows-1..1

    Start the right loop at rows - 1 to skip duplicating the center column.

  5. 5. Dry-Run rows = 5

    Trace five rows on paper before coding the full 10-row demo.

Pro Tip: if the output is a vertical list of single numbers, you almost certainly put console.log(line) inside the inner loop.

Common Pitfalls

Mistakes that commonly break mirror diagonal diamond patterns.

  1. 1. console.log Inside Inner Loop

    Each character lands on its own line — you get a column, not a diamond.

    → Use line += (i === j ? i : " ") in both loops; console.log(line) only after both inner loops.

  2. 2. Bottom Loop Starts at rows

    Starting the bottom outer loop at i = rows prints the peak row twice.

    → Use for (let i = rows - 1; i >= 1; i--) for the bottom half.

  3. 3. Duplicating Peak Row

    The middle row of the diamond appears twice — breaking symmetry.

    → Start the bottom outer loop at rows - 1, not rows.

  4. 4. Forgetting console.log After Row

    All numbers log on one long line without row breaks.

    → Add console.log(line) after both inner loops complete.

  5. 5. Blind parseInt(prompt())

    Letters or empty input return NaN when parseInt(prompt()) is unchecked.

    → Validate with Number.isFinite(rows) and re-prompt on failure.

Edge Cases

Check these inputs before calling the solution done.

rows = 1

Single row

Output is just 1 — the right loop does not run.

rows = 0

Empty output

Outer loop never runs — print nothing or show a message.

Negative

rows < 0

Treat as invalid; re-prompt instead of silent empty output.

rows = 5

Compact trace

Peak row 5 produces 9 lines — good for dry-runs.

Bad input

Non-numeric input

Unchecked parseInt(prompt()) returns NaN — use Number.isFinite.

Large rows

Wide output

Row 9 scans 17 character positions — total work grows as O(n²).

🎯 Practice Problems

Try these variations to lock in the pattern.

1. Compare with Program 53

  • Program 53 prints only the top V-half
  • Program 54 adds the bottom mirror loop for a full diamond

2. Change peak row

  • Try rows = 4 or rows = 7 in the live preview
  • Count total lines — should always be 2n-1

3. Next in series

  • Continue with Program 55
  • Build on mirror diagonal diamond patterns

4. Extract PrintRow method

  • Move inner loops into PrintRow(i, rows)
  • Call it from both outer loops — same output, cleaner code

Notes

  • Two outer loops. Top: i = 1..rows. Bottom: i = rows-1..1. Same inner loops in both.
  • line += ... builds the row; console.log(line) advances — call it after both inner loops finish each row.
  • Validate rows > 0 for interactive programs; total output lines = 2*rows - 1.
  • About 2n-1 lines, each scanning 2n-1 positions — total work is O(n²).

Quick Takeaway: top loop for (let i = 1; i <= rows; i++), bottom loop for (let i = rows - 1; i >= 1; i--), each row uses i === j and i === k, then console.log(line).

⏱️ Time and Space Complexity

ProgramTimeExtra space
Nested loops (Examples 1–3)O(n²)O(1)
Total lines2n - 1About 2n-1 chars per line
Wrap Up

🎉 Conclusion

The mirror diagonal diamond pattern is a natural follow-up to Program 53: add a second outer loop to mirror the V-half downward into a full symmetric diamond. Master the fixed-rows version, then try user input and the compact 3-row trace.

Practice the three examples above, then continue to Program 55 for the next pattern in the series.

Total lines = 2n-1 — bottom loop starts at rows-1 to avoid duplicating the peak.

💡 Best Practices

✅ Do

  • Top loop: for (let i = 1; i <= rows; i++)
  • Bottom loop: for (let i = rows - 1; i >= 1; i--)
  • Reuse the same inner loops in both outer loops
  • Call console.log(line) after both inner loops each row
  • Use Number.isFinite for user input

❌ Don’t

  • Start bottom loop at i = rows — duplicates the peak row
  • Change inner loop logic between top and bottom halves
  • Call console.log(line) inside either inner loop
  • Ignore bad input in user-facing demos
  • Skip the rows = 3 dry-run before coding rows = 5

Key Takeaways

Knowledge Unlocked

Five things to remember about this mirror diagonal diamond

Print the full diamond the beginner-friendly way.

5
Core concepts
02

Top loop

i = 1..rows

Code
03

Bottom loop

i = rows-1..1

Code
04

Line count

2n - 1 lines

Logic
O 05

Complexity

O(n²) time

Analysis

❓ Frequently Asked Questions

The first loop logs the top V-half from i = 1 to rows. The second logs the bottom half from rows-1 down to 1, mirroring the shape.
Starting at rows would log the middle row twice. rows-1 skips the peak row already logged by the top half.
It logs digits on both diagonals per row — top half grows to rows, then the bottom half mirrors back to 1, forming a symmetric diamond.
Program 53 logs only the top V-half. Program 54 adds a second outer loop to mirror the same row logic downward.
The left loop uses i === j for the main diagonal. The right loop uses i === k for the mirrored diagonal, with spaces elsewhere.
Change rows or read it from user input with parseInt(prompt()) — see Example 2.
O(n²) for n rows because the diamond has about 2n-1 lines and each line scans about 2n-1 positions.
Yes. Append when i === j or i + j === rows + 1 in a single column loop.
Use parseInt with Number.isFinite. Bare parseInt(prompt()) returns NaN on bad input.
One line logs a single 1 — the top loop runs once and the bottom loop from rows-1 down to 1 does not run.

Did you Know? 🔊

Program 53’s V-shape becomes a full diamond by adding a second outer loop from rows-1 down to 1. Total lines = 2n-1 with about 2n-1 characters per line — O(n²) overall.

Continue to Program 55

Move on to the next pattern in the JavaScript number-pattern series.

Program 55 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