What you will build
In this assignment you write one program called a pattern printer. It reads two things from the Input box: the name of a shape, and a size n. It prints the shape row by row, and then prints how many stars it used. If the name is not one it knows, or the size is out of range, it prints a short message and stops.
The assignment uses every skill from the module. You will use nested loops for the rows and the cells, range for the counts, string multiplication for the stars and spaces, border tests for the hollow shape, and a function for each shape. You will also check your input before you print anything, which is what separates a program from a set of loose loops.
Read the whole assignment before you write code. Then write a small version first, with one shape, and get it right. Add the other shapes one at a time, and run the program after each addition. Programs written this way are much easier to debug than programs written all at once, and a reviewer will see a steady build in your work.
The specification
Your program reads two values from the Input box. The first is a word, which is the pattern name. The second is a whole number n. The two values can be on one line separated by a space, or on two lines. Your program must handle both. The method split() on the whole input skips spaces and line breaks, so reading the input with sys.stdin.read().split() handles both layouts.
The pattern name must be one of seven words. Each word names a shape, and each shape has a fixed rule for its rows.
squareis a solid square ofnrows andncolumns of stars.rightis a right triangle, where rowihasistars.invertedis an inverted right triangle, where rowihasn - i + 1stars.pyramidis a centred pyramid, where rowihasn - ispaces and2 * i - 1stars.diamondis a pyramid followed by an inverted pyramid. The widest row appears once, so there are2 * n - 1rows in total.hollowis a hollow square ofnrows andncolumns. A cell is a star only when it lies on the border, and a space otherwise.butterflyhas2 * n - 1rows. Rowi, forifrom 1 ton, hasistars, then2 * (n - i)spaces, thenistars. The rows then repeat in reverse fromiequal ton - 1down to 1.
The size n must be a whole number from 1 to 20, including both ends.
Your program checks the two inputs in a fixed order. First it checks the name. If the name is not in the list, it prints the single line unknown pattern and stops. Second, if the name is valid but n is outside 1 to 20, it prints the single line n must be from 1 to 20 and stops. Only when both are valid does it print the shape.
When the shape is valid, your program prints each row on its own line. No line may have trailing spaces, which means that the last character on every row must be a star. After the last row, it prints one more line: the text stars: followed by the total number of star characters printed. For example, stars: 9 means nine stars appeared in the picture. Count the stars in the rows, not the spaces, and do not count the stars in the total line.
Your program must not print anything else. There are no prompts, no headings and no extra blank lines. An output checker compares your text with the expected text exactly, so a single extra line can make a correct solution fail.
Worked examples
These six runs are the examples the statement shows. Each one was produced by a reference program, and your output must match it exactly, character for character.
Input pyramid 3 gives:
*
***
*****
stars: 9The three rows have 1, 3 and 5 stars, which total 9. The first row has two spaces, which is n - i for i equal to 1 with n equal to 3.
Input butterfly 3 gives:
* *
** **
******
** **
* *
stars: 18The widest row has six stars, with no gap. The outer rows have one star on each side and a gap of four spaces. The stars total 2 plus 4 plus 6 plus 4 plus 2, which is 18.
Input hollow 5 gives:
*****
* *
* *
* *
*****
stars: 16A five by five border has 16 cells, and the inside has 9 cells that print spaces.
Input diamond 3 gives:
*
***
*****
***
*
stars: 13The diamond has five rows. The total of 13 is 1 plus 3 plus 5 plus 3 plus 1.
Input wings 4 gives:
unknown patternThe name wings is not in the list, so the program stops after one message, and it does not check n.
Input square 21 gives:
n must be from 1 to 20The name is valid, but 21 is above the limit, so the program prints the range message and stops.
Notice what the examples show about the order of checks. The wings 4 run prints the name message even though n is valid, and the square 21 run prints the range message even though the name is valid. Your program must follow the same order, or it will print the wrong message for an input that breaks both rules.
Requirements checklist
Use this list as your guide, and tick each item when you have tested it. A checklist keeps the work honest, because you can see what is left.
- The program reads a word and then a whole number from the Input box.
- An unknown name prints
unknown patternand nothing else. - A size outside 1 to 20 prints
n must be from 1 to 20and nothing else. - The name is checked before the size, so
wings 21prints the name message. -
squareprints the solid square, withnrows ofnstars. -
rightprints the right triangle, with rowihavingistars. -
invertedprints the inverted triangle, with rowihavingn - i + 1stars. -
pyramidprints the centred pyramid, with the spaces and stars from the specification. -
diamondprints the pyramid and then the inverted rows, with the widest row only once. -
hollowprints the border test for each cell, so only the outline is starred. -
butterflyprints the two wings with the gap formula2 * (n - i). - No row has trailing spaces.
- The last line is
stars:followed by the total number of star characters. - The program works for
nequal to 1, which every shape must handle. - The program works for
nequal to 20, and thebutterflyrow has the right width. - The code uses a function for each shape, or one function that builds the rows, and the main part only reads, checks and prints.
- Each formula has a short comment that says what it counts.
Test plan
Before you submit, run every one of the following inputs and compare the output with the rule. You do not need to memorise the expected pictures. Check the first row, the last row, the number of rows and the total of the star line.
square 1,right 1,inverted 1,pyramid 1,diamond 1,hollow 1andbutterfly 1. Each of the first six prints a single star. The butterfly prints one row,**, because its two wings meet with no gap. Count the stars and check the total.square 4,right 4,inverted 4andpyramid 4. Compare each with a table you drew on paper first.hollow 2. The whole picture is a solid two by two block, because every cell is on the border.wings 4,square 0,square 21andpyramid -3. The first two must print the expected message, andsquare 0andpyramid -3must print the range message.butterfly 20. The widest row has 40 stars and no gap. The rows from 1 to 20 have2 * istars each, which adds to 420. The rows from 19 down to 1 add to 380. The total is 800, and your program must printstars: 800after the picture.
The last item tests the largest allowed size. A program can pass small cases and still break at the edges, so do not skip it.
Rubric
Your work is graded against three levels. Each level describes what a complete solution at that level does. The levels build on each other, so a 100% solution also meets every 80% and 60% item.
60%: the basics work. The program reads the name and the size. It prints square, right and inverted correctly, with the right number of rows and stars. It prints the two messages for an unknown name and for a size out of range. Its output has no trailing spaces, and its last line is the star total. A solution at this level may use one long function with a separate loop for each shape, and it may not check the star total correctly for every shape.
80%: all the required shapes and the checks. The program also prints pyramid, diamond and hollow correctly, with the right spaces and borders. The check order is correct, so wings 21 prints the name message. The star total is correct for every shape, including the diamond, where the middle row is counted once. The code has at least one helper function, such as one that builds the spaces and stars for a row. A solution at this level passes the worked examples and most of the test plan.
100%: complete, tested and clear. The program also prints butterfly correctly, and it passes every item in the test plan, including n equal to 1 and n equal to 20. The code builds each shape as a list of lines and then prints them, so the counting of stars and the printing are in one place. Each formula has a comment. There are no loops that do the same job twice, and no print inside a loop that should print once per row. A solution at this level would read well to a reviewer who had not seen the module, and it would stay correct if a new shape were added later.
Some points lie outside these levels. A solution that prints the right output but hides it inside a very long function is at 80% at best, because it is hard to test. A solution that hard-codes the answer for each example is 0%, whatever its output looks like, because it does not follow the rule.
Hints
Use these hints in order. Try each one before you move on to the next. Each hint is short, and the reference solution is at the end of the lesson.
Hint 1: start with the reading and the checks
Read the whole input with data = sys.stdin.read().split(), after import sys at the top of the file. Then data[0] is the name and int(data[1]) is the size. Print the messages before you build any pattern. Test the name first with a list of the seven valid words, and check the size second with n < 1 or n > 20. A program that prints the messages correctly is already partly finished.
Hint 2: decide the shape of your data
Build the picture as a list of strings, one string per row, and then print the rows one at a time. A list makes the star count easy, because you can count the star characters in each row with row.count("*"). Write a function that takes the name and the size, and returns the list of rows. A list comprehension, such as ["*" * i for i in range(1, n + 1)], is a short way to build a list in one line.
Hint 3: use string multiplication for the simple shapes
In Python, "*" * 4 gives ****, and " " * 2 gives two spaces. The plus sign joins two pieces of text. For square, the row is "*" * n repeated n times. For right, use "*" * i. For inverted, use "*" * (n - i + 1).
Hint 4: the pyramid is spaces plus stars
For a pyramid row, the row text is " " * (n - i) + "*" * (2 * i - 1). The spaces come first, then the stars, so the row has no trailing spaces. The diamond uses the same expression for the top half, and for the bottom half it counts i from n - 1 down to 1, which range(n - 1, 0, -1) produces. The second number in range is never included, so the widest row does not appear twice.
Hint 5: the hollow square needs a test per cell
Use two loops, one for the rows and one for the cells. Inside the cell loop, make a variable called border that is true when i == 1 or i == n or j == 1 or j == n. Collect "*" when the test is true and " " when it is false in a list, and then join the list with "".join(cells). The method join glues a list of text pieces into one string.
Hint 6: the butterfly uses one counter that goes up and down
Count i from 1 to 2 * n - 1 and compute the width of the row from it. For i up to n the width is i. For i above n the width is 2 * n - i. Then the row is "*" * k + " " * (2 * (n - k)) + "*" * k. The formula covers both halves with one loop, and the widest row is printed once.
Hint 7: count the stars once, after the picture is built
After the list of rows is ready, add up the star characters in every row with sum(row.count("*") for row in rows). Print every row, then print the total as "stars: " + str(total). Counting after the build keeps the count honest, because the count matches exactly what you print.
Reference solution
Read this only after you have built your own program and tested it. Compare the two, and note any difference in the test plan, not only in the output. A correct program can be written in many ways, so the goal is to understand this one, not to copy it.
import sys
def square_rows(n):
# n rows, each with n stars
return ["*" * n for _ in range(n)]
def right_rows(n):
# row i has i stars
return ["*" * i for i in range(1, n + 1)]
def inverted_rows(n):
# row i has n - i + 1 stars
return ["*" * (n - i + 1) for i in range(1, n + 1)]
def pyramid_rows(n):
# row i has n - i spaces, then 2 * i - 1 stars
return [" " * (n - i) + "*" * (2 * i - 1) for i in range(1, n + 1)]
def diamond_rows(n):
# the pyramid, then the same rows counted down from n - 1 (the widest row is not repeated)
bottom = [" " * (n - i) + "*" * (2 * i - 1) for i in range(n - 1, 0, -1)]
return pyramid_rows(n) + bottom
def hollow_rows(n):
rows = []
for i in range(1, n + 1):
cells = []
for j in range(1, n + 1):
# a cell is on the border when its row or column is at an end
border = i == 1 or i == n or j == 1 or j == n
cells.append("*" if border else " ")
rows.append("".join(cells))
return rows
def butterfly_rows(n):
rows = []
for i in range(1, 2 * n):
# k is the width of the wing on this row: it rises to n, then falls
k = i if i <= n else 2 * n - i
# gap of 2 * (n - k) spaces between the two wings
rows.append("*" * k + " " * (2 * (n - k)) + "*" * k)
return rows
BUILDERS = {
"square": square_rows,
"right": right_rows,
"inverted": inverted_rows,
"pyramid": pyramid_rows,
"diamond": diamond_rows,
"hollow": hollow_rows,
"butterfly": butterfly_rows,
}
def main():
# split() reads both words whether they are on one line or two
data = sys.stdin.read().split()
name = data[0]
n = int(data[1])
if name not in BUILDERS:
print("unknown pattern")
return
if n < 1 or n > 20:
print("n must be from 1 to 20")
return
rows = BUILDERS[name](n)
for row in rows:
print(row)
# count stars after the picture is built, so the count matches the output
total = sum(row.count("*") for row in rows)
print("stars: " + str(total))
main()The program reads the name and the size, and checks them in that order. Each shape has its own function that returns the rows as text, and main prints them and counts the stars in one pass over the finished rows. The diamond reuses pyramid_rows for its top half, so the pyramid formula lives in one place. The butterfly uses one loop that counts i up to 2 * n - 1 and computes the width from it.
Submitting and reflecting
When your program passes the test plan, write a short note of two or three sentences, in your own words, about the hardest part. Did the hollow border or the butterfly gap take longest? Did the check order surprise you? A note like this shows the reviewer how you think, and it helps you remember the lesson when the topic returns in a later module.
Keep the program short. A pattern printer of this kind should fit on one screen when formatted properly. If your program is much longer, look for loops that repeat the same idea, and move them into a function, as the lessons showed for the diamond and butterfly.
Finally, look back at the planning tables you drew. Each shape in this assignment has a table for its rows, and each table gave you a formula. If your program's formulas match your tables, you have used the method from the first lesson correctly, and that method is the most useful thing this module teaches. Patterns are small, but the habit of drawing the table before the code carries over to every topic that follows.