← Computer Programming I

Quick reference

Defining and calling a function

def greet():
    print("Hello")

greet()
  • Use def to define a function.
  • Put : after ) and indent the code inside the function. This code is the function body.
  • Defining a function does not run its body. Calling it runs the body.
  • Python must run the function definition before you can call the function.

Parameters and arguments

def rectangle_area(width, height):
    return width * height

area = rectangle_area(4, 3)
  • Parameters are the names in the function definition: width and height.
  • Arguments are the values you give to a function when you call it: 4 and 3.
  • Here, the order matters: width gets 4, and height gets 3.

Returning a value

def double(number):
    return number * 2

result = double(5)
print(result)            # 10
print(double(5) + 3)     # 13
  • return ends the function call and sends a value back to the code that called it.
  • You can store this value in a variable or use it in an expression.
  • print() shows a value on the screen. It does not return the value it shows.
  • If a function reaches its end without running return, it returns None.
  • return on its own also returns None.

Decisions inside functions

def result_message(score):
    if score >= 50:
        return "Pass"
    return "Try again"

The function ends as soon as a return runs. If your code needs a result, make sure the function returns one for every case.

Local variables

def add_one(number):
    result = number + 1
    return result

number = 10
answer = add_one(number)
print(number)            # 10
print(answer)            # 11
  • Parameters and variables created inside these functions are local: their names belong to that function call.
  • The number inside the function and the number outside it are separate names.
  • Giving a new value to number inside the function does not change number outside it.
  • Use return to send a result back to the code that called the function.

Pure functions

def total_minutes(hours, minutes):
    return hours * 60 + minutes

A pure function always returns the same result when you give it the same arguments. It has no side effects: for example, it does not print output or change data outside the function.

Keep input and output separate from the calculation:

hours = int(input("Enter hours: "))
minutes = int(input("Enter minutes: "))
total = total_minutes(hours, minutes)
print(f"Total minutes: {total}")

Docstrings

def square(number):
    """Return the square of the given number."""
    return number * number

