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 3Your 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.
| Name | Shape |
|---|---|
square | a solid square of n rows and n columns |
triangle | a solid right triangle with row i holding i stars |
pyramid | a centred full pyramid of n rows |
diamond | a diamond of 2 * n - 1 rows |
hollow | a hollow square with a star border and spaces inside |
pascal | Pascal'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 3Output:
*
**
***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 3Output:
*
***
*****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 2Output:
*
***
*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 2Output:
**
**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 4Output:
1
1 1
1 2 1
1 3 3 1The 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 3Output:
unknown shapeThe 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 0Output: 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 prints1. 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
Squarewith a capital letter, orsquares, are not the six names. They must printunknown shape. The comparison is case sensitive, which meansSquareandsquareare 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.
-
squareprints a solid square, and matches the spec forn = 1,n = 2andn = 3. -
triangleprints a solid right triangle, and matches Example 1. -
pyramidprints a centred pyramid, and matches Example 2. -
diamondprints2 * n - 1rows, and the join row is printed once. It matches Example 3. -
hollowprints a border of stars with spaces inside, and matches Example 4. -
pascalprints the values with the centring and spacing of Example 5, and useslong longfor the values. - Any other name prints
unknown shape, and nothing else. -
n = 0or a negativenprints 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 withg++ -std=c++17with 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.
| Level | What it does | What it misses |
|---|---|---|
| 60 percent | Prints 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 percent | All 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 percent | All 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.
- Test
trianglewithn = 1, thenn = 3. Check that the rows grow by one star each. - Test
squarewithn = 2. The output should be a 2 by 2 block. - Test
pyramidwithn = 2. The output should be*then***. - Test
diamondwithn = 1andn = 2. Check the join row. Withn = 2, the rows must be*,***,*. - Test
hollowwithn = 1,n = 2andn = 4. Check the corners and the inside. - Test
pascalwithn = 1,n = 4andn = 6. Check that the last row ofn = 6is1 5 10 10 5 1, with the spaces in front. - Test the error cases:
shape 3,Square 3,square 0andsquare -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 sizewhen the number is above 50, so the output cannot grow too big. - A
hollow diamondshape, built from the samepyramidRowidea 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
mainchoose between them. - Test a shape with
n = 0,n = 1andn = 2before 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 along longfor 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.