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

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.
$i..2 + suffix
Row $i: print $j = $i..2, then $k = 1..($rows+1-$i).
Two per row
Decreasing loop first, increasing loop second — then row break.
rows digits
Every row prints exactly $rows digits — pivot shifts each line.
Suffix only
When $i=1, decreasing loop skips — output is 12345.
3–12 rows
Pick a row count and draw the decreasing-increasing pattern instantly in the browser.
Complexity
Each row prints $rows digits — total work grows as n².
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.
It is a dual inner-loop exercise that connects descending and ascending segments on each row.
$i = 1..$rows picks each row number.
$j = $i..2, $k = 1..suffix prints decreasing + increasing each row.
Decrease first, increase second — two inner loops per row.
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.
Given $rows = 5, print five lines: 12345, 21234, 32123, 43212, 54321.
// $rows = 5 (conceptual output)
// 12345
// 21234
// 32123
// 43212
// 54321 | Item | Type | Description |
|---|---|---|
$rows | int | How many lines to print (typically ≥ 1). |
$i, $j, $k | int | Row index $i; decreasing loop $j and increasing loop $k. |
| Printed output | text | Exactly $rows digits per row — fixed width. |
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 | Idea | Best for |
|---|---|---|
| Dual inner loops | echo $j then echo $k in two inner loops | Fixed row width — complementary loop bounds |
| fgets(STDIN) input | (int) $input after is_numeric($input) | User-chosen row count |
| Spaced digits | Print space after each digit in both loops | Easier reading for larger rows — Example 3 |
| Goal | Pattern |
|---|---|
| Set rows | $rows = 5; |
| Outer loop | for ($i = 1; $i <= $rows; $i++) |
| Decrease + increase | for ($j = $i; $j > 1; $j--) and for ($k = 1; $k <= $rows+1-$i; $k++) |
| Print digit | echo $j; and echo $k; |
| Row break | echo PHP_EOL; after both inner loops |
| Program 49 contrast | Multiplication triangle uses $i×$j products; this pattern uses dual inner loops per row |
How outer row selection, decreasing prefix, increasing suffix, and row breaks work together.
for ($i = 1; $i <= $rows; $i++)Picks row number $i — pattern height.
for ($j = $i; $j > 1; $j--)
for ($k = 1; $k <= $rows+1-$i; $k++)Prints exactly $rows digits on row $i.
echo $j; echo $k;Decreasing digits first, then increasing digits — no multiplication.
trace $i=3Dry-run row 3: decreasing 32 + increasing 123 → 32123.
Reach for this pattern when teaching dual inner loops, complementary bounds, and fixed-width row output.
Classic follow-up after multiplication triangle patterns like Program 49.
Outer/inner bound practice with an immediate visual check.
Combine loops with fgets(STDIN) for a flexible row count.
Compare with Program 49 (multiplication triangle), then continue to Program 51 (alternating triangle).
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.
Choose a row count and draw the decreasing-increasing pattern in the browser.
Three complete PHP programs — fixed $rows = 5, fgets(STDIN) input, and a spaced-digit variant. Click View Output to reveal sample console results.
Print five rows with two inner loops per row — decrease then increase.
$rows = 5Hard-coded size — first inner loop prints $i..2, second prints 1..($rows+1-$i).
<?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;
} When $i = 3, decreasing prints 32, increasing prints 123 — output 32123. Row 1 skips the decreasing loop and prints 12345.
Read $rows with fgets(STDIN) for flexible output size.
Same dual inner loops; row count comes from user input.
<?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;
} Identical loop structure to Example 1; only the row count is dynamic.
Add spaces between digits for easier reading.
Print a space after each digit in both inner loops.
<?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;
} Same dual-loop logic; only the output format adds spaces between digits.
echo is built in; use fgets(STDIN) when reading input. Set $rows (e.g. 5).
for ($i = 1; $i <= $rows; $i++) — one iteration per output line.
for ($j = $i; $j > 1; $j--) echo $j, then for ($k = 1; $k <= $rows+1-$i; $k++) echo $k — building each row.
echo PHP_EOL; after both inner loops moves to the next row.
Total prints = n² digits — O(n²) time, O(1) extra memory.
$i = 3Trace row 3 with $rows = 5 to see how both inner loops build 32123.
| Phase | Loop | Row so far |
|---|---|---|
| Decrease | $j=3 → echo 3; $j=2 → echo 2 | 32 |
| Increase | $k=1,2,3 → echo 1,2,3 | 32123 |
After both inner loops, echo PHP_EOL moves to the next row.
Where this tiny pattern (and its loop structure) shows up beyond the homework prompt.
Clearest visual proof that outer and inner bounds interact.
Example: use fgets(STDIN) for dynamic row count — see Example 2.
Each row shifts the pivot between decreasing and increasing segments.
Example: compare row 3 (32123) — decreasing 32 plus increasing 123.
Practice echo vs PHP_EOL for multi-line vs single-line output.
Example: use echo $k . " " in both loops for spaced output — Example 3.
Add spaces after each digit in both inner loops for readability.
Example: print $rows=5 with spaced output and compare readability.
Fixed row width with shifting pivot makes O(n²) concrete for beginners.
Example: count digits for $rows=5 → 5 rows × 5 digits = 25 prints.
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.
Why this pattern earns a permanent spot in beginner PHP courses.
Fixed row width makes bound mistakes obvious — each line should have exactly $rows digits.
Only loops and console output — no arrays or math libraries.
Change $rows, use fgets(STDIN), or add spaces between digits in both inner loops.
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.
Small habits that keep number-pattern code clean.
Use $rows for height and $i/$j/$k for row and loop indices.
fgets(STDIN)Avoid crashes when the user types letters instead of a number.
Run decreasing loop first, then increasing loop, then echo PHP_EOL.
Use echo $j and echo $k in the inner loops; one echo PHP_EOL per row after both loops.
Trace $rows = 5, $i = 3 on paper — expect 32123.
Pro Tip: if row lengths vary, check whether decreasing and increasing bounds are complementary.
Mistakes that commonly break decreasing-increasing number patterns.
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.
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.
Omitting echo PHP_EOL after both inner loops glues all rows onto one line.
→ Always call echo PHP_EOL after both inner loops complete.
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.
Letters or empty input fail without validation.
→ Call is_numeric($input) before casting to (int).
Using literal 10 in loop bounds instead of variable $rows breaks dynamic input.
→ Use one $rows variable for the outer loop bound.
Check these inputs before calling the solution done.
Output is one line: 1 (decreasing loop skips; suffix prints one digit).
Loop never runs — print nothing or show a message.
rows < 0Treat as invalid; re-prompt instead of silent empty output.
Large row counts produce many digits — fine for labs; use smaller n for quick demos.
Unchecked fgets(STDIN) input leaves $rows unset — call is_numeric($input) first.
Add spaces after each digit in both inner loops — see Example 3.
Try these variations to lock in the pattern.
$rows = 3, 6, or 8$rows digits$j >= 1 instead of $j > 1for ($i = $rows; $i >= 1; $i--)$rows² (e.g. 25 digits for $rows=5).echo stays on the line; PHP_EOL advances — mix them carefully.$rows > 0 for interactive programs; $rows = 1 prints one digit.$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.
| Program | Time | Extra 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) |
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.
$i, inner $j=$i..2, and inner $k=1..($rows+1-$i) before codingecho $j and echo $k, then echo PHP_EOL after both inner loops$rows ≥ 1 for interactive programsfgets(STDIN) return value before using $rowsecho PHP_EOL between the two inner loops (breaks row shape)$j > 1 for decreasing and $k <= $rows+1-$i for increasing$rows$rows = 1 edge casePrint the pattern the beginner-friendly way.
Each row prints $rows digits
$i = 1..$rows
Code$j = $i..2, $k = 1..suffix
Logicn digits/row
O(n²)
AnalysisEach 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.
Move on to the alternating ascending/descending triangle in the PHP number-pattern series.
12 people found this page helpful