Decreasing-Increasing Number Pattern in PHP

Beginner
⏱️ 8 min read
📚 Updated: Aug 2026
🎯 3 Code Examples
🚀 Live Preview
Dual Inner Loops

What You’ll Learn

The decreasing-increasing pattern prints 12345, 21234, 32123, 43212, 54321 — each row combines a descending prefix and ascending suffix. This tutorial covers dual inner-loop logic, live preview, worked PHP examples, edge cases, and O(n²) complexity.

Shape Rule

$i..2 + suffix

Row $i: print $j = $i..2, then $k = 1..($rows+1-$i).

Dual Inner Loops

Two per row

Decreasing loop first, increasing loop second — then row break.

Fixed Width

rows digits

Every row prints exactly $rows digits — pivot shifts each line.

Row 1 Special

Suffix only

When $i=1, decreasing loop skips — output is 12345.

Live Preview

3–12 rows

Pick a row count and draw the decreasing-increasing pattern instantly in the browser.

O(n²)

Complexity

Each row prints $rows digits — total work grows as n².

Introduction

A decreasing-increasing number pattern builds row $i with a descending prefix ($i..2) and an ascending suffix (1..($rows+1-$i)). Every row has exactly $rows digits.

In PHP you use nested loops: outer for ($i = 1; $i <= $rows; $i++), inner for ($j = $i; $j > 1; $j--) echo $j, inner for ($k = 1; $k <= $rows+1-$i; $k++) echo $k, then echo PHP_EOL after both inner loops.

Why it matters?

It is a dual inner-loop exercise that connects descending and ascending segments on each row.

Key Highlights

Outer loop $i

$i = 1..$rows picks each row number.

Two inner loops

$j = $i..2, $k = 1..suffix prints decreasing + increasing each row.

Dual Inner Loops

Decrease first, increase second — two inner loops per row.

Series Foundation

Follow Program 49 multiplication triangle; continue to Program 51 alternating triangle.

In short: outer $i=1..$rows, inner $j=$i..2 echo $j, inner $k=1..($rows+1-$i) echo $k, then echo PHP_EOL.

📝 Problem & Approach

Given $rows = 5, print five lines: 12345, 21234, 32123, 43212, 54321.

PHP
// $rows = 5 (conceptual output)
// 12345
// 21234
// 32123
// 43212
// 54321

Inputs & Outputs

ItemTypeDescription
$rowsintHow many lines to print (typically ≥ 1).
$i, $j, $kintRow index $i; decreasing loop $j and increasing loop $k.
Printed outputtextExactly $rows digits per row — fixed width.

Minimal workflow

Pseudocode
for i from 1 to rows:
    for j from i down to 2: print j
    for k from 1 to ($rows+1-$i): print k
    newline

Approach comparison

ApproachIdeaBest for
Dual inner loopsecho $j then echo $k in two inner loopsFixed row width — complementary loop bounds
fgets(STDIN) input(int) $input after is_numeric($input)User-chosen row count
Spaced digitsPrint space after each digit in both loopsEasier reading for larger rows — Example 3

⚡ Quick Reference

GoalPattern
Set rows$rows = 5;
Outer loopfor ($i = 1; $i <= $rows; $i++)
Decrease + increasefor ($j = $i; $j > 1; $j--) and for ($k = 1; $k <= $rows+1-$i; $k++)
Print digitecho $j; and echo $k;
Row breakecho PHP_EOL; after both inner loops
Program 49 contrastMultiplication triangle uses $i×$j products; this pattern uses dual inner loops per row

📋 Decrease Loop vs Increase Loop vs Combined

How outer row selection, decreasing prefix, increasing suffix, and row breaks work together.

Outer loop
for ($i = 1; $i <= $rows; $i++)

Picks row number $i — pattern height.

Decrease + increase
for ($j = $i; $j > 1; $j--)
for ($k = 1; $k <= $rows+1-$i; $k++)

