Problem Set 7 - Due Friday, April 17, 2020

Reading

  1. Slides and notebooks from Lec 13 (Nested Loops). For the second challenge problem, slides and notebooks from Lec 15 (Sorting).
  2. Problems and solutions from Lab 09 (Nested Loops and Sorting).
  3. Think Python, Ch. 7: Iteration and Think Python, Ch. 10: Lists

About this Problem Set

This problem set will give you practice with nested lists and loops in the context of turtle graphics. There is a challenge problem if you want to practice sorting.

Both challenges are entirely optional; there is only one normal task for this problem set.

If you want to find a partner to work with (on any or all parts of the pset), you can use this Piazza post.

Other notes:

All code for this assignment is available in the ps07 folder in the cs111/download directory within your cs server account.


Task 1: Drawing Tiles

The task 1 rubric shows how this task will be graded, and can be used as a checklist to make sure you are done with the task (but remember that all we require now is an honest attempt).

For this task, you will write turtle drawing code using nested loops that can create pictures like these:

A tiled picture using stacked red rectangles to create a brick wall effect. A tiled picture using alternating bright and dark overlapping stripes to create a basket-weave effect. A tiled picture using random diagonal lines to create a maze-like image.

These pictures are drawn using rectangular arrangements of square tiles, like the four tiles shown in this image:

An image showing four tiles: two parts of a brick wall that fit together, and two parts of a basket weave pattern that fit together.

First you will write code to draw a single tile, then to draw a floor pattern made of many tiles. In both cases, a nested list (a list which contains other lists) will specify the pattern to be drawn.

Subtask 1a: Drawing One Tile

For this subtask, your goal is to fill out the definition of the drawTile function in tiles.py so that it draws a single tile. The function is given two parameters to work with: a tilePattern, which is a nested list specifying the colors for the tile to be drawn, and a tileHeight, which specifies how large the entire tile should be. You may assume that all tiles are square, but they may not all have the same number of rows and columns. A tilePattern is a list of lists of colors, and looks like this:

exampleTile = [
    [ "blue", "blue", "navy" ],
    [ "blue", "navy", "blue" ],
    [ "navy", "blue", "blue" ]
]

That tile pattern when drawn by drawTile would look like this:

A 3x3 blue square region with three smaller squares of darker blue in the upper-right, center, and lower-left sections of the 3x3 region. The smaller squares fill each section so that their corners touch diagonally. The turtle is shown facing east and touching the north-west corner of the blue region.

Notice how the turtle (indicated by the arrow) is at the north-west corner of the square and is facing east: that is both the starting and ending position of the turtle when drawTile is called.

Your drawTile function should work for any square tile pattern and any positive tile height specified.

The docstring for the drawTile function describes in detail how it works, all you have to do is implement it so that is behaves as described here and in that docstring.

Notes

Subtask 1b: Drawing a Floor Pattern

Once you get your tile drawing function working, the second part of this task is to fill out the drawFloor function. It is quite similar to drawTile, with a few differences:

  1. Instead of starting from (and ending at) the north-west corner, it starts from the (vertical) center of the west edge of the floor.

  2. Although tiles are always square, floor patterns may be rectangular (the brick wall pattern above is 6x4, for example). You may still assume that each row of the floor pattern contains the same number of entries (no mismatched rows).

  3. Instead of each entry in the rows of the pattern being a color string, each entry will be an entire tile pattern. Your drawFloor function must call your drawTile function to draw the tiles.

The docstring for drawFloor describes its behavior in detail. Go ahead and implement it according to the behavior described there and here. When you're done the testing code should draw the brick wall and basket weave patterns shown above.

Notes

Subtask 2c: Create Your Own Floor

