The primary purpose of this problem is to give you more practice with recursion, and also to help you recognize that
recursive functions can take the place of for
and while
loops.
IMPORTANT: As mentioned in the Programming Requirements section below you are strictly prohibited from using for
and/or while
statements and/or list comprehensions in your solution. Violating this restriction may result in a score of zero for this problem.
Write a Python program in, street.py
, that prompts the user for a one-line specification of a city street and then prints a simple ASCII rendering of it. The user should be prompted as follows:
input("Street: ")The user responds with a specification that has some number of buildings, parks, and empty lots. As an example, the input line
p:19,* b:5,7,x e:7,__~is rendered as this:
+-------------------------------+ | | | xxxxx | | xxxxx | | * xxxxx | | *** xxxxx | | ***** xxxxx | | | xxxxx | | | xxxxx ~ ~ | +-------------------------------+
The input will be a single line that contains one or more whitespace-separated specifications for buildings, parks, and/or empty lots that appear along the street.
"b:WIDTH,HEIGHT,BRICK"
. The building on the street shown above has this specification:b:5,7,xThe string above specifies a building with a width of five, a height of seven, that is built of
"x"
s. Assume that WIDTH
and HEIGHT
are integers greater than zero and that BRICK
is always a single non-whitespace character.
"p:WIDTH,FOLIAGE"
. A park has exactly one tree and that tree is centered in the park. Parks always have an odd integer width that is greater than or equal to five. Every park's tree has the same shape and size but has the FOLIAGE
that is specified.
Like the brick for a building, FOLIAGE
is always a single non-whitespace character.
The park shown on the street above has this specification:
p:19,*
"e:WIDTH,TRASH"
. (Sadly, empty lots tend to accumulate trash.) The empty lot shown on the street above has this specification:
e:7,__~
The TRASH
string, "__~"
in this case (two underscores and tilde), specifies a string that is repeated as necessary to span the width of the empty lot.
Replicating "__~"
to its width of seven produces "__~__~_"
. Further, an underscore in a TRASH
string is interpreted as a blank. Combining those rules for this lot
("e:7,__~"
) produces this seven character string: " ~ ~ "
.
A TRASH
string may be longer than the width of the lot. If so, the excess characters simply don't appear in the rendered lot.
Here is a more complex street:
b:3,10,a e:10,+- p:13,* b:7,15,x b:17,4,% b:10,8,y e:5,_ b:1,3,$ p:13,^ b:10,3,# e:9,__.and its rendering:
+--------------------------------------------------------------------------------------------------+ | | | xxxxxxx | | xxxxxxx | | xxxxxxx | | xxxxxxx | | xxxxxxx | |aaa xxxxxxx | |aaa xxxxxxx | |aaa xxxxxxx yyyyyyyyyy | |aaa xxxxxxx yyyyyyyyyy | |aaa xxxxxxx yyyyyyyyyy | |aaa * xxxxxxx yyyyyyyyyy ^ | |aaa *** xxxxxxx%%%%%%%%%%%%%%%%%yyyyyyyyyy ^^^ | |aaa ***** xxxxxxx%%%%%%%%%%%%%%%%%yyyyyyyyyy $ ^^^^^ ########## | |aaa | xxxxxxx%%%%%%%%%%%%%%%%%yyyyyyyyyy $ | ########## | |aaa+-+-+-+-+- | xxxxxxx%%%%%%%%%%%%%%%%%yyyyyyyyyy $ | ########## . . .| +--------------------------------------------------------------------------------------------------+
Along with the specifications above, note these points:
Some additional examples of the behavior of this program are given here.
This program does no error handling whatsoever. The behavior is undefined if any of the above specifications are not met. That phrase, "behavior is undefined", tells the user that the program's handling of invalid input is unpredictable. For example, if a building specification is missing the BRICK
, the program might terminate with an error, or terminate with an assertion failure, or it might use the same brick that was used in a previous building. A negative height might cause the program to go into an infinite loop.
The bottom line is that you should write code that assumes the input is correct. The tester won't have any cases with invalid input. No cases with invalid input will be used when grading. All you've got to worry about is the "happy case".
An essential requirement of this problem is that you may not use any for
or while
statements or list comprehensions in your solution. Use recursion in place of looping, as you've seen done in lecture and have done yourself when solving the CloudCoder problems.
I think of this as a challenging problem to solve given only the description above and what you've seen in class, but for those who wish to have a challenge, I'll say nothing here about how to approach it. If you have trouble getting started, however, here are some hints.