Tuesday, October 27, 2026

Patterns using Arrays in C | Advanced Concepts

Patterns using Arrays in C | Advanced Concepts

Introduction

Pattern programming is an effective way to develop logical thinking and strengthen problem-solving skills in C. While basic pattern programs rely primarily on nested loops and conditional statements, more advanced patterns often require a deeper understanding of data structures, indexing, and memory organization.

One such advanced technique is pattern generation using arrays in C.

Arrays allow programmers to store, access, modify, and reuse data efficiently. When combined with nested loops, arrays can be used to construct a wide variety of patterns, including numeric sequences, symmetric arrangements, Pascal's Triangle, and patterns derived from previously calculated values.

In this article, we will explore how arrays can be used in pattern programming, understand the logic behind array-based patterns, and implement several examples in C.

By the end of this tutorial, you will understand not only how to print patterns using arrays, but also why arrays are useful when a pattern depends on stored values rather than simple row and column positions.

1. Understanding the Role of Arrays in Pattern Programming

An array is a collection of elements of the same data type stored in contiguous memory locations. Each element can be accessed using its index.

Consider the following array:

int arr[5] = {10, 20, 30, 40, 50};

The array contains five elements, indexed from 0 to 4.

IndexValue
010
120
230
340
450

In traditional pattern programming, a value is often calculated directly from the current row or column. With arrays, values can instead be stored and reused during pattern construction.

For example, arrays are particularly useful when:

  • A pattern depends on values generated in previous rows.

  • Each row contains a sequence that must be stored before printing.

  • A pattern requires reversing or rearranging elements.

  • Values must be accessed from different positions.

  • A numerical relationship exists between neighboring elements.

This makes arrays an important tool for solving patterns that cannot be conveniently generated using loops alone.

2. Pattern 1: Printing Array Elements in a Triangular Pattern

Let us begin with a simple example in which an array is used to print elements in a triangular arrangement.

Expected output

10
10 20
10 20 30
10 20 30 40
10 20 30 40 50

C program

#include <stdio.h>

int main(void)
{
    int arr[] = {10, 20, 30, 40, 50};
    int n = sizeof(arr) / sizeof(arr[0]);

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j <= i; j++)
        {
            printf("%d ", arr[j]);
        }

        printf("\n");
    }

    return 0;
}

Explanation

The outer loop controls the number of rows, while the inner loop determines how many array elements are printed in each row.

  • In the first row, only arr[0] is printed.

  • In the second row, arr[0] and arr[1] are printed.

  • In the third row, the first three elements are printed.

  • The process continues until all five elements have been included.

The condition j <= i ensures that each successive row contains one additional element.

Key concept: The array stores the values, while the nested loops determine their arrangement.

Time complexity: (O(n^2)), because the program prints a total of (n(n+1)/2) elements.

3. Pattern 2: Printing an Array in Reverse Triangular Order

Arrays also make it easy to generate patterns in which the number of printed elements decreases with each row.

Expected output

10 20 30 40 50
10 20 30 40
10 20 30
10 20
10

C program

#include <stdio.h>

int main(void)
{
    int arr[] = {10, 20, 30, 40, 50};
    int n = sizeof(arr) / sizeof(arr[0]);

    for (int i = n; i > 0; i--)
    {
        for (int j = 0; j < i; j++)
        {
            printf("%d ", arr[j]);
        }

        printf("\n");
    }

    return 0;
}

Explanation

Unlike the previous example, the outer loop starts at n and decreases until it reaches 1.

The inner loop prints the first i elements of the array. Consequently, each new row contains one fewer element than the preceding row.

This approach is useful when generating descending triangular arrangements or displaying progressively smaller portions of stored data.

Key concept: Changing the loop boundaries allows the same array to produce a different pattern without modifying its contents.

Time complexity: (O(n^2)).

4. Pattern 3: Printing a Palindromic Numeric Pattern Using an Array

A palindromic numeric pattern increases toward a central value and then decreases symmetrically.

For example, consider the following pattern:

