Embercode
✕
C++ PatternsLesson 5 of 14

55 min read

Module assignment: pattern studio

Why this assignment exists

You have now seen the row and column method, number and letter patterns, pyramids, hollow shapes, diamonds and Pascal's triangle. Each lesson showed one pattern at a time, and each program stood on its own. A real job rarely looks like that. You are given a spec, a set of shapes, and a program that must handle all of them, including wrong input. This assignment asks you to put all of the module's skills into one program.

The program is called a pattern studio. It reads one line of input with a shape name and a size. It then prints the shape. You will use loops, formulas in i and j, a border test, a helper function, a long long value, and a chain of decisions to choose the shape. When you finish, the program will answer six shapes correctly, and it will say clearly when the name is wrong.

Take your time. Most of the marks come from careful checking of small cases, not from writing a long program.

What you will build

Your program reads two values from the Input box. The first value is a word, the name of the shape. The second value is a whole number n, the size. The words are separated by a space.

pyramid 3

Your program prints the shape named by the first word, sized by n. Every shape must follow the spacing rules in this document exactly. Print each row on its own line, with a newline after the last character of the row. Do not print trailing spaces at the end of a line.

The six shape names are these, spelled in lower case.

NameShape
squarea solid square of n rows and n columns
trianglea solid right triangle with row i holding i stars
pyramida centred full pyramid of n rows
diamonda diamond of 2 * n - 1 rows
hollowa hollow square with a star border and spaces inside
pascalPascal's triangle with n rows, centred, with each value separated by a space

If the name is none of these six, print the single line unknown shape. Check the name first, before you check n.

Input and output examples

The examples below show the exact output for each input. Run each one in the Input box and compare your output with the text. A correct solution must match these examples character for character, including the leading spaces.

Example 1: a triangle

Input:

triangle 3

Output:

*
**
***

Row i has i stars, and there are no spaces. This is the solid right triangle from the row and column lesson.

Example 2: a centred pyramid

Input:

pyramid 3

Output:

  *
 ***
*****

The spaces in row i are n - i, and the stars are 2 * i - 1. The bottom row has no leading spaces.

Example 3: a diamond

Input:

diamond 2

Output:

 *
***
 *

For n = 2 the diamond has 2 * 2 - 1 = 3 rows. The top half has rows 1 and 2, and the bottom half has row 1 only, because the widest row is printed once. This is the case where the join row matters most.

Example 4: a hollow square

Input:

hollow 2

Output:

**
**

For n = 2 every cell is on the border, so the whole square is stars. This is a good check that your border test does not miss a case.

Example 5: Pascal's triangle

Input:

pascal 4

Output:

   1
  1 1
 1 2 1
1 3 3 1

The top row has n - 1 spaces, and each row below has one fewer. Each value is one more than the value above it. The values come from the formula you saw in the diamond lesson, and they are separated by single spaces.

Example 6: an unknown shape

Input:

shape 3

Output:

unknown shape

The word shape is not one of the six names, so the program prints the message and nothing else.

Example 7: a size of zero

Input:

square 0

Output: nothing. The program prints no lines at all. It must not crash, and it must not print a single star. An empty output is the correct answer for n = 0.

Edge cases you must handle

An edge case is an input at the edge of the normal range. Test each shape with these sizes before you submit.

  • n = 1. Every shape prints something small. The square prints one star. The triangle prints one star. The pyramid prints one star. The diamond prints one star, because the top half is the only row. The hollow square prints one star. The Pascal triangle prints 1. Check each one by hand.
  • n = 2. This is the size where the diamond and hollow shapes can break. The diamond must print three rows, and the join row must appear once.
  • n = 0. Every shape prints nothing. The loops must not run. Check that the program still ends normally.
  • Unknown names. Words such as Square with a capital letter, or squares, are not the six names. They must print unknown shape. The comparison is case sensitive, which means Square and square are different. Do not change the name to lower case in your code.
  • Trailing spaces. The hollow square and the diamond have rows that end with a star, so no trailing spaces appear. The Pascal triangle must print single spaces between values and none after the last value. Run a check that the last character on each line is not a space.

Requirements checklist

