Who paid what, everyone's share and the payments that settle it.
/build/project-trip-bill-splitter with the starter and the rubric already in it.Take a list of trip expenses and the friends who went, work out each person's fair share and balance, then print the payments that make everyone square.
Splitting a bill is a real problem with real edge cases: someone who paid nothing, shares that don't divide evenly, and turning balances into actual payments. Six small functions, each checked on its own.
You can model real data with tuples and dicts, keep money to 2 decimals and turn a messy situation into a clear plan.
Each step is one function in trip_split.py. In the workspace, press Check next to a step: it runs your file and tells you exactly what is still wrong. Step 1 is free; the rest are part of Pro or your 7-day free trial.
Build against this exact list — it is the spec your published project is judged on.
Copy this into a new file — or open it in a workspace as trip_split.py. The TODO parts are yours to fill.
"""
Trip bill splitter.
Works out what every friend owes after a trip and prints the payments
that settle it. Fill in one function per step, press Run, then press
"Check" on that step in the Checkpoints panel.
"""
FRIENDS = ["Aarav", "Diya", "Kabir", "Meera"]
# (who paid, what for, amount in ₹)
EXPENSES = [
("Aarav", "Hotel", 14400),
("Diya", "Scooters", 3600),
("Kabir", "Dinner at the shack", 4250),
("Aarav", "Petrol", 1800),
("Meera", "Cruise tickets", 6000),
("Diya", "Breakfast", 1350),
]
def total_spent(expenses: list[tuple[str, str, int]]) -> int:
# TODO: add up the amount (the third item) of every expense.
raise NotImplementedError("step 1, total_spent(): add up every expense")
def fair_share(expenses: list[tuple[str, str, int]], friends: list[str]) -> float:
# TODO: the total divided by the number of friends, rounded to 2 decimals.
raise NotImplementedError("step 2, fair_share(): total divided by the number of friends")
def paid_by(expenses: list[tuple[str, str, int]], friends: list[str]) -> dict[str, int]:
# TODO: a dict of name -> how much that friend paid in total.
# Every friend must be in it, even someone who paid nothing (0).
raise NotImplementedError("step 3, paid_by(): how much each friend paid")
def balances(expenses: list[tuple[str, str, int]], friends: list[str]) -> dict[str, float]:
# TODO: name -> what they paid minus the fair share, rounded to 2 decimals.
# Positive: the group owes them. Negative: they owe the group.
raise NotImplementedError("step 4, balances(): paid minus fair share")
def settle(balance: dict[str, float]) -> list[tuple[str, str, float]]:
# TODO: return a list of (payer, receiver, amount) that makes everyone 0.
# One way: the person who owes most pays the person owed most, as much
# as one of them needs; whoever reaches 0 drops out; repeat.
raise NotImplementedError("step 5, settle(): the payments that make everyone square")
def main() -> None:
total = total_spent(EXPENSES)
print(f"Trip total ₹{total:,} → ₹{fair_share(EXPENSES, FRIENDS):,.0f} each")
print("Paid: " + ", ".join(f"{n} ₹{a:,}" for n, a in paid_by(EXPENSES, FRIENDS).items()))
plan = settle(balances(EXPENSES, FRIENDS))
# TODO: print one line per payment, like "Kabir pays Aarav ₹3,600",
# then "Everyone is square after 3 payments".
raise NotImplementedError("step 6, main(): print the payment plan")
if __name__ == "__main__":
try:
main()
except NotImplementedError as todo:
# A fresh starter is SUPPOSED to stop here. Say which step is next
# instead of printing a traceback that looks like a bug.
print(f"Not built yet: {todo}")
print("Write that function, then press Run again. Each step you finish moves this message forward.")
trip_split.py and a README.md holding all 5 rubric items as a checklist.pyrun.in/u/<handle>/w/project-trip-bill-splitter.pyrun.in/u/<handle> portfolio page.Your workspace saves to this browser only. Sign in to keep it across devices and to publish it.
Flip the workspace to Public and paste its URL below, or push the file to a GitHub gist or repo.
A published PyRun workspace URL (pyrun.in/u/<handle>/w/project-trip-bill-splitter) works as the public URL too.