1
1 2 1
1 2 3 2 1
1 2 3 4 3 2 1
1 2 3 4 5 4 3 2 1

An array can store the ascending sequence of numbers, which can then be reused in reverse order to complete each row.

C program

#include <stdio.h>

int main(void)
{
    int n = 5;
    int arr[5];

    for (int i = 0; i < n; i++)
    {
        arr[i] = i + 1;
    }

    for (int i = 1; i <= n; i++)
    {
        /* Print ascending sequence */
        for (int j = 0; j < i; j++)
        {
            printf("%d ", arr[j]);
        }

        /* Print descending sequence */
        for (int j = i - 2; j >= 0; j--)
        {
            printf("%d ", arr[j]);
        }

        printf("\n");
    }

    return 0;
}

Explanation

The first loop initializes the array with values from 1 to n.

For each row, two inner loops construct the pattern:

  1. The first loop prints the elements in ascending order, from arr[0] to arr[i - 1].

  2. The second loop prints the previously visited elements in reverse order, starting from arr[i - 2].

The descending loop starts at i - 2 because the central value has already been printed by the ascending loop. Printing it again would duplicate the center.

For example, when i = 4, the program prints:

  • Ascending: 1 2 3 4

  • Descending: 3 2 1

The resulting row is:

1 2 3 4 3 2 1

Key concept: An array can be traversed in both forward and reverse directions to create symmetric patterns.

Time complexity: (O(n^2)).

5. Pattern 4: Generating Floyd's Triangle Using an Array

Floyd's Triangle is a classic numeric pattern in which consecutive integers are arranged in increasing order across successive rows.

Expected output

1
2 3
4 5 6
7 8 9 10
11 12 13 14 15

Instead of printing each number immediately, we can store the sequence in an array and then use nested loops to arrange the stored values.

C program

#include <stdio.h>

int main(void)
{
    int n = 5;
    int arr[15];
    int value = 1;
    int index = 0;

    /* Store consecutive numbers */
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            arr[index++] = value++;
        }
    }

    /* Print the stored numbers as Floyd's Triangle */
    index = 0;

    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            printf("%d ", arr[index++]);
        }

        printf("\n");
    }

    return 0;
}

Explanation

Floyd's Triangle contains a total of

[
\frac{n(n+1)}{2}
]

elements for n rows. For five rows, the array must hold 15 integers.

The program uses two stages:

Stage 1: Populate the array

The nested loops generate consecutive integers and store them in the array using index.

Stage 2: Print the pattern

The index is reset to zero, and the elements are printed row by row. The first row contains one element, the second contains two, and so on.

Notice that the array size is fixed at 15, which is sufficient for five rows. If the row count is changed, the array capacity must be adjusted accordingly.

Key concept: Separating data generation from data presentation makes it easier to reuse the same stored sequence in different arrangements.

Time complexity: (O(n^2)).

6. Pattern 5: Generating Pascal's Triangle Using an Array

Pascal's Triangle is a more advanced example because its values are related to the elements in the preceding row.

Each row begins and ends with 1. Every interior element is calculated by adding the two elements immediately above it.

Expected output

        1
      1   1
    1   2   1
  1   3   3   1
1   4   6   4   1

Mathematical relationship

If a[i][j] represents an element in Pascal's Triangle, then each interior element follows the rule:

[
a[i][j] = a[i-1][j-1] + a[i-1][j]
]

The first and last elements of every row are 1.

This relationship makes Pascal's Triangle an ideal example of using a two-dimensional array to construct a pattern from previously calculated values.

C program

#include <stdio.h>

int main(void)
{
    int n = 5;
    int a[5][5] = {0};

    for (int i = 0; i < n; i++)
    {
        a[i][0] = 1;
        a[i][i] = 1;

        for (int j = 1; j < i; j++)
        {
            a[i][j] = a[i - 1][j - 1]
                    + a[i - 1][j];
        }
    }

    /* Print Pascal's Triangle */
    for (int i = 0; i < n; i++)
    {
        for (int s = 0; s < n - i - 1; s++)
        {
            printf("  ");
        }

        for (int j = 0; j <= i; j++)
        {
            printf("%4d", a[i][j]);
        }

        printf("\n");
    }

    return 0;
}

