ShareYourGroupShareYourGroupPython

Small project 3 of 4

Bill splitter for friends

A group eats out, one person pays, and then the sums begin. This project builds a small tool for that, in three stages: an equal split, a split by what each person ordered, and a list of who should pay whom. It uses numbers, dictionaries, functions and formatting.

Stage 1: equal split

def split_equally(amount, people, tip_percent=0):
    total = amount + amount * tip_percent / 100
    return round(total / people, 2)

print(split_equally(1840, 4))
print(split_equally(1840, 4, tip_percent=10))

Output

460.0
506.0

Rounding to two places keeps the answer in rupees and paise. Because of rounding, the shares may add up to a paisa or two more or less than the bill. The next block shows how to check.

share = round(1000 / 3, 2)
print(share, share * 3)

Output

333.33 999.99

A real app gives the leftover paisa to one person. For friends, rounding each share up to the next rupee is simpler.

import math
print(math.ceil(1000 / 3))

Output

334

Stage 2: each pays for their own order

Now store what each person ordered. A dictionary maps a name to a list of prices.

orders = {
    "Asha": [220, 60],
    "Ravi": [340],
    "Meena": [180, 60, 90],
}
for name, items in orders.items():
    print(f"{name:<6}{sum(items):>6}")
print("Food total:", sum(sum(items) for items in orders.values()))

Output

Asha     280
Ravi     340
Meena    330
Food total: 950

Tax and service charge are usually a percentage of the food, so each person should carry them in proportion to what they ate. Work out one multiplier and apply it to everyone.

def shares(orders, extra_percent):
    factor = 1 + extra_percent / 100
    return {name: round(sum(items) * factor, 2) for name, items in orders.items()}

orders = {"Asha": [220, 60], "Ravi": [340], "Meena": [180, 60, 90]}
result = shares(orders, extra_percent=5)
for name, amount in result.items():
    print(f"{name:<6}{amount:>8.2f}")
print(f"{'Total':<6}{sum(result.values()):>8.2f}")

Output

Asha    294.00
Ravi    357.00
Meena   346.50
Total   997.50

The function body is a dictionary comprehension from lesson 20. It builds a new dictionary with the same names and the adjusted amounts.

Shared dishes

Some dishes are shared by the whole table. Split those equally and add them to each person's own items.

def shares(orders, shared, extra_percent):
    factor = 1 + extra_percent / 100
    each = sum(shared) / len(orders)
    return {name: round((sum(items) + each) * factor, 2) for name, items in orders.items()}

orders = {"Asha": [220], "Ravi": [340], "Meena": [180, 90]}
result = shares(orders, shared=[450, 120], extra_percent=5)
print(result)

Output

{'Asha': 430.5, 'Ravi': 556.5, 'Meena': 483.0}

Stage 3: who owes whom

Suppose different people paid for different things during a trip. First find each person's balance: what they paid minus the fair share. A positive balance means the group owes them money.

paid = {"Asha": 2400, "Ravi": 0, "Meena": 600}
fair = sum(paid.values()) / len(paid)
balance = {name: amount - fair for name, amount in paid.items()}
print(fair)
print(balance)

Output

1000.0
{'Asha': 1400.0, 'Ravi': -1000.0, 'Meena': -400.0}

Then settle. Take the person who owes the most and the person who is owed the most, move as much as possible between them, and repeat until everyone is at zero.

def settle(paid):
    fair = sum(paid.values()) / len(paid)
    balance = {name: round(amount - fair, 2) for name, amount in paid.items()}
    payments = []
    while True:
        debtor = min(balance, key=balance.get)
        creditor = max(balance, key=balance.get)
        amount = round(min(-balance[debtor], balance[creditor]), 2)
        if amount < 0.01:
            break
        payments.append(f"{debtor} pays {creditor} Rs {amount:.2f}")
        balance[debtor] += amount
        balance[creditor] -= amount
    return payments

for line in settle({"Asha": 2400, "Ravi": 0, "Meena": 600, "Kabir": 1000}):
    print(line)

Output

Ravi pays Asha Rs 1000.00
Meena pays Asha Rs 400.00

This loop always ends, because every round brings at least one person's balance to zero.

Things to notice

Ideas to extend it

Exercise 1. Write split_with_cap(amount, people) that rounds each share up to the next 10 rupees. Test it with 1840 and 3 people.

Show one answer
import math

def split_with_cap(amount, people):
    return math.ceil(amount / people / 10) * 10

print(split_with_cap(1840, 3))

Output

620

Examples on this page were run with Python 3.14 on 12 November 2026. The output shown is the real output.

This is an independent learning site. It is not connected with or approved by the Python Software Foundation. "Python" is a trademark of the Python Software Foundation and is used here only to name the language.