Split the trip bill fairly with Python
After a trip, one friend paid the hotel, another the scooters, someone else the dinner. Working out who owes whom on a napkin usually ends with someone paying twice.
This program adds up what everyone paid, works out each person's fair share and prints the payments that settle it. Type your friends' names below (comma separated) and press Run.
Who owes whom, settled in a few UPI payments.
The Python behind it · 32 lines
1friends = ["Aarav", "Diya", "Kabir", "Meera"] # who went on the trip23# Who paid for what on the Goa trip (₹)4paid = [5 (friends[0], "Hotel", 14400), (friends[1], "Scooters", 3600),6 (friends[2 % len(friends)], "Dinner at the shack", 4250),7 (friends[0], "Petrol", 1800), (friends[-1], "Cruise tickets", 6000),8 (friends[1], "Breakfast", 1350),9]1011total = sum(amount for _, _, amount in paid)12share = total / len(friends)13print(f"Trip total ₹{total:,} → ₹{share:,.0f} each\n")1415balance = {name: -share for name in friends}16for name, _, amount in paid:17 balance[name] += amount1819# Settle up: the person who owes most pays the person owed most, and repeat20owes = sorted([[b, n] for n, b in balance.items() if b < -1])21gets = sorted([[b, n] for n, b in balance.items() if b > 1], reverse=True)22payments = 023while owes and gets:24 pay = min(-owes[0][0], gets[0][0])25 print(f" {owes[0][1]:<8} pays {gets[0][1]:<8} ₹{pay:,.0f}")26 payments += 127 owes[0][0] += pay28 gets[0][0] -= pay29 if owes[0][0] > -1: owes.pop(0)30 if gets[0][0] < 1: gets.pop(0)3132print(f"\n✓ Everyone is square after {payments} UPI payment{'' if payments == 1 else 's'}")
How the code works, step by step
1.Record who paid for what
Each expense is (who paid, what for, amount). The names come from the box above, so the same code works for any group.
3# Who paid for what on the Goa trip (₹)4paid = [5 (friends[0], "Hotel", 14400), (friends[1], "Scooters", 3600),6 (friends[2 % len(friends)], "Dinner at the shack", 4250),7 (friends[0], "Petrol", 1800), (friends[-1], "Cruise tickets", 6000),8 (friends[1], "Breakfast", 1350),9]2.Work out the fair share
Add every amount with sum and a generator expression, then divide by the number of friends.
11total = sum(amount for _, _, amount in paid)12share = total / len(friends)13print(f"Trip total ₹{total:,} → ₹{share:,.0f} each\n")3.Find each person's balance
Everyone starts at minus their share, then gets back what they paid. A positive balance means the group owes you; a negative one means you owe the group.
15balance = {name: -share for name in friends}16for name, _, amount in paid:17 balance[name] += amount4.Settle up
Two sorted lists hold who owes and who is owed. The person who owes most pays the person owed most, as much as one of them needs, and whoever is settled leaves the list. The loop repeats until nobody is left.
19# Settle up: the person who owes most pays the person owed most, and repeat20owes = sorted([[b, n] for n, b in balance.items() if b < -1])21gets = sorted([[b, n] for n, b in balance.items() if b > 1], reverse=True)22payments = 023while owes and gets:24 pay = min(-owes[0][0], gets[0][0])25 print(f" {owes[0][1]:<8} pays {gets[0][1]:<8} ₹{pay:,.0f}")26 payments += 127 owes[0][0] += pay28 gets[0][0] -= pay29 if owes[0][0] > -1: owes.pop(0)30 if gets[0][0] < 1: gets.pop(0)3132print(f"\n✓ Everyone is square after {payments} UPI payment{'' if payments == 1 else 's'}")
Make it yours
- Let an expense be shared by only some friends (not everyone came to dinner).
- Read the expenses from a Google Sheet export.
- Print a UPI-ready message for each payment.
Questions
- Does this always find the fewest possible payments?
- Not always. It pairs the biggest debts with the biggest credits, which settles any group in at most one payment fewer than the number of people, and is usually close to the minimum. Finding the true minimum for large groups is a much harder problem.
- Why does the code ignore balances under ₹1?
- Dividing money can leave fractions of a rupee. Treating anything under ₹1 as settled stops the loop from chasing paise.