Explanation

The program declares a two-dimensional array with five rows and five columns.

For each row:

  1. The first element is assigned 1.

  2. The diagonal element at a[i][i] is assigned 1.

  3. Interior elements are calculated by adding two values from the preceding row.

  4. After the array has been constructed, nested loops print the triangle.

For example, the fourth row in zero-based indexing is calculated as follows:

  • a[3][0] = 1

  • a[3][1] = 1 + 2 = 3

  • a[3][2] = 2 + 1 = 3

  • a[3][3] = 1

The resulting row is 1 3 3 1.

The first loop inside the printing section adds leading spaces to improve the triangular appearance. The next loop prints the calculated elements.

Key concept: A two-dimensional array can store an entire pattern when each element depends on values from earlier rows.

Time complexity: (O(n^2)).

Space complexity: (O(n^2)), because the program stores the triangle in a two-dimensional array.

Note that Pascal's Triangle values grow rapidly. For larger row counts, an int may overflow; a larger integer type can extend the usable range but does not eliminate overflow indefinitely.

7. Pattern 6: Printing a Matrix in a Spiral Pattern Using Arrays

A spiral pattern demonstrates a different use of arrays. Instead of generating values in triangular rows, the program traverses a two-dimensional array in a defined order.

Consider the following matrix:

1   2   3   4
5   6   7   8
9  10  11  12
13 14  15  16

The spiral traversal produces:

1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10

C program

#include <stdio.h>

int main(void)
{
    int a[4][4] = {
        { 1,  2,  3,  4},
        { 5,  6,  7,  8},
        { 9, 10, 11, 12},
        {13, 14, 15, 16}
    };

    int top = 0, bottom = 3;
    int left = 0, right = 3;

    while (top <= bottom && left <= right)
    {
        /* Traverse from left to right */
        for (int j = left; j <= right; j++)
            printf("%d ", a[top][j]);
        top++;

        /* Traverse from top to bottom */
        for (int i = top; i <= bottom; i++)
            printf("%d ", a[i][right]);
        right--;

        /* Traverse from right to left */
        if (top <= bottom)
        {
            for (int j = right; j >= left; j--)
                printf("%d ", a[bottom][j]);
            bottom--;
        }

        /* Traverse from bottom to top */
        if (left <= right)
        {
            for (int i = bottom; i >= top; i--)
                printf("%d ", a[i][left]);
            left++;
        }
    }

    printf("\n");

    return 0;
}

Explanation

The algorithm maintains four boundaries:

  • top: the first row that has not yet been traversed.

  • bottom: the last row that has not yet been traversed.

  • left: the first unvisited column.

  • right: the last unvisited column.

During each iteration, the program traverses the top row, right column, bottom row, and left column. After each traversal, the corresponding boundary moves inward.

The conditions before the bottom-row and left-column traversals prevent elements from being visited twice when the remaining region becomes smaller.

Key concept: Array-based patterns can involve traversal strategies, not just the arrangement of printed numbers.

Time complexity: (O(r \times c)), where r is the number of rows and c is the number of columns. Every matrix element is visited at most once.

Space complexity: (O(1)) auxiliary space, excluding the matrix itself.

8. Important Techniques for Array-Based Pattern Programming

The examples above demonstrate several reusable techniques. Understanding these techniques is more important than memorizing individual programs.

8.1 Understand array indexing

C arrays use zero-based indexing. For an array of size n, the valid indices range from 0 to n - 1.

Accessing an element outside this range results in undefined behavior. Always ensure that loop conditions remain within the array's bounds.

8.2 Separate data generation from pattern printing

Whenever possible, divide the program into two logical stages:

  1. Generate or calculate the required values.

  2. Print those values in the desired arrangement.

