A star pyramid is a centered triangle pattern where each row i has (2*i - 1) stars and (n - i) leading spaces for alignment.
Loop from row 1 to n and compute the spaces and star count per row using the row index.
This is the most fundamental pattern problem — master it and all centered patterns become easy.
function pyramid(n) {
for (let i = 1; i <= n; i++) {
console.log(' '.repeat(n - i) + '*'.repeat(2 * i - 1));
}
}
// Input: n=4 => Output:
// *
// ***
// *****
// *******
// Input: n=3 => Output:
// *
// ***
// *****
Total stars in an n-row pyramid = n² (sum of first n odd numbers: 1+3+5+...+(2n-1)).
Key formula: spaces = n - row, stars = 2 * row - 1. Memorize this pair for all centered patterns.
An inverted pyramid starts with the widest row (2n-1 stars) at the top and narrows to a single star at the bottom.
Loop from n down to 1: for row i, print (n - i) leading spaces and (2*i - 1) stars.
This is the mirror image of the regular pyramid — both use the same formula but in opposite loop directions.
function invertedPyramid(n) {
for (let i = n; i >= 1; i--) {
console.log(' '.repeat(n - i) + '*'.repeat(2 * i - 1));
}
}
// Input: n=4 => Output:
// *******
// *****
// ***
// *
// Input: n=3 => Output:
// *****
// ***
// *
Key change: Loop direction reversed from 1 to n to n to 1 — that's the only difference from the regular pyramid.
Combining pyramid and inverted pyramid gives the diamond pattern — two patterns in one.
A diamond combines a top pyramid and a bottom inverted pyramid, sharing the single widest middle row.
Compute half = Math.ceil(n/2), print the top pyramid up to half rows, then the bottom from half-1 down to 1.
The second loop starts at half-1 to avoid repeating the center row — a key boundary detail.
function diamond(n) {
let half = Math.ceil(n / 2);
for (let i = 1; i <= half; i++)
console.log(' '.repeat(half - i) + '*'.repeat(2 * i - 1));
for (let i = half - 1; i >= 1; i--)
console.log(' '.repeat(half - i) + '*'.repeat(2 * i - 1));
}
// Input: n=5 => Output:
// *
// ***
// *****
// ***
// *
// Input: n=3 => Output:
// *
// ***
// *
Total rows = 2*half - 1. Math.ceil handles both even and odd n gracefully.
The diamond pattern is built on the pyramid pattern — understand one and the other follows naturally.
A number triangle prints the numbers 1 through i on row i — it's the numeric counterpart of the star right triangle.
Outer loop controls the row (1 to n); inner loop runs from 1 to i, building each row as a space-separated string.
Use row.trim() to remove the trailing space after the last number on each row.
function numberTriangle(n) {
for (let i = 1; i <= n; i++) {
let row = '';
for (let j = 1; j <= i; j++) row += j + ' ';
console.log(row.trim());
}
}
// Input: n=4 => Output:
// 1
// 1 2
// 1 2 3
// 1 2 3 4
// Input: n=2 => Output:
// 1
// 1 2
Variation: To print row number repeated (row 3 = "3 3 3"), replace j with i in the inner loop.
Total numbers = 1+2+...+n = n*(n+1)/2 (triangular numbers).
Floyd's Triangle fills rows with consecutive natural numbers: row 1 has 1 number, row 2 has 2, row 3 has 3, and so on.
The key: a counter num starts at 1 and increments continuously across ALL cells of ALL rows, independent of the loop variables.
The outer counter variable persisting across rows is a classic nested loop pattern worth memorizing.
function floyds(n) {
let num = 1;
for (let i = 1; i <= n; i++) {
let row = '';
for (let j = 1; j <= i; j++) row += (num++) + ' ';
console.log(row.trim());
}
}
// Input: n=4 => Output:
// 1
// 2 3
// 4 5 6
// 7 8 9 10
// Input: n=3 => Output:
// 1
// 2 3
// 4 5 6
Total numbers in n rows = n*(n+1)/2. Row k starts at number k*(k-1)/2 + 1.
Notice num is declared OUTSIDE both loops — this is what makes it persist and continue incrementing across all rows.
A hollow square prints stars only on its four borders — the first row, last row, first column, and last column — leaving the interior empty.
For each cell (i, j), print a star if it's on any border: i===0 || i===n-1 || j===0 || j===n-1. Otherwise print spaces.
This introduces the concept of boundary condition checking in 2D nested loops.
function hollowSquare(n) {
for (let i = 0; i < n; i++) {
let row = '';
for (let j = 0; j < n; j++)
row += (i === 0 || i === n-1 || j === 0 || j === n-1) ? '* ' : ' ';
console.log(row);
}
}
// Input: n=4 => Output:
// * * * *
// * *
// * *
// * * * *
// Input: n=3 => Output:
// * * *
// * *
// * * *
Hollow area = (n-2)² for n>2 (the interior not printed). For n=1 or n=2, the entire square is filled.
Apply the same boundary logic to triangles and diamonds for hollow variants of those patterns.
A right-angled triangle is the simplest star pattern: row i has exactly i stars, left-aligned with no leading spaces.
A single loop from 1 to n, printing '*'.repeat(i) for each row, is all you need.
This is usually the first pattern problem introduced since it requires only a single loop with no nesting.
function rightTriangle(n) {
for (let i = 1; i <= n; i++) {
console.log('*'.repeat(i));
}
}
// Input: n=5 => Output:
// *
// **
// ***
// ****
// *****
// Input: n=3 => Output:
// *
// **
// ***
Inverted version: change the loop to for (let i = n; i >= 1; i--) — just one character change reverses the triangle.
For a mirrored right triangle, pad each row: ' '.repeat(n-i) + '*'.repeat(i).
A zigzag pattern places a single star per column at varying row positions creating a diagonal wave effect across a 3-row grid.
For each column, compute col % 4. Stars appear in row 0 at mod 0, row 1 at mod 1, row 2 at mod 2, and row 0 again at mod 3 — creating the wave cycle.
This teaches modular arithmetic for generating periodic patterns without explicit wave functions.
function zigzag(n) {
for (let row = 0; row < 3; row++) {
let line = '';
for (let col = 0; col < n; col++) {
let mod = col % 4;
line += ((mod === row) || (mod === 2 && row === 0)) ? '* ' : ' ';
}
console.log(line);
}
}
// Input: n=9 => Output:
// * * *
// * * * *
// * *
Period = 4 columns per complete wave cycle. The pattern repeats every 4 columns across the output.
Zigzag patterns appear in the classic ZigZag Conversion LeetCode problem used in string encoding algorithms.
In this pattern, row 0 prints 'A', row 1 prints 'A B', row 2 prints 'A B C', and so on — increasing by one letter each row.
Use String.fromCharCode(65 + j) to convert a zero-based index j into the corresponding uppercase letter (A=65 in ASCII).
This combines nested loop structure with ASCII character arithmetic — a foundational technique for letter-based patterns.
function charPattern(n) {
for (let i = 0; i < n; i++) {
let row = '';
for (let j = 0; j <= i; j++)
row += String.fromCharCode(65 + j) + ' ';
console.log(row.trim());
}
}
// Input: n=4 => Output:
// A
// A B
// A B C
// A B C D
// Input: n=3 => Output:
// A
// A B
// A B C
ASCII values: A=65, Z=90. Lowercase letters start at 97. Adjust the base to print lowercase.
Variation: Print the current row's own letter repeated row-times: row 3 = 'C C C' by using i as both the character index and loop count.
Pascal's Triangle is a triangular array where each element equals the sum of the two elements directly above it on the previous row.
Build it using a 2D array: every row starts and ends with 1, and each inner element is tri[i-1][j-1] + tri[i-1][j].
This is foundational in combinatorics — row k contains binomial coefficients C(k,0), C(k,1), ..., C(k,k).
function pascals(n) {
let tri = [];
for (let i = 0; i < n; i++) {
tri[i] = [1];
for (let j = 1; j < i; j++)
tri[i][j] = tri[i-1][j-1] + tri[i-1][j];
tri[i][i] = 1;
console.log(' '.repeat(n - i) + tri[i].join(' '));
}
}
// Input: n=5 => Output:
// 1
// 1 1
// 1 2 1
// 1 3 3 1
// 1 4 6 4 1
Row k sum = 2k — each row's sum is double the previous row.
Pascal's Triangle encodes Fibonacci numbers (diagonal sums), powers of 2 (row sums), and powers of 11 (row concatenation).
A butterfly pattern is symmetric: stars appear on both left and right sides of each row, with spaces in the middle creating a wing effect.
For the top half (rows 1 to n): print i stars, then 2*(n-i) spaces, then i stars. The bottom half mirrors the top upward.
This combines left star count, middle space count, and right star count in each row.
function butterfly(n) {
for (let i = 1; i <= n; i++) {
let s = '*'.repeat(i), sp = ' '.repeat(2 * (n - i));
console.log(s + sp + s);
}
for (let i = n - 1; i >= 1; i--) {
let s = '*'.repeat(i), sp = ' '.repeat(2 * (n - i));
console.log(s + sp + s);
}
}
// Input: n=4 => Output:
// * *
// ** **
// *** ***
// ********
// *** ***
// ** **
// * *
Total rows = 2n - 1. The middle row has 2n stars (fully filled with no spaces).
Middle row spaces = 0 when i = n — that's when both halves touch and form the widest row.
A sandglass starts with the widest row at the top (2n-1 stars), narrows to a single star in the middle, then expands back to the widest row at the bottom.
First half: loop from n down to 1 with increasing leading spaces and decreasing stars. Second half: loop from 2 back up to n with decreasing spaces and increasing stars.
The middle single star is printed once when the first loop completes at i=1.
function sandglass(n) {
for (let i = n; i >= 1; i--) {
console.log(' '.repeat(n - i) + '*'.repeat(2 * i - 1));
}
for (let i = 2; i <= n; i++) {
console.log(' '.repeat(n - i) + '*'.repeat(2 * i - 1));
}
}
// Input: n=4 => Output:
// *******
// *****
// ***
// *
// ***
// *****
// *******
Total rows = 2n - 1. Second loop starts at i=2 to avoid repeating the middle single-star row.
Think of it as a diamond rotated 90° — both share the same two-loop structure.
A hollow triangle prints stars only on the three edges: the first column (left side), the hypotenuse (right side where j=i), and the base (last row).
For the first and last rows, print all stars. For middle rows, print a star at the start and end only, filling the interior with spaces.
This teaches conditional output in nested loops — printing stars only at boundary positions.
function hollowTriangle(n) {
for (let i = 1; i <= n; i++) {
if (i === 1) {
console.log('*');
} else if (i === n) {
console.log('*'.repeat(n));
} else {
console.log('*' + ' '.repeat(i - 2) + '*');
}
}
}
// Input: n=5 => Output:
// *
// * *
// * *
// * *
// *****
Middle rows have exactly 2 stars with (i-2) spaces between them. No padding needed — left-aligned.
For a centered hollow triangle, add ' '.repeat(n-i) at the start of each line.
A right-aligned staircase places row i's stars flush against the right margin, with (n-i) spaces on the left.
This is the opposite of the left-aligned right triangle — the staircase "climbs" from bottom-left to top-right.
Use ' '.repeat(n - i) + '#'.repeat(i) for each row.
function staircase(n) {
for (let i = 1; i <= n; i++) {
console.log(' '.repeat(n - i) + '#'.repeat(i));
}
}
// Input: n=4 => Output:
// #
// ##
// ###
// ####
// Input: n=5 => Output:
// #
// ##
// ###
// ####
// #####
Row i has exactly (n-i) leading spaces and i hash symbols.
This is a classic HackerRank warm-up that tests understanding of right-justification with string padding.
An X pattern places stars on the main diagonal (where row index = column index) and the anti-diagonal (where row + col = n - 1).
For each cell (i, j), print a star if i === j (main diagonal) OR i + j === n - 1 (anti-diagonal); otherwise print a space.
This pattern teaches diagonal index arithmetic in 2D grid traversal.
function crossPattern(n) {
for (let i = 0; i < n; i++) {
let row = '';
for (let j = 0; j < n; j++) {
row += (i === j || i + j === n - 1) ? '* ' : ' ';
}
console.log(row);
}
}
// Input: n=5 => Output:
// * *
// * *
// *
// * *
// * *
Main diagonal: i === j. Anti-diagonal: i + j === n - 1. Center cell satisfies both for odd n.
For even n there is no single center cell — the two diagonals pass through 2n-1 distinct cells total.
A multiplication table is an n×n grid where cell (i, j) holds the product of row i and column j.
Use two nested loops — outer for rows 1 to n, inner for columns 1 to n — and format each product for alignment using padStart.
Understanding multiplication table layout is a precursor to matrix operations in linear algebra and programming.
function multiTable(n) {
for (let i = 1; i <= n; i++) {
let row = '';
for (let j = 1; j <= n; j++) {
row += String(i * j).padStart(4);
}
console.log(row);
}
}
// Input: n=3 => Output:
// 1 2 3
// 2 4 6
// 3 6 9
// Input: n=4 => Output (row 4): 4 8 12 16
padStart(4) reserves 4 characters per number, keeping all columns aligned regardless of digit count.
For n=9, the max value is 81 (2 digits), so padStart(3) would be sufficient.
A wave pattern places exactly one star per column at a varying row height, creating a smooth up-down cycling effect across the grid.
For each column, compute its height position using col % (2 * (rows - 1)). If the phase is less than rows, use it directly; otherwise use the mirrored value.
This combines modular arithmetic with grid row-by-row printing.
function wave(cols, rows) {
let h = [];
for (let c = 0; c < cols; c++) {
let p = c % (2 * (rows - 1));
h.push(p < rows ? p : 2 * (rows - 1) - p);
}
for (let r = 0; r < rows; r++) {
let line = '';
for (let c = 0; c < cols; c++)
line += h[c] === r ? '* ' : ' ';
console.log(line);
}
}
// Input: cols=10, rows=3 => Output:
// * * *
// * * * *
// * * * *
Period = 2*(rows-1) columns per complete up-down cycle.
Wave patterns appear in signal processing visualization and zigzag string encoding problems in LeetCode.
A checkerboard alternates between two characters based on the parity of (row + column): even positions get one symbol, odd positions get another.
For each cell (i, j): if (i + j) is even print '#', otherwise print '.'.
This pattern is used as a base for many chess/board game visualizations.
function checkerboard(n) {
for (let i = 0; i < n; i++) {
let row = '';
for (let j = 0; j < n; j++) {
row += (i + j) % 2 === 0 ? '# ' : '. ';
}
console.log(row);
}
}
// Input: n=4 => Output:
// # . # .
// . # . #
// # . # .
// . # . #
// Input: n=3 => Output:
// # . #
// . # .
// # . #
Parity rule: (i + j) % 2 === 0 → one character; otherwise → the other.
A checkerboard has a symmetry property: rotating 90° produces a shifted pattern of the same type.
A number border fills only the boundary of an n×n matrix with sequential numbers in clockwise order, leaving the interior empty.
Traverse: top row L→R, right column T→B (skip corner), bottom row R→L (skip corner), left column B→T (skip corners).
This is the foundation of the spiral matrix problem in competitive programming and interviews.
function numberBorder(n) {
let mat = Array.from({length: n}, () => Array(n).fill(' '));
let num = 1;
for (let j = 0; j < n; j++) mat[0][j] = num++;
for (let i = 1; i < n; i++) mat[i][n-1] = num++;
for (let j = n-2; j >= 0; j--) mat[n-1][j] = num++;
for (let i = n-2; i > 0; i--) mat[i][0] = num++;
mat.forEach(row => console.log(row.map(v => String(v).padStart(3)).join('')));
}
// Input: n=4 => Output:
// 1 2 3 4
// 12 5
// 11 6
// 10 9 8 7
Border count for n×n = 4*(n-1). The perimeter formula gives the total sequential numbers to place.
For a full spiral (multiple rings), repeat the same process recursively for shrinking inner matrices.
An inverted right triangle starts with n stars on the first row and decreases by one star per row until row n has just 1 star.
Simply loop from n down to 1, printing '*'.repeat(i) stars per row — no leading spaces needed.
This is the complement of the standard right triangle and reinforces downward-counting loop patterns.
function invertedRight(n) {
for (let i = n; i >= 1; i--) {
console.log('*'.repeat(i));
}
}
// Input: n=5 => Output:
// *****
// ****
// ***
// **
// *
// Input: n=3 => Output:
// ***
// **
// *
Total stars = 1 + 2 + ... + n = n*(n+1)/2 (triangular number).
Combine with the right triangle to create a bowtie/arrow pattern pointing left when viewed sideways.
In this pattern, row 1 has 'A' once, row 2 has 'B' twice, row 3 has 'C' three times, and so on up to n rows.
For row i (1-indexed): the letter is String.fromCharCode(64 + i) and it's repeated i times.
This combines ASCII arithmetic with the number-of-repetitions equaling the row index.
function alphaRepeat(n) {
for (let i = 1; i <= n; i++) {
let ch = String.fromCharCode(64 + i);
console.log((ch + ' ').repeat(i).trim());
}
}
// Input: n=4 => Output:
// A
// B B
// C C C
// D D D D
// Input: n=5 => Output (row 5): E E E E E
ASCII mapping: A=65, so charCodeAt(64 + i) gives A for i=1, B for i=2, etc.
Variation: print the same letter across all rows but repeat it row-number times: useful for histogram-style patterns.
In this reversed number triangle, row i shows the numbers from i down to 1 instead of 1 up to i.
For each row i, run an inner loop from i down to 1, appending each number to the row string.
This is the mirror of the standard number triangle and tests downward inner loop logic.
function mirrorNumberTri(n) {
for (let i = 1; i <= n; i++) {
let row = '';
for (let j = i; j >= 1; j--) row += j + ' ';
console.log(row.trim());
}
}
// Input: n=4 => Output:
// 1
// 2 1
// 3 2 1
// 4 3 2 1
// Input: n=5 => Output (row 5): 5 4 3 2 1
Inner loop direction: starts at i and decrements to 1 — the reverse of the standard triangle.
Combine this with the standard triangle to create a symmetrical diamond number pattern.
In this pattern, row i shows i stars increasing from the left AND a mirrored matching count from the right, with stars expanding and contracting.
Top half: rows 1 to n, increasing stars. Bottom half: rows n-1 down to 1, decreasing stars. Unlike the butterfly, no spaces in the middle.
This creates an arrowhead or chevron-like pattern pointing to the right when rotated.
function growShrink(n) {
for (let i = 1; i <= n; i++) console.log('*'.repeat(i));
for (let i = n - 1; i >= 1; i--) console.log('*'.repeat(i));
}
// Input: n=4 => Output:
// *
// **
// ***
// ****
// ***
// **
// *
Total rows = 2n - 1. The peak row with n stars appears exactly once.
When printed sideways this is an arrow pointing right — a common pattern interview question.
A spiral matrix fills an n×n grid with sequential numbers 1 through n×n by traversing the boundary layers clockwise inward.
Use four boundaries (top, bottom, left, right) that shrink after each pass: fill top row L→R, right column T→B, bottom row R→L, left column B→T, then move all boundaries inward.
This is an interview favorite that tests boundary management and directional traversal.
function spiralMatrix(n) {
let mat = Array.from({length: n}, () => Array(n).fill(0));
let top = 0, bottom = n-1, left = 0, right = n-1, num = 1;
while (top <= bottom && left <= right) {
for (let i = left; i <= right; i++) mat[top][i] = num++;
top++;
for (let i = top; i <= bottom; i++) mat[i][right] = num++;
right--;
if (top <= bottom) for (let i = right; i >= left; i--) mat[bottom][i] = num++;
bottom--;
if (left <= right) for (let i = bottom; i >= top; i--) mat[i][left] = num++;
left++;
}
mat.forEach(row => console.log(row.map(v => String(v).padStart(3)).join('')));
}
// Input: n=3 => Output:
// 1 2 3
// 8 9 4
// 7 6 5
Total numbers = n×n. The algorithm fills exactly 4*(n-1) cells in each outer ring.
Spiral matrix traversal is a classic algorithm that appears in Google, Amazon, and Microsoft interviews.
A heart pattern can be approximated in ASCII using rows of stars: a wide top with two bumps, narrowing to a point at the bottom.
The top portion has two arcs (each about n/2 wide) separated by a gap, then rows expand and finally converge to a point in the lower half.
While the exact shape varies by implementation, this pattern tests complex conditional star placement.
function heart(n) {
// Top half: two bumps
for (let i = n / 4; i <= n / 2; i++) {
let row = ' '.repeat(n / 2 - i);
row += '*'.repeat(2 * i - 1) + ' ' + '*'.repeat(2 * i - 1);
console.log(row);
}
// Bottom half: pyramid narrowing to point
for (let i = n; i >= 1; i--) {
console.log(' '.repeat(n - i) + '*'.repeat(2 * i - 1));
}
}
// Input: n=8 => Output (approximate heart):
// *** ***
// ***** *****
// ******* *******
// ***************
// *************
// ***********
// *********
// *****
// ***
// *
The exact appearance depends on terminal width and character aspect ratio. Adjust spacing for best visual result.
Heart patterns are popular in creative coding challenges and demonstrate mastery of multi-region conditional patterns.