Shape Rule
Shrinking row width
Row 1 prints $rows numbers, row 2 prints $rows-1, down to one number on the last line.

The sequential decreasing-width number triangle prints consecutive integers in rows that get shorter each line. This tutorial covers the shape rule, the $k counter, nested loops, printf alignment, a live preview, algorithm steps, worked PHP examples, edge cases, and complexity.
Shrinking row width
Row 1 prints $rows numbers, row 2 prints $rows-1, down to one number on the last line.
Global sequence
$k = 1 tracks the next value; $k++ after each print keeps the sequence continuous.
Rows
for ($i = 1; $i <= $rows; $i++) walks from the widest row to the narrowest.
Decreasing count
for ($j = $rows; $j >= $i; $j--) runs fewer times as $i grows.
1–20 rows
Pick a row count and draw the sequential triangle instantly in the browser.
Complexity
Total values = n(n+1)/2; extra memory stays O(1).
A sequential decreasing-width number triangle prints consecutive integers while each row gets one value shorter. With $rows = 5, the output is 1 2 3 4 5, then 6 7 8 9, then 10 11 12, 13 14, and 15.
In PHP you solve it with two nested for loops and a shared $k counter: the outer loop picks the row, the inner loop prints $rows - $i + 1 formatted numbers with printf("%3d", $k++), then echo PHP_EOL moves to the next line.
It teaches counter-driven output and formatted columns — key skills before harder number-pattern variants.
Row $i prints $rows - $i + 1 consecutive values.
printf("%3d", $k++) keeps columns aligned.
printf("%3d", $k++) in the inner loop; echo PHP_EOL after.
Follow Program 37 palindrome rows; continue to Program 39 rotating numbers.
In short: for each row $i from 1 to $rows, print $rows - $i + 1 consecutive numbers with printf("%3d", $k++), then call echo PHP_EOL.
Given a positive integer $rows, print consecutive integers starting at 1 in a triangle where row $i contains exactly $rows - $i + 1 values.
// First 5 rows (conceptual shape)
// 1 2 3 4 5
// 6 7 8 9
// 10 11 12
// 13 14
// 15 | Item | Type | Description |
|---|---|---|
$rows | int | Number of triangle lines to print (typically ≥ 1). |
| Printed output | text | Left-aligned rows of consecutive integers; row $i has $rows - $i + 1 values. |
for i from rows down to 1:
if i is even:
for j from i down to 1: print j
else:
for j from 1 to i: print j
print newline | Approach | Idea | Best for |
|---|---|---|
| Nested loops + k counter | Outer rows + inner shrinking width + format | Learning and interviews |
| Custom start k | Change initial k instead of 1 | Variations and demos |
| Goal | Pattern |
|---|---|
| Walk each row | for ($i = 1; $i <= $rows; $i++) |
| Print shrinking count | for ($j = $rows; $j >= $i; $j--) printf("%3d", $k++); |
| End the row | echo PHP_EOL; |
| Wider columns | printf("%4d", $k++); for larger totals |
| Program 37 variant | Palindrome per row instead of global sequence |
Same triangle — different ways to emit aligned numbers.
no paddingDigits run together — columns misalign at 10+
%3dRight-aligns each value in a 3-character field
returns stringBuilds formatted text without printing directly
$k counterMaster the $k++ pattern before wider field widths
Reach for this pattern when teaching counters and formatted output inside nested loops.
Most PHP pattern series start here before pyramids and diamonds.
Outer/inner bound practice with an immediate visual check.
Combine loops with fgets(STDIN) for a flexible row count.
Compare Program 37 palindrome rows and Program 39 rotating numbers next.
This is a console teaching pattern — not how you build modern app screens.
Key benefit: one small program that locks in nested loops, output sequencing, and O(n²) thinking.
Choose a row count between 1 and 20 and draw the sequential decreasing-width triangle in the browser.
Three complete PHP programs — fixed row count, fgets(STDIN) input, and a custom starting value for $k. Click View Output to reveal sample console results.
Print five rows with nested loops, a $k counter, and formatted output.
$rows = 5Hard-coded height — ideal for first demos and screenshots.
<?php
$rows = 5;
$k = 1;
for ($i = 1; $i <= $rows; $i++) {
for ($j = $rows; $j >= $i; $j--) {
printf("%3d", $k++);
}
echo PHP_EOL;
} When $i = 1, the inner loop runs 5 times and prints 1 through 5. When $i = 2, it prints 6 through 9, and so on until the last row prints 15. echo PHP_EOL after the inner loop starts the next row.
Let the user choose the height at runtime.
Read the row count with fgets(STDIN).(int) trim(fgets(STDIN)) (check is_numeric() in real apps).
<?php
echo "Enter the number of rows: ";
$input = trim(fgets(STDIN));
if (!is_numeric($input)) return;
$rows = (int) $input;
if ($rows < 1) return;
$k = 1;
for ($i = 1; $i <= $rows; $i++) {
for ($j = $rows; $j >= $i; $j--) {
printf("%3d", $k++);
}
echo PHP_EOL;
} Same nested-loop core as Example 1; only the source of $rows changes. Non-numeric input throws invalid input with (int) trim(fgets(STDIN)) — check is_numeric() for safer labs.
Same shape with a different starting value for the sequence.
$k = 10Initialize $k with any starting value — the inner loop logic stays the same.
<?php
$rows = 5;
$k = 10;
for ($i = 1; $i <= $rows; $i++) {
for ($j = $rows; $j >= $i; $j--) {
printf("%3d", $k++);
}
echo PHP_EOL;
} Only the initial value of $k changes. The shrinking inner loop still prints $rows - $i + 1 values per row. Great for variations once you understand the default $k = 1 version.
Set $rows = 5; and use fgets(STDIN) when reading input. Set loop variables $i, $j, $k.
for ($i = 1; $i <= $rows; $i++) selects the current row from widest to narrowest.
for ($j = $rows; $j >= $i; $j--) prints $rows - $i + 1 numbers with printf("%3d", $k++).
echo PHP_EOL ends the row so the next outer iteration starts fresh.
Total digit prints: 1+2+…+n = n(n+1)/2 — O(n²) time, O(1) extra memory.
$rows = 4Trace each outer-loop value of $i, the inner-loop count, and the values printed via $k.
$i | Inner runs | $k range | Printed row |
|---|---|---|---|
1 | 4 | 1..4 | 1 2 3 4 |
2 | 3 | 5..7 | 5 6 7 |
3 | 2 | 8..9 | 8 9 |
4 | 1 | 10 | 10 |
Total value prints: 1 + 2 + 3 + 4 = 10 = 4×5/2.
Where this tiny pattern (and its loop structure) shows up beyond the homework prompt.
Clearest visual proof that outer and inner bounds interact.
Example: change $j <= $i and watch the shape change.
Foundation for inverted, pyramid, diamond, and hollow variants.
Example: change $k start to 100 for a shifted sequence.
Practice echo vs echo PHP_EOL without complex math.
Example: put echo PHP_EOL inside the inner loop by mistake.
Swap digits for letters, stars, or spaced output once the loop works.
Example: use %4d when values exceed two digits.
Triangular totals make O(n²) concrete for beginners.
Example: count printed digits for n = 10 still → 55.
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 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.
Wrong bounds show up immediately as a broken staircase.
Only loops and console output — no arrays or math libraries.
Invert, center, hollow, or change the fill character with small edits.
Streaming output needs no storage beyond loop counters.
Pro Tip: learn the $k-counter nested-loop version first; then try custom start values or wider format widths.
Small habits that keep number-pattern code clean.
Use $rows (or n) and keep $i/$j for row/column — or rename to row/col.
trim(fgets(STDIN))Avoid crashes when the user types letters instead of a number.
Only call echo PHP_EOL after the inner loop finishes the row.
Use %4d or wider when total values exceed 99.
Trace $rows = 3 on paper before coding larger demos.
Pro Tip: if the output is a vertical list of single digits per line, you almost certainly put echo PHP_EOL inside the inner loop.
Mistakes that commonly break sequential decreasing-width number patterns.
Each digit lands on its own line — you get a column, not a triangle.
→ Use printf("%3d", $k++) for values; echo PHP_EOL only after the inner loop.
Using $j <= $rows on every row prints a rectangle; resetting $k each row breaks the sequence.
→ Keep for ($j = $rows; $j >= $i; $j--) and one shared $k.
Omitting echo PHP_EOL glues every digit onto one endless line.
→ Always end the row after the inner loop.
Letters or empty input throw undefined rows.
→ Prefer trim(fgets(STDIN)) and re-prompt on failure.
Switching to $i = 0 without adjusting the inner bound prints an empty first row or wrong counts.
→ If 0-based, print $i with wrong inner bound (e.g. $j <= $i + 1).
Check these inputs before calling the solution done.
Output is just 1 on one line.
Outer loop never runs — print nothing or show a message.
rows < 0Treat as invalid; re-prompt instead of silent empty output.
Output grows as n²/2 characters — fine for labs, noisy for huge n.
Unchecked fgets(STDIN) leaves $rows unset — call is_numeric($input) first.
Initialize $k to any value — the sequence continues from there.
Try these variations to lock in the pattern.
4321234%4d or %5d for larger trianglesn(n+1)/2 — hence O(n²) time.print stays on the line; println advances — mix them carefully.$rows > 0 for interactive programs; $rows = 1 should print a single 1.Quick Takeaway: outer loop picks the row, inner loop prints shrinking count with $k++, then break the line.
| Program | Time | Extra space |
|---|---|---|
| Nested loops (Examples 1–2) | O(rows²) | O(1) |
| Custom start k (Example 3) | O(rows²) | O(1) |
The sequential decreasing-width number triangle combines nested loops with a shared $k counter and formatted output — a natural step after palindrome rows. Master the default $k = 1 version, then optionally change the start value or field width.
Practice the three examples above, then continue to Program 39 for the rotating number pattern.
Row $i prints $rows - $i + 1 consecutive values — keep printf("%3d", $k++) for digits and echo PHP_EOL for the break.
printf("%3d", $k++) for values and echo PHP_EOL after each rowrows ≥ 1 for interactive programsis_numeric($input) return value before using $rowsecho PHP_EOL inside the inner digit loop$rows = 1 edge casePrint the pattern the beginner-friendly way.
Row i prints rows-i+1 values
DefinitionControls each row
Code$k++ after each print
LogicAligns columns
I/OO(n²) time
AnalysisRow $i prints $rows - $i + 1 consecutive numbers via a shared $k counter. Total values for n rows is the triangular number n(n+1)/2 — 15 when $rows = 5.
Move on to the rotating number pattern in the PHP number-pattern series.
12 people found this page helpful