Problem Set 4 - Due Mon, Feb 27 at 23:59
Reading
- Think Python, Ch. 8: Strings
- Think Python, Ch. 7: Iteration
- Slides and notebooks from Lec 6 and Lec 7
- Lab 05: Loops
About this Problem Set
This problem set will give you practice with strings, operations with strings, loops with strings, loops with graphics.
- In Task 1 you will create your own function that uses a loop construct to generate a
picture with repeating elements from
cs1graphics
. - In Task 2 (Partner task), you will create your own functions that use loops to analyze and manipulate strings. Use this shared Google Doc to find a pair programming partner and record your partner . Please do not use the cs111-spring17 group to find a partner. Remember that you can work with the same partner a maximum of TWO times this semester.
- NEW: Penality for not recording your partner. We will deduct 2 points per day for any students who have not recorded their names on the pair programming google doc by Thursday, Feb 23rd at 11:59pm
- In Task 3 you will write a new solution that uses loops for the Diamonds Pattern Task 1 from ps02.
- The CS111 Problem Set Guide gives an overview of psets, including a detailed description of individual and partner tasks.
- Last semester students spent on average 2.2 hours on Task 1A (min/max = 0.5/7 hrs); 2.6 hours on Task 2 (min/max = 1/8 hrs; and 1.3 hours on Task 3 (min/max = 0.15/8 hrs). Spring 2017, Task 1B is a newly added task.
All code for this assignment is available in the ps04
folder in
the cs111/download
directory within your cs
server account.
This assignment also uses the Otter Inspector program
to help you do a final check for Task 2, Task 3 and your Honor Code form before you submit.
Guidelines for the correctness and quality of your solution are here.
Task 1A: Concentric Circles
This is an individual problem which you must complete on your own, though you may ask for help from the CS111 staff.
In this task, your goal is to generate pictures like the following:
![]() |
![]() |
paper1 = Canvas(200, 200) cybla = concentricCircles(200, 5, 'cyan', 'black') paper1.add(cybla) cybla.move(100, 100) |
paper2 = Canvas(400, 400) grellow = concentricCircles(400, 8, 'green', 'yellow') paper2.add(grellow) grellow.move(200, 200) |
![]() |
![]() |
paper3 = Canvas(500, 500) pima = concentricCircles(500, 2, 'pink', 'magenta') paper3.add(pima) pima.move(250, 250) |
paper4 = Canvas(500, 500) reblu = concentricCircles(500, 13, 'red', 'blue') paper4.add(reblu) reblu.move(250, 250) |
You will create a Python file named circles.py
and define in it the function
concentricCircles
that fulfills the following contract:
def concentricCircles(size, numCircles, color1, color2):
"""Creates and returns a Layer containing numCircles
circles, all of which are centered at (0, 0).
Let r be the radius of the smallest circle. Then the radii of
the circles grow in arithmetic progression -- r, 2r, 3r, etc. --
up to the radius of the largest circle, which is size/2.
The smallest circle is filled with color1 and afterwards the colors are
alternated between color1 and color2.
"""
Notes
- Read the contract carefully, to determine how to calculate the radius of the largest and smallest circles, as well as every radius in between.
- Use an appropriate
for
loop to draw the circles. - You can draw the circles from smallest to largest or from largest to smallest.
If you draw the circles from smallest to largest, the
setDepth
method is helpful for preventing later, bigger circles from hiding the smaller ones. To learn how to use this method, study the example in the slide 6-34 (Lecture notes for "Sequences and Loops"). - The first color is always used to color the smallest circle in the center.
- Don't forget to import
cs1graphics
via the following line at the beginning of your code:from cs1graphics import *
Testing
Your function should work as described for any arguments, but you should at the very least test it on the examples pictured above.
If you look at the 4 statements (shown in gray boxes in Task 1A above) that are
used to generate each of the concentric circles above, you'll note
there is a pattern. Capture that pattern by writing a function called
showConcentricCircles
that fulfills the following contract:
def showConcentricCircles(canvasSize, numCircles, color1, color2):
"""Creates and returns a canvasSize x canvasSize white canvas containing
numCircles concentric circles centered in the canvas, with the
smallest circle having color1 and alternating with color2.
"""
For example, the following invocation produces the canvas below (note the title):
showConcentricCircles(500, 13, 'red', 'blue')

All of your testing should be done using main
.
If you add the code below to your circles.py
file
and run it, you should see the circles that match those shown above. (For a reminder
on using main
convention for testing,
scroll down to the Disabling Test Work section in Lab03).
if __name__ == "__main__":
cybla = showConcentricCircles(200, 5, 'cyan', 'black')
grellow = showConcentricCircles(400, 8, 'green', 'yellow')
reblu = showConcentricCircles(500, 13, 'red', 'blue')
pima = showConcentricCircles(500, 2, 'pink', 'magenta')
Recall that is we use a variable to store the returned canvas object, then we can close the canvas from the command line as shown below:
cybla.close()
Task 1B: Rows of Concentric Circles
This is an individual problem which you must complete on your own, though you may ask for help from the CS111 staff.
In this task, your goal is to generate pictures like the following:
![]() |
single = circleRow(1, 500, 7, 'orange', 'yellow') |
![]() |
triple = circleRow(3, 400, 10, 'red', 'pink') |
![]() |
quint = circleRow(5, 240, 8, 'blue', 'green') |
![]() |
dozen = circleRow(12, 100, 10, 'black', 'white') |
Note that we use variables to store the returned canvas objects so we
can close the canvas from the command line (e.g., dozen.close()
).
In your circles.py
file, you will create a function
circleRow
that fulfills the following contract:
def circleRow(numCirclesInRow, size, numCircles, color1, color2):
"""Creates and returns a numCirclesInRow*size x size white canvas containing
numCirclesInRow circles, each of which is a concentric circle (created
by invoking concentricCircles). The distance between the center of each
successive circle is size. The title of the canvas should be a string
representation of the invocation of the circleRow function that
created the canvas."""
Testing
All of your testing should be done using main
.
Your function should work as described for any arguments, but you
should at the very least test it on the four examples pictured above.
Note that if you choose a large number for numCirclesInRow
, this may
generate a canvas that does not fit within your screen.
For example, the test code below should generate the blue and green row of 5 circles shown above.
if __name__ == "__main__":
quint = circleRow(5, 240, 8, 'blue', 'green')
You can close the canvas from the command line:
quint.close()
Notes
- Read the
circleRow
contract carefully to determine how to create your row of concentric circles and how to determine the size of the canvas circleRow
returns a Canvas object- Use an appropriate
for
loop to draw the row of circles - You must invoke
concentricCircles
that you wrote for Task 1A incircleRow
- The title of the canvas must include the values of all
circleRow
parameters
Task 2: Word Play
This task is a partner problem in which you are required to work with a partner as part of a two-person team.
Subtask 1: Word Properties
We are interested in some fun properties of written words.
- Is the word a palindrome? Palindromes are words that spell the same backwards as forwards -- for example, civic and noon.
- Does the word use only the top row of keys (i.e., 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p') on the keyboard? Examples are typewriter or pretty.
- What is the Scrabble value of the word? This is determined by adding the points assigned by Scrabble to each letter, which are:
A = 1 | B = 3 | C = 3 | D = 2 | E = 1 | F = 4 |
G = 2 | H = 4 | I = 1 | J = 8 | K = 5 | L = 1 |
M = 3 | N = 1 | O = 1 | P = 3 | Q = 10 | R = 1 |
S = 1 | T = 1 | U = 1 | V = 4 | W = 4 | X = 8 |
Y = 4 | Z = 10 |
Your task is to flesh out the definitions of the functions in the provided file
wordplay.py
. Your functions should not be sensitive to capitalization (see examples below).
In [2]: isPalindrome('civic')
Out[2]: True
In [3]: isPalindrome('Noon')
Out[3]: True
In [4]: isPalindrome('soon')
Out[4]: False
In [5]: isTopRow('Typewriter')
Out[5]: True
In [6]: isTopRow('pretty')
Out[6]: True
In [7]: isTopRow('rest')
Out[7]: False
In [8]: scrabbleScore('juxtapose')
Out[8]: 25
In [9]: scrabbleScore('quiz')
Out[9]: 22
In [10]: scrabbleScore('Wellesley')
Out[10]: 15
Notes
- The string method
lower
will be useful in all functions. - Python has a very terse statement for reversing a word, which you saw
in lecture.
In [11]: word = 'wellesley' In [12]: word[::-1] Out[12]: 'yelsellew'
The reason this works is because Python allows negative indices to refer to the elements of a sequence. Refer to slide 6-23 in the Lecture 06 notes. A less cryptic way to write the above statement is the following:
In [13]: word[-1:-(len(word)+1):-1]
Out[13]: 'yelsellew'
Clearly, the terse form is easier to write, but harder to understand.
Subtask 2: Mystery Speech
How would English sound like if we were not allowed to use each letter more than once in a sentence? Would one still be able to understand it? Let's try it out with some famous (or not) phrases. Can you guess them? (The phrases are shown at the end of this subtask).
In []: keepFirstLetter(somePhrase1)
Out[]: 'To be r n '
In []: keepFirstLetter(somePhrase2)
Out[]: 'The king s da, lo v !'
In []: keepFirstLetter(somePhrase3)
Out[]: 'We ar nv gti bck oh'
In this subtask, you'll flesh out the body of the function keepFirstLetter
which transforms string phrases as shown above. This function is also
part of the wordplay.py
file.
def keepFirstLetter(phrase):
"""Returns a new string that contains only the first occurrence of a
letter from the original phrase.
The first letter occurrence can be upper or lower case.
Non-alpha characters (such as punctuations and space) are left
unchanged.
"""
Notes
- The string methods
lower
andisalpha
will come handy in this task. - You will need to create state variables that keep track of the changing state during the iteration.
- The phrases used above are:
somePhrase1 = 'To be or not to be' somePhrase2 = 'The king is dead, long live the king!' somePhrase3 = "We are never ever getting back together" # a Taylor Swift song
- Remember to put all your testing inside
if __name__ == '__main__':
Fun Ungraded Challenge: If you manage to create a meaningful English phrase
which after passing through keepFirstLetter
contains all the
letters of the alphabet, please post it to the Google Group. We will add them to the
mystery phrases for the next semester.
Task 3: Revisiting the Diamond Pattern
This is an individual problem which you must complete on your own, though you may ask for help from the CS111 staff.
In the file diamonds.py
, write a new solution that uses loops to
print the same diamond pattern from Task 1 in ps02.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Goal for this problem
Your goal is to strive for a concise solution that uses functions and
loops to capture as many patterns as possible. For many, this will
require a departure from your ps02 diamond
solution and an
exploration of for loops and lists.
Notes/Constraints
- You'll again define a zero-parameter function,
diamondPattern
, that prints the entire pattern. - Your new solution should use at least one
for
loop. -
Use only the predefined strings (see
diamonds.py
in theps04
folder) and no others.-
You may concatenate these strings to form larger strings, but may not build any new strings delimited by quotation marks.
- Note that we have added one new variable in the file
diamonds.py
that you may use:starList = [oneStar, twoStar, threeStar, twoStar, oneStar]
-
- You may not use the newline character
\n
. - You are allowed to use the
print
function directly at most 5 times in your program (more credit will be given to solutions with fewerprint
invocations). -
Full credit will be awarded to solutions that effectively minimize the number of functions and the number of function calls.
- Remember to put all your testing inside
if __name__ == '__main__':
Task 4: Honor Code Form
As in the previous two psets, your honor code submission for this pset will involve
defining entering values for the variables in the honorcode.py
file.
Remember to run otterInspect.py
one final time before you submit
to check that your wordplay.py
and diamonds.py
programs work as intended, and
that your honor code form is complete.
While running your code through otterInspect is not required,
it is highly recommended since it may catch errors that you haven't noticed.
If you have issues running otterInspect.py
, first check the following:
- Your code is in the provided program files in the
ps04
folder, and you haven't deleted or moved any of the existing files. - You have selected "Keep directory synced to editor" when running
otterInspect.py
in Canopy - You have followed the specifications here of how your code should be organized into functions.
- If
otterInspect
says you have failed test cases, read the problem set directions carefully to verify exactly what your functions are supposed to do. In particular, be careful about the distinction between print and return, and check that the returned values are of the appropriate types. Precision is important in CS! Points will be deducted for such mistakes.
How to turn in this Problem Set
- Save your final
circles.py
anddiamonds.py
file in theps04
folder. - Each team member should save their
wordplay.py
file in theirps04
folder. This file should contain a comment with names of both partners at the top. - Save your filled-up
honorcode.py
file inps04
as well. - Note: It is critical that the name of the folder you submit is
ps04
, and your submitted files arecircles.py
,wordplay.py
,diamonds.py
, andhonorcode.py
. In other words, do not rename the folder that you downloaded, do not create new files or folders, and do not delete or re-name any of the existing files in this folder. Improperly named files or functions will incur penalties. - Drop your entire
ps04
folder in yourdrop
folder on thecs
server using Cyberduck by 11:59pm on Monday, Feb 27th, 2017. - Failure to submit your code before the deadline will result in zero credit for the code portion of PS4.