Homework 5: Containers¶
Objectives¶
- Gain experience working with the membership operator (
in
) and identity operator (is
). - Solve problems using the following container types:
list
,tuple
,set
,dictionary
.
Submissions Limited
From now on, the number of submissions on Gradescope will be limited. For HW5, you may submit each exercise up to 20 times. Before you submit to Gradescope, make sure that you:
- Test your code, either in the shell or in the
__main__
block. - Run
!flake8
, and resolve all PEP 8 and docstring issues.
Exercise 5.1 Object Comparisons¶
For this exercise you will write a function that will evaluate any two
Python objects in order to provide a numeric score indicating how
closely related they are. Create a file named compare.py
with a
single function named compare
. This function must take two
arguments, and must return an integer satisfying the
following requirements:
- If the arguments contain references to the same object, return 0.
- If the arguments refer to different objects with same type and same value, return 1.
- If the arguments are the same type, but have different values, return 2.
- If the arguments are of different types, return 3.
The following interaction provides some examples of the expected behavior.
>>> a = "#1"
>>> b = a
>>> c = "#"
>>> c += "1"
>>> d = "#2"
>>> e = 7
>>> compare(a, b) # Same object.
0
>>> compare(a, c) # Different objects the same value.
1
>>> compare(c, d) # Same type, different values.
2
>>> compare(d, e) # Different types.
3
Exercise 5.2 Sort Short¶
Create a file named sorting.py
that provides two functions:
swap
and sort_short
.
swap
¶
The swap
function must take three arguments: a list, and two
integers representing indices into the list. It must then swap the
the list elements stored at the provided indices. It should not have
any return value.
Here is an example of the expected behavior:
>>> items = ["a", "b", "c"]
>>> swap(items, 0, 2)
>>> print(items)
['c', 'b', 'a']
sort_short
¶
The sort_short
function must take a single list argument containing
numeric values. The list will have no more than three items. This
function must rearrange the items in the list so that they appear in
increasing order. Your implementation should call the swap
method as
needed to move items within the list. For example, if we knew that
the list would have exactly two items, the following implementation
would be correct:
def sort_short(items):
if items[0] > items[1]:
swap(items, 0, 1)
There is no return value. You may assume that the list will not contain duplicates.
Here is an example illustrating how we can use the assert
statement
to check for the correct behavior:
if __name__ == "__main__":
items = [1]
sort_short(items)
assert items == [1]
items = [2, 1]
sort_short(items)
assert items == [1, 2]
items = [3, 2, 1]
sort_short(items)
assert items == [1, 2, 3]
The assert
statement provides a built-in mechanism for confirming
that our code is working as expected. If the expression after assert
evaluates to True
, then nothing happens, if it evaluates to False
,
then there will be an AssertionError
indicating that there is
something wrong with our implementation (or with our test).
Note: Your solution must not use any loops, and it must not use any built-in sorting functions.
Exercise 5.3 Image Manipulations¶
Computers typically represent images as a grid of pixels where each pixel is a tiny rectangular region of a particular color. The color of a pixel may be represented as a three-entry tuple where the first entry represents the amount of red, the second represents the amount of green and the third represents the amount of blue. These three color values (often referred to as channels) are restricted to be in the range 0–255. For example:
# Create some variables to store tuples representing common colors...
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
black = (0, 0, 0)
white = (255, 255, 255)
Complete the following two functions for working with color values.
These should both be in a file named color_utils.py
.
adjust_brightness
¶
This function will take two parameters: the first is a length-three tuple representing a color. The second is an integer representing a value (positive or negative) that will be added to each color channel. The return value must be a tuple where each color channel has been adjusted by the requested quantity, with values clipped to stay in the range 0-255. For example:
>>> %Run color_utils.py
>>> adjust_brightness((0, 0, 250), 10)
(10, 10, 255)
>>> adjust_brightness((100, 5, 255), -10)
(90, 0, 245)
Advice: As you program this function, you will probably find
yourself repeating much of the code three times: once for each color
channel. This is a good opportunity to use a helper function.
Helper functions are functions that simplify the implementation, but
aren't explicitly required by the specification. In this case, it
would be useful to have a helper function named adjust_channel
that would handle the logic for increasing or decreasing the value of
a single color. You can then avoid code duplication by calling this
function three times in adjust_brightness
.
same_color
¶
This function returns a Boolean value indicating whether two provided color tuples are similar enough to be considered the same color. It must take three parameters: the first two are color tuples, and the third is an integer value representing the maximum allowable difference between corresponding channels in the two color tuples. For example:
>>> same_color((128, 25, 80), (128, 25, 80), 0)
True
>>>> same_color((129, 25, 80), (128, 25, 80), 0) # Red differs by 1!
False
>>>> same_color((129, 25, 80), (128, 25, 80), 1) # Allow a difference of 1!
True
Just for fun: We've provided some simple demo programs that you
can use to try out these functions once you have them working. In
order to execute these programs, store then in the same directory as
your color_utils.py
file and run them using Thonny. You will need
to install the Pillow
(Python Imaging Library) package through the
Thonny package manager.
-
adjust_brightness.py
: This application allows the user to select an image (which must be in JPG format), and increase or decrease the brightness by a user-specified amount. This is accomplished by applying youradjust_brightness
function to each pixel. -
green_screen.py
: This application allows the user to select an image with a green-screen background and a second image that will be used as a background replacement. It then applies a green-screen effect by checking each pixel in the original image against the green-screen color using yoursame_color
function. Pixels that are determined to be the same color as the green screen are replaced with the corresponding pixel from the background image. You can test the application using the following two images. Right click them and download them into the same folder as your Python code.
If you want to create your own green-screen images, this web-based image viewer will allow you to view the colors of individual pixels so you can determine the appropriate color values for the "green" in your background: https://imagecolorpicker.com.
Exercise 5.4 Basketball Scores¶
The JMU basketball program needs help calculating player
statistics. They would like you to write them a program, named
scores.py
, containing two functions:
player_stats
This function must take a list argument containing a sequence of integers, where each integer represents the total points scored by a particular player in a single game. It must return a dictionary with the following key/value pairs:- The
"total"
key must be mapped to the player's total points for the season. - The
"average"
key must be mapped to the player's average points per game. - The
"zeros"
key must be mapped to the number of times the player scored 0 points in a game. - The
"final"
key must be mapped to the number of points the player scored in the final game of the season.
- The
print_stats
This function must take two arguments: a string representing a player name and a list argument containing a sequence of integers representing the points scored by a particular player. It should then print out a nicely formatted report with each of the statistics provided by theplayer_stats
method. This function must not include the logic for calculating the various statistics. Instead, it must callplayer_stats
and make use of the returned dictionary.
Here is an example illustrating the expected behavior of player_stats
:
>>> stats = player_stats([19, 6, 12, 22, 22, 17])
>>> print(stats)
{'total': 98, 'average': 16.333333333333332, 'zeros': 0, 'final': 17}
Here is an example illustrating the expected behavior of print_stats
:
>>> print_stats("Kiki Jefferson", [19, 6, 12, 22, 22, 17])
--Kiki Jefferson--
Total points: 98
Average points: 16.3
Number of 0 point games: 0
Final game score: 17
Notice that each statistic is indented two spaces and the average points value is rounded to one decimal place.
Both functions should work correctly for any list of integers of length at least 1. You should test your functions with several different integer lists to make sure that they behave correctly in each case.
Note: You must not use loops in your program. Programs that use loops will receive no credit.
Exercise 5.5 Assigning Tasks¶
For this exercise you will write Python code to assist in fairly
dividing up tasks between two roommates. You must create a file named
assign.py
that contains a single function named assign_task
.
The assign_task
function must take three
arguments: a string representing the new task, and two sets containing
the tasks that have already been assigned. The function must return a
Boolean indicating whether the resulting assignment is fair. A
fair assignment is any assignment such that number of elements in each
set differs by at most one. Task assignments must satisfy the
following requirements:
- There can be no duplicate tasks. If a task already exists in either set, it must be ignored. You may assume that there will not be duplicate tasks in the provided sets.
- New tasks must be added to the set that currently has fewest items. In the case of a tie, the task must be added to the set associated with the first set argument.
The following interaction provides some examples of the expected behavior:
>>> my_work = set(["sweep", "windows", "laundry"])
>>> your_work = set()
>>> assign_task("tidy", my_work, your_work)
False
>>> print(my_work, your_work)
{'windows', 'sweep', 'laundry'} {'tidy'}
>>> assign_task("sweep", my_work, your_work)
False
>>> print(my_work, your_work)
{'windows', 'sweep', 'laundry'} {'tidy'}
>>> assign_task("garbage", my_work, your_work)
True
HW5 Reflection (required)¶
Submit the graded survey on Canvas after completing the assignment.