Problem Set 4 - Due Mon, Feb 27 at 23:59

Reading

  1. Think Python, Ch. 8: Strings
  2. Think Python, Ch. 7: Iteration
  3. Slides and notebooks from Lec 6 and Lec 7
  4. 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.

  1. In Task 1 you will create your own function that uses a loop construct to generate a picture with repeating elements from cs1graphics.
  2. 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.
  3. 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
  4. In Task 3 you will write a new solution that uses loops for the Diamonds Pattern Task 1 from ps02.
  5. The CS111 Problem Set Guide gives an overview of psets, including a detailed description of individual and partner tasks.
  6. 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

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


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.

  1. Is the word a palindrome? Palindromes are words that spell the same backwards as forwards -- for example, civic and noon.
  2. 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.
  3. 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 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

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

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:


How to turn in this Problem Set