Before you submit, go through this checklist. Each box must be ticked. A box you cannot tick tells you where to look.

  • The program reads a word and then an integer from one line of input.
  • square prints a solid square, and matches the spec for n = 1, n = 2 and n = 3.
  • triangle prints a solid right triangle, and matches Example 1.
  • pyramid prints a centred pyramid, and matches Example 2.
  • diamond prints 2 * n - 1 rows, and the join row is printed once. It matches Example 3.
  • hollow prints a border of stars with spaces inside, and matches Example 4.
  • pascal prints the values with the centring and spacing of Example 5, and uses long long for the values.
  • Any other name prints unknown shape, and nothing else.
  • n = 0 or a negative n prints nothing and does not crash.
  • No line ends with a space, in any shape.
  • At least one helper function is used for a row, and the diamond calls it for both halves.
  • The program has #include <iostream> and #include <string>, and it compiles with g++ -std=c++17 with no errors.

Grading rubric

Your mark depends on how many shapes are correct and how careful the code is. The three levels below describe what a 60 percent, an 80 percent and a 100 percent solution look like.

LevelWhat it doesWhat it misses
60 percentPrints square, triangle and pyramid correctly for n from 1 to 5. Compiles.diamond, hollow or pascal are missing or wrong. The unknown name is not handled.
80 percentAll six shapes match the examples for n from 1 to 5. Unknown names print the message.Some edge cases fail, such as n = 2 in the diamond, or n = 0. Trailing spaces appear in one or two shapes.
100 percentAll six shapes match the examples and the edge cases. No trailing spaces. The row logic lives in functions. The Pascal values use long long. Each function has a name that says what it prints.Nothing from the checklist. A 100 percent answer may still have a small style issue, but it is correct and easy to read.

A solution that is correct but has no helper function can still reach 100 percent, provided every other requirement is met. A solution that prints the right output by writing the shapes as fixed text, without loops, does not meet the spirit of the assignment, and it loses marks for the loop requirement.

How to test your work

Test in a fixed order, so you find a bug in the simplest case first.

  1. Test triangle with n = 1, then n = 3. Check that the rows grow by one star each.
  2. Test square with n = 2. The output should be a 2 by 2 block.
  3. Test pyramid with n = 2. The output should be * then ***.
  4. Test diamond with n = 1 and n = 2. Check the join row. With n = 2, the rows must be *, ***, *.
  5. Test hollow with n = 1, n = 2 and n = 4. Check the corners and the inside.
  6. Test pascal with n = 1, n = 4 and n = 6. Check that the last row of n = 6 is 1 5 10 10 5 1, with the spaces in front.
  7. Test the error cases: shape 3, Square 3, square 0 and square -2.

When a test fails, write down the expected output and the actual output side by side. Find the first row that differs. Then find the loop that prints that row. Most bugs are in one of three places: a formula for the spaces, a limit that is off by one, or a test that uses the wrong edge.

Step-by-step hints

Try the assignment yourself before you open these hints. Each hint unlocks one step of the work.

Hint 1: the program skeleton

Read the shape name into a string, then read n into an int. Use cin >> shape >> n;. Then use an if and else if chain that compares shape with each name. The last else prints unknown shape. Write one function for each shape, and call it from the chain. Start with square only, get it to pass the examples, and add the other shapes one at a time.

Hint 2: the first three shapes

square is two loops that each print * n times, with a newline after the inner loop. triangle is the same, except the inner limit is i. pyramid uses a row with n - i spaces and 2 * i - 1 stars. Write the pyramid row as a function pyramidRow(int n, int i), because the diamond will need it too.

Hint 3: the diamond

The diamond is the pyramid rows from i = 1 to n, and then the same rows from i = n - 1 down to 1. Do not start the bottom half at n. That prints the widest row twice. Two loops that each call pyramidRow are enough.

Hint 4: the hollow square

Visit every cell with two loops. Print * when i == 1, or i == n, or j == 1, or j == n. Print a space otherwise. Use || between the four tests, not &&.

Hint 5: Pascal's triangle

Use the row loop with n - r - 1 leading spaces. Keep a long long value that starts at 1 for each row. For each position k, print the value. Then update it with value = value * (r - k) / (k + 1);. Multiply before you divide. Print a space between values, but not after the last one.

