def robust_addition(numbers : list) -> float:
# TODO: Implement the function to sum only numeric values in the list.
pass
Assignment 01: Programming
AI Notice: I expect that this entire assignment can be readily solved by today’s AI systems. I would encourage you to attempt the assignment yourself first, but if you find yourself stuck, you can use AI tools to help you. I have to emphasize that if you do so, it is crucial that you take the time to understand the AI’s solution and not just copy it. The goal is to learn and practice the concepts, not just to complete the assignment. If you don’t need AI to solve the assignment – great! It can still help – ask it to review your solution, critique it, or suggest improvements. This will help you learn even more about how to write good code.
Problem 1: Robust addition
Write a function that takes in a list of numbers and returns their sum. However, if the list contains any non-numeric values, the function should ignore those values and only sum the numeric ones. The exception is if the non-numeric values can be converted to numeric types (like strings representing numbers), in which case they should be converted and included in the sum. If the list is empty or contains no numeric values, the function should return 0.
Problem 2:
You have a 1D NumPy array of student scores (0–100).
- Write a function pass_rate(scores, threshold) that returns the fraction of scores ≥ threshold.
- Write a function top_percentile(scores, p) that returns the score value at the p-th percentile (e.g. p=0.9 ⇒ 90th percentile).
Constraints:
- Use no Python loops or list-comprehensions.
- Leverage NumPy’s casting behavior (boolean \(\to\) integer).
import numpy as np
from typing import Union
= Union[np.ndarray, list[float]]
Array1D
def pass_rate(scores: Array1D, threshold: float) -> float:
"""
Return the proportion of entries in `scores` >= threshold.
"""
= np.asarray(scores)
arr # TODO: compute proportion without loops
...
def top_percentile(scores: Array1D, p: float) -> float:
"""
Return the p-th percentile of `scores`, where 0 < p < 1.
"""
= np.asarray(scores)
arr # TODO: use a single np function
...
Problem 3: Palindrome Checker
Write a function that checks whether a given string is a palindrome (a word, phrase, number, or other sequence of characters that reads the same forward and backward, ignoring spaces, punctuation, and capitalization). The function should return True
if the string is a palindrome and False
otherwise.
def is_palindrome(s: str) -> bool:
# TODO: Implement the function to check if the string is a palindrome.
# Ignore spaces, punctuation, and capitalization.
pass
Problem 4: Multiple data tables and Pandas operations
We did not cover how to do all this in class, but here are some exercises to practice merging and querying data with Pandas. Please refer to the Pandas documentation, the links below, and feel free to ask AI assistants to point you to the right functions and methods.
Some related reading: - Blog post on relational databases - Joins in SQL / relational databases - Joins in Pandas
Below we define the data for a set of tables related to car registrations and traffic violations. You should be able to use the Pandas library to perform various queries on this data. Try the following exercises:
Show all violations for “Alice Smith” (D001).
Hint: Joindrivers
→registrations
→violations
and filter wheredl_number == "D001"
.Find violations on cars older than 2018.
Hint: Joincars
→violations
and filter whereyear < 2018
.Which plates have zero recorded violations?
Hint: Anti-joinregistrations
(orcars
) againstviolations
.Count total violations per driver (include drivers with none).
Hint: Merge all tables, then.groupby("dl_number")
+.size()
(or.count()
).Compute average fine per driver, sorted descending.
Hint: Group bydl_number
and use.mean()
on thefine
column.For each car make (e.g. Ford, Toyota), what is the total number of violations?
Hint: Joincars
→violations
→ group bymake
and use.size()
.What’s the average fine by vehicle year?
Hint: Mergecars
→violations
, group byyear
, and use.mean()
onfine
.
import pandas as pd
from pandas import DataFrame
# — Driver info — (10 drivers)
= pd.DataFrame([
drivers "dl_number": "D001", "name": "Alice Smith", "age": 34},
{"dl_number": "D002", "name": "Bob Jones", "age": 28},
{"dl_number": "D003", "name": "Carol Diaz", "age": 45},
{"dl_number": "D004", "name": "David Lee", "age": 52},
{"dl_number": "D005", "name": "Eva Chen", "age": 23},
{"dl_number": "D006", "name": "Frank Moore", "age": 36},
{"dl_number": "D007", "name": "Grace Patel", "age": 41},
{"dl_number": "D008", "name": "Henry Zhao", "age": 29},
{"dl_number": "D009", "name": "Ivy Nguyen", "age": 50},
{"dl_number": "D010", "name": "Jack O'Connor", "age": 31},
{
])
# — Car registrations (DL → plate) — (15 registrations)
= pd.DataFrame([
registrations "dl_number": "D001", "plate": "ABC-123"},
{"dl_number": "D001", "plate": "XYZ-999"},
{"dl_number": "D002", "plate": "JKL-456"},
{"dl_number": "D003", "plate": "MNO-321"},
{"dl_number": "D004", "plate": "PQR-654"},
{"dl_number": "D005", "plate": "STU-111"},
{"dl_number": "D005", "plate": "VWX-222"},
{"dl_number": "D006", "plate": "YZA-333"},
{"dl_number": "D007", "plate": "BCD-444"},
{"dl_number": "D007", "plate": "EFG-555"},
{"dl_number": "D008", "plate": "HIJ-666"},
{"dl_number": "D009", "plate": "KLM-777"},
{"dl_number": "D009", "plate": "NOP-888"},
{"dl_number": "D010", "plate": "QRS-999"},
{
])
# — Car info (plate → make/model/year) — (14 cars)
= pd.DataFrame([
cars "plate": "ABC-123", "make": "Toyota", "model": "Camry", "year": 2018},
{"plate": "XYZ-999", "make": "Honda", "model": "Civic", "year": 2020},
{"plate": "JKL-456", "make": "Ford", "model": "Escape", "year": 2019},
{"plate": "MNO-321", "make": "Tesla", "model": "Model 3", "year": 2021},
{"plate": "PQR-654", "make": "Nissan", "model": "Altima", "year": 2017},
{"plate": "STU-111", "make": "Chevy", "model": "Malibu", "year": 2016},
{"plate": "VWX-222", "make": "Kia", "model": "Soul", "year": 2022},
{"plate": "YZA-333", "make": "BMW", "model": "X3", "year": 2015},
{"plate": "BCD-444", "make": "Audi", "model": "A4", "year": 2019},
{"plate": "EFG-555", "make": "Hyundai", "model": "Elantra", "year": 2020},
{"plate": "HIJ-666", "make": "Subaru", "model": "Outback", "year": 2018},
{"plate": "KLM-777", "make": "Ford", "model": "Focus", "year": 2017},
{"plate": "NOP-888", "make": "Mazda", "model": "CX-5", "year": 2021},
{"plate": "QRS-999", "make": "Chevy", "model": "Impala", "year": 2014},
{
])
# — Traffic violations (plate → violation) — (20 entries)
= pd.DataFrame([
violations "plate": "ABC-123", "date": "2025-06-01", "type": "speeding", "fine": 150},
{"plate": "ABC-123", "date": "2025-06-07", "type": "red_light", "fine": 200},
{"plate": "XYZ-999", "date": "2025-06-11", "type": "seatbelt", "fine": 75},
{"plate": "JKL-456", "date": "2025-06-05", "type": "parking", "fine": 40},
{"plate": "MNO-321", "date": "2025-06-09", "type": "speeding", "fine": 120},
{"plate": "PQR-654", "date": "2025-06-10", "type": "dui", "fine": 500},
{"plate": "STU-111", "date": "2025-06-12", "type": "speeding", "fine": 130},
{"plate": "VWX-222", "date": "2025-06-14", "type": "parking", "fine": 55},
{"plate": "YZA-333", "date": "2025-06-15", "type": "red_light", "fine": 250},
{"plate": "BCD-444", "date": "2025-06-16", "type": "speeding", "fine": 160},
{"plate": "EFG-555", "date": "2025-06-17", "type": "parking", "fine": 35},
{"plate": "HIJ-666", "date": "2025-06-18", "type": "seatbelt", "fine": 80},
{"plate": "KLM-777", "date": "2025-06-19", "type": "speeding", "fine": 140},
{"plate": "NOP-888", "date": "2025-06-20", "type": "dui", "fine": 600},
{"plate": "QRS-999", "date": "2025-06-21", "type": "parking", "fine": 45},
{"plate": "ABC-123", "date": "2025-06-22", "type": "speeding", "fine": 155},
{"plate": "ZZZ-000", "date": "2025-06-12", "type": "speeding", "fine": 130},
{"plate": "UNKNOWN", "date": "2025-06-23", "type": "red_light", "fine": 220},
{"plate": "NOP-888", "date": "2025-06-24", "type": "seatbelt", "fine": 85},
{"plate": "STU-111", "date": "2025-06-25", "type": "parking", "fine": 50},
{ ])
Problem 5: List Comprehension and Lambda Functions
Read about two advanced Python features we did not cover in class: - List comprehensions - Lambda functions
They are very useful for writing concise code, since they allow you to create lists and functions in a single line.
Write a list comprehension that builds a staircase pattern of the word “Staircases” with 10 steps, letter by letter.
- Example output:
['S', 'St', 'Sta', 'Stai', 'Stair', 'Stairc', 'Stairca', 'Staircas', 'Staircase', 'Staircases']
Write a lambda function that takes a list of numbers and returns a new list containing only the numbers from the original list that are divisible by 3.
Write a lambda function that takes a string and returns the string reversed. (e.g. “shalom” becomes “molahs”). Then, apply this function to the column of names in the
drivers
table to create a new column calledreversed_name
. (You can use theapply
method on a Pandas DataFrame to apply a function to each element in a column.)
Problem 6: Object-Oriented Programming (OOP) with Inheritance
Objective
Practice defining base classes, subclasses, method overriding, etc.
Build a mini sports‐league system. You’ll model TeamMember, Player, Coach, and Team, then extend with sport‐specific players.
Complete the class definitions below:
from typing import List
class TeamMember:
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
def role(self) -> str:
"""Return the member’s role name."""
...
class Player(TeamMember):
def __init__(self, name: str, age: int, position: str, number: int) -> None:
super().__init__(name, age)
self.position = position
self.number = number
def role(self) -> str:
...
def play(self) -> str:
"""Return a generic “is playing” message."""
...
class Coach(TeamMember):
def __init__(self, name: str, age: int, experience_years: int) -> None:
super().__init__(name, age)
self.experience_years = experience_years
def role(self) -> str:
...
def train(self, player: Player) -> str:
"""Return a training message."""
...
class Team:
def __init__(self, name: str) -> None:
self.name = name
self.members: List[TeamMember] = []
def add_member(self, member: TeamMember) -> None:
...
def lineup(self) -> List[str]:
"""List ‘Name – Role’ for each member."""
...
def game_day(self) -> None:
"""
For each Player, call play();
for each Coach, call train() on every Player.
Print each message.
"""
...
Once the methods are all defined, you can create instances of these classes and test the functionality.
Instantiate two teams, “HaPoel” and “Maccabi”. Try adding players and coaches to each team, and then print out the team lineups with .lineup()
and simulate a gameday preparation with .game_day()
.
Next: Define two subclasses of Player
: BasketballPlayer
and FootballPlayer
(European football, not American). Each subclass should have a unique play()
method that prints a sport-specific message. For example, BasketballPlayer
might print “Nailing a three-pointer!” while FootballPlayer
might print “Goooooooooal!”.
Problem 7: Functional vs. Object-Oriented Programming for team statistics
This exervise is designed to emphasize the differences between functional and object-oriented programming paradigms.
We’ll define a dataset with recorded game statistics for a team of players, and then implement two different approaches to compute the team’s statistical leaders: one using functional programming and the other using object-oriented programming.
= pd.DataFrame({
data "game_id": ["001", "001", "002", "002", "002"],
"team": ["HaPoel", "Maccabi", "HaPoel", "Maccabi", "HaPoel"],
"player": ["Messi", "Ronaldo", "Messi", "Wagner", "Neymar"],
"goals": [1, 2, 1, 0, 1],
"assists": [0, 1, 0, 2, 1],
"minutes_played": [90, 90, 90, 90, 90]
})
# compute the scoring leader for a given team
def compute_scoring_leader(data, team: str) -> str:
...
# compute the scoring leader for a given team using OOP
class TeamStats:
def __init__(self, data: pd.DataFrame, team: str) -> None:
...
def scoring_leader(self) -> str:
...