This separation makes programs easier to understand, debug, and modify. It is particularly helpful for patterns such as Pascal's Triangle, where values depend on previously calculated elements.

8.3 Identify relationships between elements

Before implementing a pattern, determine how each element is calculated.

For example:

  • Consecutive-number patterns use an incrementing value.

  • Palindromic patterns reuse elements in reverse order.

  • Pascal's Triangle uses the sum of two neighboring elements from the previous row.

  • Spiral patterns use directional traversal and changing boundaries.

Identifying the relationship first helps you select the appropriate array structure and loop conditions.

8.4 Choose the correct array dimensions

Use a one-dimensional array when values form a sequence. Use a two-dimensional array when values represent rows and columns or when one row depends on another.

Also, ensure that the allocated capacity is sufficient for the largest input. For a triangular pattern with n rows, the number of elements may be (n(n+1)/2), so the required capacity increases quadratically.

8.5 Analyze time and space complexity

A pattern containing n rows may require (O(n^2)) time because the total number of printed elements can grow quadratically.

However, not every pattern requires an array. If values can be calculated directly and do not need to be stored or reused, ordinary nested loops may be simpler and more memory-efficient.

Arrays should be used when their storage and indexing capabilities provide a clear advantage.

9. Common Mistakes to Avoid

When implementing array-based patterns in C, pay attention to the following issues:

  • Incorrect index calculations: Using i instead of i - 1 or starting a reverse loop from the wrong index can produce incorrect output.

  • Out-of-bounds access: Never read or write beyond the allocated array dimensions.

  • Incorrect initialization: Initialize elements before using them in calculations, particularly in multidimensional arrays.

  • Duplicated central elements: In symmetric patterns, avoid printing the middle value twice.

  • Insufficient storage: Allocate enough space for the maximum number of elements required by the pattern.

  • Integer overflow: Some numerical patterns grow quickly and may exceed the range of the chosen integer type.

  • Unnecessary arrays: Do not introduce arrays when the pattern can be generated more clearly without storing intermediate values.

A useful debugging technique is to print the current row index, column index, and calculated value temporarily. This makes it easier to identify errors in indexing and loop boundaries.

10. Practice Problems

After understanding the examples, try implementing the following patterns independently.

Beginner level

  1. Print the elements of an array in a right-angled triangular pattern.

  2. Print a triangular pattern in which each row contains the first i odd numbers.

  3. Display an array in reverse triangular order.

Intermediate level

  1. Generate a palindromic numeric pattern using an array.

  2. Store the first n Fibonacci numbers in an array and display them in a triangular arrangement.

  3. Read a matrix from the user and print its elements in a zigzag row-wise pattern.

Advanced level

  1. Generate Pascal's Triangle using a two-dimensional array.

  2. Print a matrix in clockwise and anticlockwise spiral order.

  3. Generate a pattern by sorting each row of a matrix before printing it.

  4. Construct a diamond-shaped numeric pattern by storing and reusing values from its upper half.

For each problem, first determine the expected output, identify the relationship between elements, choose the appropriate array structure, and then design the loops.

Conclusion

Pattern programming using arrays in C extends the concepts of traditional nested-loop patterns by introducing data storage, indexed access, reverse traversal, and relationships between previously calculated values.

Simple triangular patterns demonstrate how arrays can control the arrangement of stored elements, while palindromic patterns illustrate reverse traversal. Floyd's Triangle shows how a stored sequence can be organized into rows, Pascal's Triangle introduces dependency-based calculations, and spiral traversal demonstrates how multidimensional arrays can be processed systematically.

The most important lesson is that effective pattern programming depends on understanding the relationship between data, indices, and traversal logic—not merely writing nested loops.

As you progress through more advanced C programming concepts, practice designing patterns that require you to store, transform, and reuse data. These exercises will strengthen your understanding of arrays and prepare you for more complex topics, including matrix algorithms, dynamic programming, and data structure manipulation.


For all Pattern Programs list click here: 

…till the next post, bye-bye & take care  


No comments:

Post a Comment