Hint 6: the edge cases

If n is zero or negative, every loop stops before it prints. You do not need an extra check for most shapes. Check each shape with n = 0 anyway, because it is the first thing a tester tries. If the output for n = 0 is not empty, a loop start or limit is wrong.

Reference solution

Read the reference solution only after you have tried the assignment yourself. It is a complete program that compiles with g++ -std=c++17 and produces every example in this document. Use it to compare, not to copy. Your own code may have different function names and still be correct.

Reference solution
#include <iostream>
#include <string>
using namespace std;
 
void pyramidRow(int n, int i) {
    for (int s = 1; s <= n - i; s++) {
        cout << " ";
    }
    for (int j = 1; j <= 2 * i - 1; j++) {
        cout << "*";
    }
    cout << "\n";
}
 
void printSquare(int n) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cout << "*";
        }
        cout << "\n";
    }
}
 
void printTriangle(int n) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            cout << "*";
        }
        cout << "\n";
    }
}
 
void printPyramid(int n) {
    for (int i = 1; i <= n; i++) {
        pyramidRow(n, i);
    }
}
 
void printDiamond(int n) {
    for (int i = 1; i <= n; i++) {
        pyramidRow(n, i);
    }
    for (int i = n - 1; i >= 1; i--) {
        pyramidRow(n, i);
    }
}
 
void printHollow(int n) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (i == 1 || i == n || j == 1 || j == n) {
                cout << "*";
            } else {
                cout << " ";
            }
        }
        cout << "\n";
    }
}
 
void printPascal(int n) {
    for (int r = 0; r < n; r++) {
        for (int s = 0; s < n - r - 1; s++) {
            cout << " ";
        }
        long long value = 1;
        for (int k = 0; k <= r; k++) {
            cout << value;
            if (k < r) {
                cout << " ";
            }
            value = value * (r - k) / (k + 1);
        }
        cout << "\n";
    }
}
 
int main() {
    string shape;
    int n;
    cin >> shape >> n;
    if (shape == "square") {
        printSquare(n);
    } else if (shape == "triangle") {
        printTriangle(n);
    } else if (shape == "pyramid") {
        printPyramid(n);
    } else if (shape == "diamond") {
        printDiamond(n);
    } else if (shape == "hollow") {
        printHollow(n);
    } else if (shape == "pascal") {
        printPascal(n);
    } else {
        cout << "unknown shape\n";
    }
    return 0;
}

Why the reference is built this way

The reference uses one function per shape, so each shape can be checked on its own. The diamond calls pyramidRow twice, once for each half, so the spaces and stars are written in one place. The main function is only a chooser. It reads the input, then calls the function for the name it received.

The if chain checks the name before anything is printed, so an unknown name never produces a shape. The loops in each function are written so that a size of zero or below runs no loop at all, which gives the empty output the spec asks for.

The Pascal function keeps one long long value at a time, which is the formula method from the diamond lesson. It uses O(1) extra space and prints O(n squared) values in total.

Extension for a stronger submission

If you finish early and want more practice, add one of these to your program. Each one is optional, and none is required for full marks.

  • A seventh shape called hourglass, with the spacing of the hourglass lesson.
  • A check that prints bad size when the number is above 50, so the output cannot grow too big.
  • A hollow diamond shape, built from the same pyramidRow idea with a border test inside each row.

What you now know

  • A program that prints many shapes should give each shape its own function, and have main choose between them.
  • Test a shape with n = 0, n = 1 and n = 2 before you trust it, because those sizes break formulas.
  • The join row of a diamond must be printed once, which means the bottom half starts at n - 1.
  • Use || to test the border of a hollow shape, and a long long for Pascal values.
  • A correct program matches the examples character for character, including spaces, and prints no trailing spaces.
  • Read the wrong output row by row, find the first row that differs, and check the loop that prints it.
Practice this topic: coding problems for C++ Patterns →

Stuck? Ask the tutor

Ask about anything in this lesson. Answers are short and use simple words.

Sign in to ask the tutor.

← Diamonds and advanced patterns