A docstring explains what a function does. Write it as the first statement inside the function, between triple quotes (""").

Checks with assert

assert square(3) == 9
assert square(0) == 0
assert square(-2) == 4
  • assert checks a condition.
  • If the condition is True, the program continues without printing anything.
  • If it is False, Python reports an AssertionError.
  • Check common values and values at a boundary, such as 49 and 50 when the pass mark is 50.

Decomposition

Decomposition means breaking a problem into smaller tasks. Give each task a name, such as:

  1. Read the input.
  2. Calculate the result.
  3. Print the result.

Give each function a clear task. Decide what arguments it needs and what value it should return.


Problem 1: Say hello

Write a function named greet with one parameter, name. The function should print a greeting using that name.

Call the function twice: once with "Aziza" and once with "Bekzod".

Expected output

Hello, Aziza!
Hello, Bekzod!

Problem 2: Age in months

Write a function named age_in_months with one parameter, years. The function should return the number of months in that many years.

Assume each year has 12 months.

Call the function with 18, 5, and 0. Print each returned value outside the function.

Expected output

216
60
0

Problem 3: Money left

Write a function named money_left with two parameters:

  • money: how much money you have;
  • price: how much you spend.

The function should return how much money remains. Assume money and price are non-negative and you have enough money.

Use these calls and print each returned value outside the function:

money_left(50000, 18000)
money_left(20000, 20000)
money_left(10000, 0)

Expected output

32000
0
10000

Problem 4: Bus fare

Write a function named bus_fare with one parameter, age.

The function should return:

  • 0 if the passenger is younger than 7;
  • 2000 otherwise.

Assume age is a non-negative integer.

Use these calls and print each returned value outside the function:

bus_fare(4)
bus_fare(7)
bus_fare(18)

Expected output

0
2000
2000

Problem 5: In range

Write a function named is_in_range with three parameters: number, lower, and upper.

The function should return True if number is between lower and upper, including both ends. Otherwise, return False.

Assume lower is less than or equal to upper.

Check your function using these assertions:

assert is_in_range(5, 1, 10) == True
assert is_in_range(1, 1, 10) == True
assert is_in_range(10, 1, 10) == True
assert is_in_range(0, 1, 10) == False
assert is_in_range(11, 1, 10) == False

Problem 6: Alarm message

Write a function named alarm_message with two parameters:

  • hour: a whole number from 0 to 23;
  • is_weekend: either True or False.

The function should return:

  • "Sleep in" if it is the weekend, whatever the hour;
  • "Get up" if it is not the weekend and the hour is 7 or later;
  • "Too early" otherwise.

Add a short docstring and check your function using these assertions:

assert alarm_message(6, False) == "Too early"
assert alarm_message(7, False) == "Get up"
assert alarm_message(9, False) == "Get up"
assert alarm_message(6, True) == "Sleep in"
assert alarm_message(9, True) == "Sleep in"

Problem 7: Cinema tickets

A cinema uses these ticket prices:

  • children younger than 12: 20000 so‘m;
  • everyone aged 12 or older: 35000 so‘m.

Write two functions:

  1. ticket_price(age) — return the ticket price for one person.
  2. total_price(first_age, second_age) — call ticket_price for each person and return the total price.

Assume both ages are non-negative integers. Add a short docstring to each function.

Check your functions:

assert ticket_price(11) == 20000
assert ticket_price(12) == 35000
assert total_price(8, 10) == 40000
assert total_price(8, 20) == 55000
assert total_price(20, 8) == 55000
assert total_price(18, 25) == 70000

Then write a program that reads two ages and prints the total price. Keep input() and print() outside both functions.

Example

Enter the first age: 8
Enter the second age: 20
Total price: 55000 so‘m

Problem 8: Parking fee

A car park charges for each hour started. For example, 61 minutes counts as 2 hours.

The prices are:

  • 0 minutes: no charge;
  • the first hour: 5000 so‘m;
  • each additional hour: 3000 so‘m.

Write two functions:

  1. hours_to_pay(minutes) — return the number of hours to pay for. Use // and % to count full hours and check for remaining minutes.
  2. parking_fee(minutes) — use hours_to_pay and return the total fee.

Assume minutes is a non-negative integer. Add a short docstring to each function.

Check your functions:

assert hours_to_pay(0) == 0
assert hours_to_pay(60) == 1
assert hours_to_pay(61) == 2

assert parking_fee(0) == 0
assert parking_fee(1) == 5000
assert parking_fee(60) == 5000
assert parking_fee(61) == 8000
assert parking_fee(125) == 11000

Then read the number of minutes from the user and print the fee. Keep input() and print() outside both functions.

Example

Enter parking time in minutes: 125
Parking fee: 11000 so‘m

Problem 9: Is this date valid?

Write a program that checks whether a day, month, and year form a valid date.

Write three functions:

  1. is_leap_year(year) — return True if the year is a leap year, or False otherwise.
  2. days_in_month(month, year) — use is_leap_year when needed and return the number of days in the month. Assume the month is from 1 to 12.
  3. is_valid_date(day, month, year) — return True if the date is valid, or False otherwise. Use days_in_month, but only after checking the year and month.

A valid date must have:

  • a year greater than 0;
  • a month from 1 to 12;
  • a day from 1 to the number of days in that month.

The month lengths are:

  • 30 days: April (4), June (6), September (9), November (11);
  • 31 days: all other months except February;
  • February (2): 29 days in a leap year, otherwise 28.

A year is a leap year if it is divisible by 400, or if it is divisible by 4 but not by 100.

Check your functions:

assert is_leap_year(2000) == True
assert is_leap_year(1900) == False
assert days_in_month(2, 2024) == 29
assert days_in_month(4, 2026) == 30

assert is_valid_date(29, 2, 2024) == True
assert is_valid_date(29, 2, 2026) == False
assert is_valid_date(31, 4, 2026) == False
assert is_valid_date(0, 1, 2026) == False
assert is_valid_date(15, 13, 2026) == False
assert is_valid_date(1, 1, 0) == False

Then read a day, month, and year from the user and print Valid date or Invalid date. Assume the user enters integers.

Example

Enter the day: 29
Enter the month: 2
Enter the year: 2026
Invalid date

Problem 10: Time for a meeting

Two students want to work together. Each student has a free period during the same day.

Times are given as minutes after midnight. For example, 540 means 09:00, and 600 means 10:00.

Write two functions:

  1. overlap_minutes(start1, end1, start2, end2) — return the number of minutes when both students are free. Return 0 if their free periods do not overlap.
  2. can_meet(start1, end1, start2, end2, duration) — use overlap_minutes and return whether they have enough shared time for a meeting of duration minutes.

Assume:

  • all times are integers from 0 to 1440;
  • each start time is earlier than its end time;
  • duration is a positive integer.

If one free period ends exactly when the other starts, they have 0 shared minutes.

Example

The first student is free from 09:00 to 11:00. The second is free from 10:00 to 12:00.

They are both free from 10:00 to 11:00: 60 minutes.

Checks

# Partly overlapping periods
assert overlap_minutes(540, 660, 600, 720) == 60

# One period is inside the other
assert overlap_minutes(540, 720, 600, 660) == 60

# Same periods
assert overlap_minutes(540, 600, 540, 600) == 60

# Periods that touch or are separate
assert overlap_minutes(540, 600, 600, 660) == 0
assert overlap_minutes(540, 600, 660, 720) == 0

# The second student is free earlier
assert overlap_minutes(600, 720, 540, 660) == 60

assert can_meet(540, 660, 600, 720, 60) == True
assert can_meet(540, 660, 600, 720, 61) == False

Add two more assertions of your own: one where can_meet returns True and one where it returns False.


Problem 11: Packing an order

A shop packs cups into two sizes of boxes:

  • a large box holds exactly 6 cups;
  • a small box holds exactly 4 cups.

Every box used must be full. The shop has a limited number of each size. You do not have to use all available boxes.

Write two functions:

  1. minimum_boxes(cups, large_available, small_available) — return the smallest number of boxes needed to pack exactly cups cups. Return -1 if this is impossible.
  2. can_pack(cups, large_available, small_available) — use minimum_boxes and return True if the order can be packed, or False otherwise.

Assume all arguments are non-negative integers. Packing 0 cups needs 0 boxes.

Example

An order contains 18 cups. The shop has 2 large boxes and 3 small boxes.

Using both large boxes leaves 6 cups, which cannot fill small boxes exactly. Using 1 large box and 3 small boxes packs all 18 cups.

The result is 4 boxes.

Checks

assert minimum_boxes(18, 3, 0) == 3
assert minimum_boxes(18, 2, 3) == 4
assert minimum_boxes(20, 2, 2) == 4
assert minimum_boxes(8, 2, 0) == -1
assert minimum_boxes(8, 0, 2) == 2
assert minimum_boxes(7, 5, 5) == -1
assert minimum_boxes(0, 0, 0) == 0

assert can_pack(18, 2, 3) == True
assert can_pack(8, 2, 0) == False

Add two more assertions of your own.


Problem 12: Split the bill

Three friends share a restaurant bill equally. Each friend has a limited amount of money.

If a friend cannot pay their share, they pay all the money they have. The other two split the remaining amount equally. If one of them cannot pay that new share, the last friend pays what remains.

For example, the bill is 90000 so‘m:

  • Aziza has 10000 so‘m.
  • Bekzod has 50000 so‘m.
  • Dilshod has 100000 so‘m.

Each person’s first share is 30000. Aziza can pay only 10000, so Bekzod and Dilshod each pay 40000.

Write a function named payment_for_first with four parameters:

  • bill: the total bill;
  • first_money: the first friend’s available money;
  • second_money: the second friend’s available money;
  • third_money: the third friend’s available money.

The function should return how much the first friend pays. Return -1 if the three friends do not have enough money in total.

Assume all arguments are non-negative numbers. Use ordinary division; you do not need to round the results.

Divide your solution into smaller functions where useful.

Checks

# Everyone can pay an equal share
assert payment_for_first(90000, 50000, 50000, 50000) == 30000

# The first friend cannot pay an equal share
assert payment_for_first(90000, 10000, 50000, 100000) == 10000

# Another friend cannot pay an equal share
assert payment_for_first(90000, 50000, 10000, 100000) == 40000

# Two friends have too little money
assert payment_for_first(90000, 100000, 10000, 20000) == 60000

# Not enough money in total
assert payment_for_first(90000, 20000, 20000, 20000) == -1

# No bill to pay
assert payment_for_first(0, 10000, 20000, 30000) == 0

Add a check where one friend can afford the first equal share but cannot afford the larger share after another friend pays less.


Problem 13: Pouring water

You have three bottles: A, B, and C. Each bottle has a capacity and a starting amount of water, measured in millilitres.

Pour water in this order:

  1. From A into B.
  2. From B into C.
  3. From C into A.

At each step, pour as much as possible. Stop when the source bottle is empty or the receiving bottle is full. No water is spilled.

Write two functions:

  1. pour_amount(source_water, destination_water, destination_capacity) — return how much water can be poured.
  2. water_in_a(capacity_a, capacity_b, capacity_c, water_a, water_b, water_c) — use pour_amount for each step and return the amount of water in A after all three steps.

Each step must use the amounts left after the previous step.

Assume all arguments are integers, capacities are positive, and each starting amount is between 0 and that bottle’s capacity.

Example

The capacities are:

  • A: 800 ml;
  • B: 500 ml;
  • C: 300 ml.

At the start, A contains 800 ml, and B and C are empty.

Step Water in A Water in B Water in C
Start 800 0 0
A → B 300 500 0
B → C 300 200 300
C → A 600 200 0

The function returns 600.

Checks

# The source can be emptied
assert pour_amount(200, 100, 500) == 200

# The receiving bottle fills first
assert pour_amount(600, 100, 500) == 400

# The receiving bottle is already full
assert pour_amount(200, 500, 500) == 0

assert water_in_a(800, 500, 300, 800, 0, 0) == 600
assert water_in_a(500, 800, 300, 500, 0, 0) == 300

# All bottles start full
assert water_in_a(800, 500, 300, 800, 500, 300) == 800

# All bottles start empty
assert water_in_a(800, 500, 300, 0, 0, 0) == 0

Add a check where all three bottles start partly full. Trace the three pours to find the expected answer before running your code.