Prints exactly $rows digits on row $i.

Digit values
echo $j; echo $k;

Decreasing digits first, then increasing digits — no multiplication.

Learning tip
trace $i=3

Dry-run row 3: decreasing 32 + increasing 12332123.

Context

When This Pattern Shows Up

Reach for this pattern when teaching dual inner loops, complementary bounds, and fixed-width row output.

  1. First lab exercise

    Classic follow-up after multiplication triangle patterns like Program 49.

  2. Nested-loop warm-up

    Outer/inner bound practice with an immediate visual check.

  3. Console I/O practice

    Combine loops with fgets(STDIN) for a flexible row count.

  4. Gateway to variants

    Compare with Program 49 (multiplication triangle), then continue to Program 51 (alternating triangle).

  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 complementary loop bounds, pivot shifting, and O(n²) thinking.

🔮 Live Preview

Choose a row count and draw the decreasing-increasing pattern in the browser.

Try 3, 5, or 8 rows (up to 12).

Live result
Press "Draw pattern".

Examples Gallery

Three complete PHP programs — fixed $rows = 5, fgets(STDIN) input, and a spaced-digit variant. Click View Output to reveal sample console results.

📚 Getting Started

Print five rows with two inner loops per row — decrease then increase.

Example 1 — Fixed $rows = 5

Hard-coded size — first inner loop prints $i..2, second prints 1..($rows+1-$i).

PHP
<?php
$rows = 5;

for ($i = 1; $i <= $rows; $i++) {
    for ($j = $i; $j > 1; $j--) {
        echo $j;
    }
    for ($k = 1; $k <= ($rows + 1 - $i); $k++) {
        echo $k;
    }
    echo PHP_EOL;
}

How It Works

When $i = 3, decreasing prints 32, increasing prints 123 — output 32123. Row 1 skips the decreasing loop and prints 12345.

📈 Practical Variant

Read $rows with fgets(STDIN) for flexible output size.

Example 2 — fgets(STDIN) Input

Same dual inner loops; row count comes from user input.

PHP
<?php
echo "Enter the number of rows: ";
$input = trim(fgets(STDIN));
if (!is_numeric($input)) {
    echo "Invalid input." . PHP_EOL;
    exit(1);
}
$rows = (int) $input;

for ($i = 1; $i <= $rows; $i++) {
    for ($j = $i; $j > 1; $j--) {
        echo $j;
    }
    for ($k = 1; $k <= ($rows + 1 - $i); $k++) {
        echo $k;
    }
    echo PHP_EOL;
}

How It Works

Identical loop structure to Example 1; only the row count is dynamic.

⚡ Formatting Variant

Add spaces between digits for easier reading.

Example 3 — Spaced Digits

Print a space after each digit in both inner loops.

PHP
<?php
$rows = 5;

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

How It Works

Same dual-loop logic; only the output format adds spaces between digits.

🧠 How the Algorithm Prints Rows

1

Set up

echo is built in; use fgets(STDIN) when reading input. Set $rows (e.g. 5).

Setup
2

Loop rows

for ($i = 1; $i <= $rows; $i++) — one iteration per output line.

Loop
3

Decrease then increase

for ($j = $i; $j > 1; $j--) echo $j, then for ($k = 1; $k <= $rows+1-$i; $k++) echo $k — building each row.

Inner
4

New line after row

echo PHP_EOL; after both inner loops moves to the next row.

Break
=

Decreasing-increasing number pattern complete

Total prints = digits — O(n²) time, O(1) extra memory.

🔎 Worked Walkthrough — row $i = 3

Trace row 3 with $rows = 5 to see how both inner loops build 32123.

PhaseLoopRow so far
Decrease$j=3 → echo 3; $j=2 → echo 232
Increase$k=1,2,3 → echo 1,2,332123

After both inner loops, echo PHP_EOL moves to the next row.

Use Cases

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

1. Teaching Dual Inner Loops

