Logical Reasoning

Pattern Printing

25 Questions

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.