Due: Tuesday, September 8 at 11:59 PM EDT
This homework reviews the Python tools and programming practices we will use throughout the course. You will practice core Python, NumPy, Matplotlib, classes, objects, and dictionaries.
By the end of the homework, you should be able to:
Credit: Adapted from materials by Sara Mathieson and Allison Gong. Some NumPy examples are based on the NumPy quickstart tutorial.
Download the Homework 1 starter files from Piazza. Your working folder should contain:
python_intro.pynumpy_tutorial.pymatplotlib_tutorial.pyStudent.pydata/facebook_users.csvREADME.mdThe lab computers have Python and the required libraries installed. If you work on your own computer, install Python 3 and the required packages:
python3 -m pip install numpy matplotlib
Run each program from a terminal. For example:
python3 python_intro.py
Your programs may initially produce no output, but they should run without errors.
Complete the exercises in python_intro.py. Test every function in a main() function.
Write a function named movie_ticket_cost() that prompts the user for their age and prints the price of one ticket. Its signature should be:
def movie_ticket_cost() -> None:
Use Python’s input() function and an appropriate conditional statement.
Write two functions that shuffle a given list. Use a type variable so the functions work with lists containing any one type:
from typing import TypeVar
T = TypeVar("T")
def shuffle_in_place(items: list[T]) -> None:
...
def shuffled_copy(items: list[T]) -> list[T]:
...
Do not use a built-in list-shuffling function or a built-in operation that swaps elements. You may use the random library, except for random.shuffle().
Document the algorithm used by each function. In your tests, print the original list after calling each function so that the difference between in-place and out-of-place behavior is clear. The Python list documentation may be helpful.
Write a recursive function that returns the nth Fibonacci number for a non-negative integer n:
def fib(n: int) -> int:
Use these base cases:
Implement two binary-search functions. Each function takes a query and a sorted list lst, then returns the index of the query or -1 if it is absent. Use type annotations like these:
def binary_search_iterative(query: int, values: list[int]) -> int:
...
def binary_search_recursive(query: int, values: list[int]) -> int:
...
Use a loop and maintain low and high indices:
Use recursion and list slicing:
You may write a helper function. Recall that list slices use the following form:
lst[start_index:end_index:step_size]
For example:
words = ["hello", "welcome", "to", "data", "science"]
words[:2] # ["hello", "welcome"]
words[2:] # ["to", "data", "science"]
words[2:4] # ["to", "data"]
In README.md, state the Big-O running time of each binary-search implementation and explain your answers in terms of the list length, n.
NumPy provides arrays, matrices, and efficient mathematical operations. Complete the three typed functions in numpy_tutorial.py, then run main() to see their results alongside the provided demonstrations.
def create_random_3d_array() -> np.ndarray:
Return a NumPy array with shape (4, 6, 5). Fill every entry with a random integer in [0, 301).
def required_slices(
array: np.ndarray,
) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
Return these four slices, in this order:
array[2]array[:, 1]array[:3, :2]array[2:4, :]Before running the code, write the expected value of each slice in README.md.
def concatenate_arrays(
array: np.ndarray,
) -> tuple[np.ndarray, np.ndarray]:
The input will have shape (5, 4). Return:
(6, 4) array formed by appending the row [2, 4, 6, 8] along axis 0.(5, 5) array formed by appending the column [0, 1, 2, 3, 4] along axis 1.Study the provided invalid-concatenation example and explain in README.md why its shapes are incompatible. Also review the provided basic array operations and make sure their output is clear to you.
Complete matplotlib_tutorial.py. You will create two figures: one from real data and one from mathematical functions.
The file data/facebook_users.csv contains two columns: year and the number of monthly active Facebook users worldwide during the fourth quarter, measured in millions. The data were obtained from Statista.
Keep the filename in your code exactly as data/facebook_users.csv. The Gradescope autograder includes its own copy of this dataset and places it at that relative path before running your program. Do not upload facebook_users.csv to Gradescope.
First, read the data one line at a time:
years: list[int] = []
users: list[int] = []
fb_file = open("data/facebook_users.csv", "r")
for line in fb_file:
tokens = line.split(",")
years.append(int(tokens[0]))
users.append(int(tokens[1]))
print(years)
print(users)
Then read the same file as a NumPy array:
user_data: np.ndarray = np.loadtxt("data/facebook_users.csv", delimiter=",")
print(user_data)
Use NumPy slicing to separate the x- and y-values when using the second approach.
Create a scatter plot with plt.scatter():
plt.scatter(x_values, y_values, color="black")
Every submitted graph must include meaningful axis labels and a title:
plt.xlabel("x-axis label")
plt.ylabel("y-axis label")
plt.title("figure title")
Next, overlay predictions from this linear model:
y = -432342.27 + 215.39x
For each year, compute the predicted number of users and draw the predictions with plt.plot():
plt.plot(x_values, predicted_values, color="blue")
Create a figures folder if it does not already exist, then save the finished plot exactly as follows:
plt.savefig("figures/facebook_users.pdf", format="pdf")
plt.clf()
Remove or comment out plt.show() before saving; otherwise, you may save an empty figure.
Use these coefficient lists:
quad_coefs: list[int] = [0, 4, -1] # y = 4x - x^2
cubic_coefs: list[int] = [2, 0, -2, 1] # y = 2 - 2x^2 + x^3
Create a sequence of x-values with np.linspace(), then compute the corresponding y-values for both polynomials:
np.linspace(0, 5, 10)
Plot both curves on one graph. Adjust the number of x-values and observe how it affects the apparent smoothness of the curves. Record your observation in README.md.
Give each curve a label and add a legend:
plt.plot(x_values, y_values, label="curve label")
plt.legend()
Add axis labels and a title. You may use plt.xlim() or plt.ylim() to improve the visible range. Save the final figure exactly as follows:
plt.savefig("figures/quad_cubic.pdf", format="pdf")
This portion is an independent review. Consult the linked Python documentation and ask questions during lab as needed.
Student classIn Student.py, implement a Student class with these attributes:
Define a constructor:
def __init__(self, name: str, graduation_year: int, college: str) -> None:
All instance methods must include self as their first parameter.
Next, implement these methods with the exact signatures shown:
def add_course(self, course: str) -> None:
...
def drop_course(self, course: str) -> None:
...
def __str__(self) -> str:
...
add_course(), which adds a course only when the student is not already enrolled and prints an appropriate message;drop_course(), which removes a course only when the student is currently enrolled and prints an appropriate message; and__str__(), which returns a clear string containing all fields.Getters for the attributes are optional. Comment the class and test every method in main().
Review the Python dictionary documentation. Using the student information supplied in the starter code, construct a dictionary whose keys are integer student ID numbers and whose values are Student objects.
Then complete these experiments:
README.md.Student value already stored under another key. Print the dictionary and explain what happened.Style is part of the grade for every lab. Follow PEP 8 and these course conventions:
snake_case; classes use PascalCase.from module import *.Example function documentation:
def fib(n: int) -> int:
"""Return the nth Fibonacci number.
Args:
n: A non-negative integer.
Returns:
The nth Fibonacci number.
"""
Before submitting:
main() for every Part 1 function and every Student method;README.md;Submit one .zip file to the HW01 assignment on Gradescope. The archive must preserve this structure:
python_intro.py
numpy_tutorial.py
matplotlib_tutorial.py
Student.py
README.md
figures/facebook_users.pdf
figures/quad_cubic.pdf
Do not include data/facebook_users.csv in the submitted archive. Although the file is part of the starter materials for local testing, the Gradescope autograder supplies it automatically at data/facebook_users.csv when your code runs.
Name the archive LastName_FirstName_HW01.zip. After uploading, verify that Gradescope displays every required file.