Clearest visual proof that outer and inner bounds interact.

Example: use fgets(STDIN) for dynamic row count — see Example 2.

2. Pivot Shift Link

Each row shifts the pivot between decreasing and increasing segments.

Example: compare row 3 (32123) — decreasing 32 plus increasing 123.

3. Console Formatting Drills

Practice echo vs PHP_EOL for multi-line vs single-line output.

Example: use echo $k . " " in both loops for spaced output — Example 3.

4. Spaced Output

Add spaces after each digit in both inner loops for readability.

Example: print $rows=5 with spaced output and compare readability.

5. Complexity Intuition

Fixed row width with shifting pivot makes O(n²) concrete for beginners.

Example: count digits for $rows=5 → 5 rows × 5 digits = 25 prints.

6. Input Validation Labs

Pair the pattern with fgets(STDIN) and positive-row checks.

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

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

Advantages

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

  1. 1. Instant Visual Feedback

    Fixed row width makes bound mistakes obvious — each line should have exactly $rows digits.

  2. 2. Minimal Concepts

    Only loops and console output — no arrays or math libraries.

  3. 3. Easy to Extend

    Change $rows, use fgets(STDIN), or add spaces between digits in both inner loops.

  4. 4. O(1) Extra Memory

    Streaming output needs no storage beyond loop counters.

Pro Tip: learn the dual inner loops first; then try fgets(STDIN) input and the spaced-digit variant in Example 3.

Usage Tips

Small habits that keep number-pattern code clean.

  1. 1. Name Variables Clearly

    Use $rows for height and $i/$j/$k for row and loop indices.

  2. 2. Prefer fgets(STDIN)

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

  3. 3. Row Break After Inner Loop

    Run decreasing loop first, then increasing loop, then echo PHP_EOL.

  4. 4. Use echo for Values

    Use echo $j and echo $k in the inner loops; one echo PHP_EOL per row after both loops.

  5. 5. Dry-Run One Small n

    Trace $rows = 5, $i = 3 on paper — expect 32123.

Pro Tip: if row lengths vary, check whether decreasing and increasing bounds are complementary.

Common Pitfalls

Mistakes that commonly break decreasing-increasing number patterns.

  1. 1. echo PHP_EOL Inside an Inner Loop

    Each digit lands on its own line — you get a column, not a fixed-width row.

    → Use echo $j and echo $k inside both inner loops; echo PHP_EOL only after they finish.

  2. 2. Wrong Complementary Bounds

    Mismatched decreasing/increasing bounds change row length — lines no longer have exactly $rows digits.

    → Keep for ($j = $i; $j > 1; $j--) and for ($k = 1; $k <= $rows+1-$i; $k++) for fixed width.

  3. 3. Forgetting the Row Break

    Omitting echo PHP_EOL after both inner loops glues all rows onto one line.

    → Always call echo PHP_EOL after both inner loops complete.

  4. 4. echo PHP_EOL Between the Two Inner Loops

    Breaking between decreasing and increasing loops splits one row across two lines.

    → Run both inner loops back-to-back, then call echo PHP_EOL once per row.

  5. 5. Unchecked fgets(STDIN) Input

    Letters or empty input fail without validation.

    → Call is_numeric($input) before casting to (int).

  6. 6. Hard-coding 10 Everywhere

    Using literal 10 in loop bounds instead of variable $rows breaks dynamic input.

    → Use one $rows variable for the outer loop bound.

Edge Cases

Check these inputs before calling the solution done.

$rows = 1

Single line

Output is one line: 1 (decreasing loop skips; suffix prints one digit).

$rows = 0

Empty pattern

Loop never runs — print nothing or show a message.

Negative

rows < 0

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

Large n

Many rows

Large row counts produce many digits — fine for labs; use smaller n for quick demos.

Bad input

Non-numeric fgets(STDIN) input

Unchecked fgets(STDIN) input leaves $rows unset — call is_numeric($input) first.

