Python Quest

Track 2 · Lesson 11 of 11

Mini project: restaurant bill splitter

Build a restaurant bill splitter step by step: read dish prices, add VAT and a tip, split the total fairly and print an aligned summary.

About 50 minIntermediate5 exercisesFree

You will be able to

  • Plan a small program as a sequence of inputs, calculations and outputs
  • Combine input conversion, arithmetic, constants and rounding in one program
  • Find and fix a calculation bug from its symptom
  • Handle awkward input such as extra spaces, one diner and a zero tip
  • Produce a neatly aligned summary with f-string format specifications

Four colleagues finish lunch at a restaurant. The bill lists the dishes, the 15% VAT still has to be added, they want to leave a tip, and everyone wants to know exactly what to pay. Someone opens a calculator app, someone else gets a different answer, and the waiter waits.

In this project you'll write the program that settles it. You will build it in five milestones, each one a working program that the next one extends. Along the way you'll use almost everything from this track: converting input, arithmetic, a constant, rounding money, splitting a line of input, and aligned f-string output.

The plan

Before writing code, describe the program in three parts:

PartWhat happens
Inputdish prices, the tip percentage, the number of people
Calculationsubtotal = sum of prices; VAT = subtotal × 15%; tip = subtotal × tip% ; total = subtotal + VAT + tip; each person = total ÷ people
Outputa summary with every amount shown to two decimal places

Two decisions matter for money. First, the tip is calculated on the subtotal (before VAT), which is how the restaurant in this project does it. Second, you keep full precision in the calculations and round only the amounts you show or charge. Rounding in the middle of a calculation lets small errors pile up.

The whole calculation on fixed numbers, before any input
VAT_RATE = 0.15

subtotal = 45 + 62.5 + 32.5
vat = subtotal * VAT_RATE
tip = subtotal * 10 / 100
total = subtotal + vat + tip
each = round(total / 4, 2)

print("Subtotal:", subtotal)
print("VAT:", vat)
print("Tip:", tip)
print("Total:", total)
print("Each:", each)

Try it: Change the 4 to 3 people. Then multiply each by 3 in a new print() line: does it give back the total exactly?

Milestone 1: the subtotal

Start with the input side. The waiter reads out three dish prices, one per line. Each arrives as a string, so convert each one with float() — prices can have halalas (decimals).

Guided practice · ●difficulty 1 of 5 · about 5 min

Milestone 1: add up the dishes

Read three dish prices, one per line, with input() (no prompt text — the tests type the values for you). Convert each to a float, store their sum in subtotal, and print it with two decimal places.

For the prices 48.50, 62 and 29.75 the output is:

Subtotal: 140.25 SAR

Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.

Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type

Output

Run your code to see its output, or Check to test it against the requirements.

The solution becomes available after you pass, or after all three hints and two checks.

Milestone 2: VAT and tip

The VAT rate is the same for every bill, so it belongs in a constant: an UPPER_CASE name set once at the top (see Naming and readability). If the rate ever changes, you edit one line. The tip percentage changes from table to table, so it is read as input.

Challenge · ●●difficulty 2 of 5 · about 7 min

Milestone 2: add VAT and a tip

Read the subtotal (a decimal number) and then the tip percentage (a whole number) with input(), one per line, with no prompt text.

  • Define a constant VAT_RATE = 0.15 at the top.
  • vat is the subtotal times VAT_RATE.
  • tip is the tip percentage of the subtotal (not of the subtotal plus VAT).
  • total is subtotal + VAT + tip.

Print four lines, every amount with two decimals. For a subtotal of 240 and a tip of 10:

Subtotal: 240.00 SAR
VAT (15%): 36.00 SAR
Tip (10%): 24.00 SAR
Total: 300.00 SAR

The percentage in the tip line is the number that was typed.

Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.

Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type

Output

Run your code to see its output, or Check to test it against the requirements.

The solution becomes available after you pass, or after all three hints and two checks.

Milestone 3: splitting the total

Dividing the total between people needs true division, /, and the result has to be rounded to halalas. Remember from Float precision and rounding that rounding can leave a tiny gap: 100 SAR split three ways is 33.33 each, which only adds up to 99.99. Restaurants usually accept that one halala difference.