Now that you've gotten the drawTile and drawFloor functions done, it's time for some fun: fill out the code for myFloorPattern so that it returns a floor pattern, which uses one or more custom tiles that it also defines (the starter code defines one tile which is just a blue square, and a pattern that's just one of those tiles).

When your myFloorPattern function is returning a custom floor pattern, the last piece of testing code should show you what this pattern looks like. Your function can simply return a list structure that you carefully craft by hand and enter into your Python file, or it can use code (even perhaps nested for loops) to create some kind of complex pattern if you like (what about a rainbow, for example?).

The final picture shown above is a custom floor pattern created from two diagonal tiles that are selected at random to fill in the floor, creating a randomized maze structure. The inspiration for that pattern is a 1-line BASIC program from the 1980's.


Feedback: Time Spent File

As in the previous psets, your time spent submission for this pset will involve entering values for the variables in the timeSpent.py file.


How to turn in this problem set

Challenge Problems (optional & ungraded)

Challenge 1: Advanced Tiles

This is an open-ended challenge: extend your tile and floor drawing code in some way to create new possibilities for drawing tiles, and then create a new custom floor that makes use of these. Make sure that you do this in another file (e.g., fancyTiles.py) so that your task 1 code is not changed.

Examples of ways you could extend the code:

Here are some example images that are possible with a few of the above extensions:

A tiled picture using stacked red rectangles to create a brick wall effect. A tiled picture using alternating bright and dark overlapping stripes to create a basket-weave effect. A tiled picture using alternating bright and dark overlapping stripes to create a basket-weave effect. A tiled picture using random diagonal lines to create a maze-like image.

Challenge 2: Word Patterns and Distant Reading

In literature, especially "classic" literature, authors' perspectives shape the possibilities of the narrative world in ways that don't fully reflect the real world we live in. Actions that an author deems important or realistic occur, other actions do not.

One group of techniques that can help us examine how the world of a novel is constructed is called "distant reading," and these techniques involve reading a text not in the linear manner that was intended but instead picking out words or phrases based on some other principle and examining the patterns that result. Interpreting these patterns can be tricky, but they can also reveal interesting information.

For this challenge, you will apply a very simple distant reading technique to several classic novels to examine how often different classic novels discuss men vs. women.

In the distantReading.py file there is a pronounUsage variable which contains data extracted from a few "classic" novels about how many times different gendered pronouns are used (unfortunately, this technique is not easy to extend to examine representation of characters beyond a gender binary, which is one of its limitations). In this challenge exercise, you'll fill in the various sorting functions in distantReading.py which sort the data in different ways, and finally create a report function that sorts the data according to the ratio between female and male pronouns and then prints information about each novel in sorted order, including the "gender ratio" for that novel.

You will write three sorting functions, each with an associated helper function act as the sort key:

Finally, you will write a reportGenderRatios function which uses sortByGenderRatio to sort the data, and then prints the title, author, year of publication, and gender ratio for each novel in the sorted result.

Click on "show results" below to show the correct results, but only after you've written the sorting functions yourself and think that they're correct.

Show results The full output of the program when all functions have been implemented should be:
By year:
  Don Quixote
  Emma
  Frankenstein
  Alice's Adventures in Wonderland
  Dracula
  Anne of Green Gables

By total pronouns:
  Don Quixote
  Emma
  Dracula
  Anne of Green Gables
  Frankenstein
  Alice's Adventures in Wonderland

By gender ratio:
  Anne of Green Gables
  Alice's Adventures in Wonderland
  Emma
  Frankenstein
  Dracula
  Don Quixote

Gender ratio report:
"Anne of Green Gables" by Lucy Maud Montgomery, 1908: 3.298
"Alice's Adventures in Wonderland" by Lewis Carroll, 1865: 3.066
"Emma" by Jane Austen, 1815: 1.298
"Frankenstein" by Mary Shelley, 1818: 0.464
"Dracula" by Bram Stoker, 1897: 0.377
"Don Quixote" by Cervantes, 1605: 0.235

 

Although this kind of word-counting is a fairly trivial example of distant reading, we will get to a more interesting example next week when we are learning about dictionaries.