Compact

Single-line form

Add spaces after each digit in both inner loops — see Example 3.

🎯 Practice Problems

Try these variations to lock in the pattern.

1. Change rows

  • Try $rows = 3, 6, or 8
  • Verify each row has exactly $rows digits

2. Bound tweak

  • Try $j >= 1 instead of $j > 1
  • Observe how row shape changes

3. Reverse outer loop

  • Use for ($i = $rows; $i >= 1; $i--)
  • Print tallest pivot row first

4. Next in series

  • Continue with Program 51 alternating triangle
  • Connect to alternating row order patterns

Notes

  • Digit count. Total prints = $rows² (e.g. 25 digits for $rows=5).
  • echo stays on the line; PHP_EOL advances — mix them carefully.
  • Validate $rows > 0 for interactive programs; $rows = 1 prints one digit.
  • Decreasing uses $j > 1; increasing uses $k <= $rows+1-$i — bounds must complement for fixed width.

Quick Takeaway: outer $i=1..$rows, inner $j=$i..2 echo $j, inner $k=1..($rows+1-$i) echo $k, then echo PHP_EOL.

⏱️ Time and Space Complexity

ProgramTimeExtra space
Fixed $rows = 5 (Example 1)O(n²)O(1)
fgets(STDIN) input (Example 2)O(n²)O(1)
Spaced digits (Example 3)O(n²)O(1)
Wrap Up

🎉 Conclusion

The decreasing-increasing pattern combines dual inner loops per row — a natural step after multiplication triangle patterns. Master the fixed-$rows version first, then try fgets(STDIN) input and the spaced-digit variant in Example 3.

Practice the three examples above, then continue to Program 51 for the alternating ascending/descending triangle pattern.

Keep echo PHP_EOL after both inner loops — one row break per outer iteration.

💡 Best Practices

✅ Do

  • Explain outer $i, inner $j=$i..2, and inner $k=1..($rows+1-$i) before coding
  • Use echo $j and echo $k, then echo PHP_EOL after both inner loops
  • Validate $rows ≥ 1 for interactive programs
  • Check fgets(STDIN) return value before using $rows
  • State O(n²) time when asked about complexity

❌ Don’t

  • Put echo PHP_EOL between the two inner loops (breaks row shape)
  • Use inner bound $j > 1 for decreasing and $k <= $rows+1-$i for increasing
  • Hard-code 5 instead of variable $rows
  • Ignore bad console input in user-facing demos
  • Skip the $rows = 1 edge case

Key Takeaways

Knowledge Unlocked

Five things to remember about this decreasing-increasing number pattern

Print the pattern the beginner-friendly way.

5
Core concepts
02

Outer loop

$i = 1..$rows

Code
03

Dual loops

$j = $i..2, $k = 1..suffix

Logic
n 04

Fixed width

n digits/row

I/O
O 05

Complexity

O(n²)

Analysis

❓ Frequently Asked Questions

Row $i prints $j from $i down to 2, then $k from 1 up to ($rows+1-$i). Concatenating both parts creates lines like 21234 and 32123.
For $i=1, the decreasing loop ($j=$i..2) does not run, so only the increasing loop prints 1..$rows.
For $i=3, decreasing prints 32, increasing prints 123 ($rows+1-$i=3), giving 32123.
Yes. Use a variable $rows — the same two-loop structure works for any positive n.
Echo a space after each digit in both inner loops — see Example 3.
Yes. Each row prints exactly $rows digits — the pivot shifts each line.
O($n²) for n rows. Each row prints O(n) digits.
Use trim(fgets(STDIN)) and is_numeric($input) before casting to int.

Did you Know? 🔊

Each row combines a decreasing prefix ($i..2) and an increasing suffix (1..($rows+1-$i)). Row 1 prints only the suffix — 12345; row 3 gives 32123.

Continue to Program 51

Move on to the alternating ascending/descending triangle in the PHP number-pattern series.

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