Debugging · ●●difficulty 2 of 5 · about 6 min

Milestone 3: fix the per-person amount

A teammate wrote the splitting step. It reads the total and the number of people, one per line. Diners complain about what it shows:

  • a total of 100 split between 3 people shows Each person pays: 33.0 SAR — that is too little, it should be 33.33;
  • a total of 250 split between 4 shows Each person pays: 62.0 SAR instead of 62.50.

Fix the program so that per_person holds the share rounded to 2 decimal places and the last line always shows two decimals. Keep the other lines as they are.

Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.

Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type

Output

Run your code to see its output, or Check to test it against the requirements.

The solution becomes available after you pass, or after all three hints and two checks.

Milestone 4: real-world input

Typing each value on its own line is slow. A quicker way is to type everything on one line, such as 300 4 10 for subtotal, people and tip. People are not careful typists, though: some add extra spaces, some eat alone, some leave no tip. split() with no argument splits on any run of spaces and ignores spaces at the ends, which makes it the right tool here (as you saw in Processing input).

Edge cases · ●●●difficulty 3 of 5 · about 7 min

Milestone 4: one line, messy spacing

Read one line with input() (no prompt text) that holds three values separated by spaces: the subtotal (decimal), the number of people (whole number) and the tip percentage (whole number), for example 300 4 10. The line may contain extra spaces anywhere, such as " 120 1 0 ".

Using a constant VAT_RATE = 0.15 and the tip calculated on the subtotal, store each person's share, rounded to 2 decimal places, in per_person, and print one line:

Each of 4 pays 93.75 SAR

(300 + 45 VAT + 30 tip = 375, split 4 ways.) For 120 1 0 the output is Each of 1 pays 138.00 SAR.

Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.

Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type

Output

Run your code to see its output, or Check to test it against the requirements.

The solution becomes available after you pass, or after all three hints and two checks.

Milestone 5: the printed summary

The last step is presentation. A summary is easier to check when labels line up on the left and amounts line up on the right, like a till receipt. Width and alignment specifications from f-strings and formatting do this: {'Total':<14} pads a label to 14 characters on the left side, and {total:>12.2f} right-aligns a number in 12 characters with two decimals.

Two aligned rows
subtotal = 140.0
people = 4
print(f"{'Subtotal':<14}{subtotal:>12.2f}")
print(f"{'People':<14}{people:>12}")
print("=" * 26)

Try it: Change < to > in the first f-string and run it. Which way reads better on a receipt?

Milestone · ●●●difficulty 3 of 5 · about 12 min

Milestone 5: the complete bill splitter

Put everything together. The program reads three lines with input() (no prompt text):

  1. three dish prices on one line, separated by spaces (extra spaces possible), e.g. 45 62.5 32.5
  2. the tip percentage, a whole number, e.g. 10
  3. the number of people, a whole number, e.g. 4

Use VAT_RATE = 0.15, calculate the tip on the subtotal, keep full precision in subtotal, vat, tip and total, and store each person's share rounded to 2 places in each_person. Then print this summary. Each row is a label left-aligned in 14 characters followed by a value right-aligned in 12 characters; amounts have two decimals and the number of people is a whole number. The line of = signs is 26 characters long.

BILL SUMMARY
==========================
Subtotal            140.00
VAT 15%              21.00
Tip 10%              14.00
Total               175.00
People                   4
Each person          43.75
==========================

The tip label shows the percentage that was typed (Tip 12%, Tip 0%).

Python code editor. Tab indents. Press Escape then Tab to leave the editor. Control or Command plus Enter runs the code; Shift plus Enter checks your answer.

Ctrl+Enter run · Shift+Enter check · your code is saved in this browser as you type

Output

Run your code to see its output, or Check to test it against the requirements.

The solution becomes available after you pass, or after all three hints and two checks.

Summary

  • A program is easier to write when you plan it as input, calculation and output first.
  • Constants such as VAT_RATE name fixed values; percentages typed by a user are divided by 100.
  • Use true division for money, keep full precision while calculating, and round only the amounts you show or charge.
  • split() with no argument copes with any spacing, and each piece still needs converting with float() or int().
  • Matching width and alignment specifications, like <14 and >12.2f, turn a list of numbers into a readable summary.