In-Class#
Coding Practice#
Code 5.1: Next Even Number#
You should write a function next_even
that takes an integer n
as input and returns the next even number. That is, if n
is even, the function should return the even number that is 2
greater than n
. If n
is odd, the function should return the even number that is 1
greater than n
. The function should work for both positive and negative integers.
Look at the following code:
def next_even(n):
return 0
test1 = next_even(5) == 6
test2 = next_even(-5) == -4
test3 = next_even(6) == 8
test4 = next_even(-6) == -4
test5 = next_even(0) == 2
test6 = next_even(-1) == 0
all_tests_passed = test1 and test2 and test3 and test4 and test5 and test6
print("All tests passed:", all_tests_passed)
if not all_tests_passed:
print("Individual test results:", test1, test2, test3, test4, test5, test6)
The code contains a placeholder function that always returns 0
and is clearly not correct. However, it includes good test cases for the function next_even
. This is to show that you can write test cases before writing the function.
Now, write the function next_even
so that it passes the tests.
Code 5.2: Instructions for the Next Two Exercises#
Writing tests for functions often involves just as much work as writing the functions themselves and is just as important. For the next two problems, we suggest that you find a buddy and test each other’s functions. Do the following:
Divide the tasks between you:
One student should write the function
sign_text
in the filesign_text.py
and the test fornumber_digits
in the filenumber_digits_test.py
. This student should not create a solution for thenumber_digits
function but may include a placeholder solution that always returns the same value.The second student should write the function
number_digits
in the filenumber_digits.py
and the test forsign_text
in the filesign_text_test.py
. This student should not create a solution for thesign_text
function, but it is okay to place a placeholder solution that always returns the same value.
Send the files to each other, so that you both have all four files, and place these four files in the same folder.
Use two different testing strategies:
Test the
sign_text
function by placing the test code and the function definition in the same file and executing this file.Test the
number_digits
function by importing the function into the test file and running the test file. That is, you should writefrom number_digits import number_digits
in the first line of the test file. This will allow you to call the function
number_digits
in the test file.
If your functions do not pass the tests, debug them together. The bugs can be in the function or in the test.
You can use the same testing strategy for other exercises as well.
Code 5.3: Sign Text#
We often need to determine whether a number is positive, negative, or zero. Write a function sign_text
that takes a number as input and returns a string 'positive'
, 'negative'
, or 'zero'
based on the sign of the number.
The test for this function should contain at least six different numbers, including positive, negative, and zero, both integers and floats.
Code 5.4: Number of Digits#
We often need to determine the number of digits in an integer. Write a function number_digits
that takes a positive integer as input and returns the number of digits in the number.
The test for this function should contain at least six different positive integers with varying numbers of digits.
Hint
You can convert the integer to a string and then use the len
function.
Code 5.5: Customized Greeting#
We need a function customized_greeting
that constructs a polite greeting depending on the time of day and customized to a specific person. The function should take two arguments: name
and hour
.
The argument name
is a string containing the name of the person. The argument hour
is the hour of the day given in 24-hour format, so it is an integer between 0 and 23.
The greeting should start with:
'Good morning'
for all hours between 7 and 11.'Good afternoon'
for all hours between 12 and 17.'Good evening'
for all hours between 18 and 22.'Good night'
for all other values ofhour
.
The greeting should be followed by a comma, the name of the person, and an exclamation mark.
For example, customized_greeting('Alice', 8)
should return 'Good morning, Alice!'
.
Hint
To test your solution, you may copy the following code into the same file as your solution. If the message says that your code passes all tests, this is an indication (but not a guarantee!) that your solution is correct.
test1 = customized_greeting("John", 6) == "Good night, John!"
test2 = customized_greeting("Nanna", 11) == "Good morning, Nanna!"
test3 = customized_greeting("Elise", 12) == "Good afternoon, Elise!"
test4 = customized_greeting("Anton", 20) == "Good evening, Anton!"
test5 = customized_greeting("Laura", 22) == "Good evening, Laura!"
test6 = customized_greeting("Mikkel", 23) == "Good night, Mikkel!"
test7 = customized_greeting("Sasha", 0) == "Good night, Sasha!"
test8 = customized_greeting("Olivia", 7) == "Good morning, Olivia!"
all_tests_passed = test1 and test2 and test3 and test4 and test5 and test6 and test7 and test8
print("All tests passed:", all_tests_passed)
# Uncomment to see the results of individual tests
# print(test1, test2, test3, test4, test5, test6, test7, test8)
Code 5.6: Disc Area and Sphere Surface Area#
The area of a disc is given by the formula \(A = \pi r^2\), and the surface area of a sphere is given by the formula \(S = 4 \pi r^2\).
Write two functions disc_area
and sphere_surface_area
that take the radius of a disc and a sphere as input and return the area of the disc and the surface area of the sphere, respectively. Use math.pi
as the value of \(\pi\), and remember to import the math
module. Can you write sphere_surface_area
in a way such that it uses (calls) disc_area
? Test your functions.
Hint
You can use the following code to test your solution by comparing the expected output with the output of your function. This is only an indication (but not a guarantee!) that your solution is correct. For example, if you made a mistake and returned a string instead of a number, you would not notice this mistake by looking at the output.
print("Radius 1, expected disc area: 3.141592653589793, got:", disc_area(1))
print("Radius 1, expected sphere surface area: 12.566370614359172, got:", sphere_surface_area(1))
print("Radius 2.8, expected disc area: 24.630086404143974, got:", disc_area(2.8))
print("Radius 2.8, expected sphere surface area: 98.5203456165759, got:", sphere_surface_area(2.8))
print("Radius 14.5, expected disc area: 660.519855417254, got:", disc_area(14.5))
print("Radius 14.5, expected sphere surface area: 2642.079421669016, got:", sphere_surface_area(14.5))
Hint
The following code provides better tests, as it compares the output of the function with the expected output. When comparing floating-point numbers, instead of using ==
it is better to check whether the two numbers are very close. This is because two correct solutions can be slightly different due to the way floating-point numbers are stored in the computer.
test1 = math.isclose(disc_area(1), 3.14159265, rel_tol=0.0001)
test2 = math.isclose(sphere_surface_area(1), 12.5663706, rel_tol=0.0001)
test3 = math.isclose(disc_area(2.8), 24.630086, rel_tol=0.0001)
test4 = math.isclose(sphere_surface_area(2.8), 98.520345, rel_tol=0.0001)
test5 = math.isclose(disc_area(14.5), 660.51985, rel_tol=0.0001)
test6 = math.isclose(sphere_surface_area(14.5), 2642.07942, rel_tol=0.0001)
all_tests_passed = test1 and test2 and test3 and test4 and test5 and test6
print("All tests passed:", all_tests_passed)
if not all_tests_passed:
print("Individual test results:", test1, test2, test3, test4, test5, test6)
Code 5.7: Parts to Ratio#
When mixing liquids, the mixing instructions are often given in parts. For example, instructions to mix elderflower syrup with water might say 1+4, which means that you should mix one part elderflower syrup with four parts water. Given such instructions, we are interested in knowing the ratio of the one part in relation to the total liquid. Again looking at the example 1+4, the obtained mixture has \(1 + 4 = 5\) parts in total, and the elderflower syrup is one part of this. Therefore, the ratio of elderflower syrup to the total liquid is \(\frac{1}{5} = 0.2\).
Write a function parts_to_ratio
that takes two arguments, part
and part_other
, and returns the ratio of part
in relation to the total liquid.
Hint
You can use the following code to test your solution by comparing the expected output with the output of your function.
test1 = parts_to_ratio(1, 2) == 1/3
test2 = parts_to_ratio(3, 2) == 3/5
test3 = parts_to_ratio(5, 4) == 5/9
test4 = parts_to_ratio(1, 1) == 1/2
test5 = parts_to_ratio(7, 3) == 7/10
test6 = parts_to_ratio(2, 3) == 2/5
test7 = parts_to_ratio(4, 4) == 4/8
all_tests_passed = test1 and test2 and test3 and test4 and test5 and test6 and test7
print("All tests passed:", all_tests_passed)
Code 5.8: Is Divisible#
We are often interested in knowing whether a number is divisible by another number. For example, 28 is divisible by 7, because \(28 = 7 \cdot 4\), but 29 is not divisible by 7 because we would get a remainder of 1.
Write a function called is_divisible
that takes the numbers num
and divisor
as arguments and returns True
if num
is divisible by divisor
.
Test your function on a range of values. For example, is_divisible(10, 2)
should return True
and is_divisible(10, 3)
should return False
.
Hint
You can use the modulo operator %
, and the function body should be a single line.
Problem Solving#
Problem 5.9: Profit Margin#
The profit margin is a measure of how much of the company’s revenue is profit. The profit margin is calculated as
where \(r\) is the revenue and \(c\) is the cost.
Create a function called profit_margin_pct
that receives two parameters, revenue
and cost
, and returns the profit margin as a percentage. The following companies would like to know how much profit margin they have made in the last year. Use the function to calculate the profit margin for each company. We use 10**9
for a billion.
Company |
Cost ($) |
Revenue ($) |
Profit Margin (%) |
---|---|---|---|
Lemonade stand inc. |
20 |
40 |
50 |
Floormart |
30 billion |
31 billion |
|
Ztartup |
200000 |
144000 |
|
Orange Inc. |
60 billion |
83 billion |
Problem 5.10: Dilute Solution#
We want to dilute a solution by mixing it with a solvent. The mixing proportions are given in parts. The solution has a certain concentration, and after mixing it with the solvent, the concentration will be lowered. We want to compute the new concentration of the solution after it is mixed.
For example, consider having a solution that has a concentration of \(0.5\) g/L and mixing 2 parts of solution with 3 parts solvent. The resulting solution has \( 2 + 3 = 5 \) parts, of which 2 parts are the original solution. Therefore, the concentration of the diluted solution will be \(\frac{2}{5}\cdot 0.5 = 0.2\) g/L.
Write a function dilute
with arguments concentration
, part_solution
, and part_solvent
that returns the concentration of the diluted solution.
Check
Check your solution by following the instructions below and comparing your result with ours.
Make a solution with 50 g/L of NaCl in water.
Dilute 2 parts of the solution with 3 parts of water.
Dilute it again by mixing 1 part of the previous solution with 4 parts of water.
Dilute it again by mixing 9 parts of the previous solution with 1 part of water.
The final concentration of the solution should be 3.6 g/L.
Problem 5.11: Deflection of a Beam#
The deflection of a beam is given by
where \(D\) is the deflection, \(M\) is the load, \(L\) is the length of the beam, \(\lambda\) is the modulus of elasticity, and \(I\) is the moment of inertia. The illustration below shows an unloaded and a loaded beam.
Write a function that calculates the deflection of a beam. The function should have the following signature:
calculate_beam_deflection.py
calculate_beam_deflection(length, load, modulus_of_elasticity, moment_of_inertia)
Calculate the deflection of a beam under a load.
Parameters:
|
|
The length of the beam (m). |
|
|
The load applied to the beam (N). |
|
|
The modulus of elasticity of the beam material (Pa). |
|
|
The moment of inertia of the beam’s cross-section (m). |
Returns:
|
The deflection of the beam (m). |
How to test this function? Consider first setting all parameters to 1 and calculate the expected result by hand. See if your function returns the same result. Try some more interesting values and see if the function returns the expected result.
Problem 5.12: Wind Chill#
Wind chill is the lowering of body temperature due to the flow of cool air. The perceived temperature is denoted by wind chill temperature \(T_{WC}\). The cooling effect depends on air temperature \(T\) and wind speed \(v\) with the formula:
where \(T\) is the temperature in Celsius and \(v\) is the wind speed in km/h.
Write the function wind_chill
that takes as input the actual temperature temperature
(in degrees Celsius) and the wind speed windspeed
(in km/h). The function should return the perceived temperature rounded to the nearest integer.
The code below can be used to nicely print the result.
windchill = wind_chill(temperature, windspeed)
print(round(temperature), "°C with a wind speed of",
round(windspeed), "km/h feels like", windchill, "°C.")
To test your function, we have supplied test_wind_chill.py
. You can run this file to see if your function is working as expected. The file runs the following four tests and checks if the output matches the expected outputs shown below.
>>> wind_chill(10, 25)
7
>>> wind_chill(0, 100)
-11
>>> wind_chill(40, 0)
38
>>> wind_chill(40, 20)
45
Problem 5.13: Bacterial Growth#
We grow bacteria in a closed container that can sustain a certain number of bacteria. To investigate bacterial growth, we use the model
where \(\Delta N\) is the change in the number of bacteria from one hour to another, \(r\) is the hourly growth rate, \(N\) is the number of bacteria, and \(K\) is the maximum number of bacteria that can be in the container. The expression in the parentheses is the fraction of the container that is empty. So if no space is empty and \(N = K\) the number of bacteria will not increase further.
Starting from an initial population, we want to know how many hours it will take for the bacteria to fill more than 90% of the container.
Consider \(N=100\), \(r=0.1\), and \(K=1000\). After one hour, the population will be 109, then approximately 118.7, 129.2, 140.4, and so on. The population will reach 90% of the maximum population after 44 hours.
Create a file called bacterial_growth.py
. In this file create a function with the following specifications:
bacterial_growth.py
bacterial_growth(initial, growth_rate, max_bact)
Simulates bacterial growth over one week and returns the time taken to reach 90% of the maximum population.
Parameters:
|
|
The initial number of bacteria. |
|
|
The growth rate of the bacteria. |
|
|
The maximum population of the bacteria. |
Returns:
|
The number of hours for the bacteria to reach 90% of the maximum population. Returns -1 if the population does not reach 90% within one week. |
One expected output is shown below.
>>> bacterial_growth(100, 0.1, 1000)
44
You should also test your function with test_bacterial_growth.py
.
Problem 5.14: Blood Pressure#
Measurement of blood pressure consists of two values: systolic blood pressure (a higher value) and diastolic blood pressure (a lower value). Based on these two values, blood pressure can be categorized as indicated in the chart below.
Create a function blood_pressure
that takes two numbers, representing the systolic and diastolic blood pressure, as input. The function should return a string with the blood pressure category, written exactly as in the chart above. If a measurement is between categories, the category for the higher value should be returned.
For example, if the systolic blood pressure is 120 and the diastolic blood pressure is 65, according to the chart, the measurement is between the normal and prehigh blood pressure catergories. The function should return the higher category, which is the string 'Prehigh'
.
The function should have the following specifications:
blood_pressure.py
blood_pressure(systolic, diastolic)
Categorizes blood pressure based on systolic and diastolic readings.
Parameters:
|
|
A valid systolic blood pressure value. |
|
|
A valid diastolic blood pressure value. |
Returns:
|
The blood pressure category. |
The script solving this problem was presented in the live demo. You can now make a function based on it and test it with the following:
Show tests
test0 = blood_pressure(120, 65) == 'Prehigh'
test1 = blood_pressure(100, 95) == 'Stage 1 high'
test2 = blood_pressure(80, 50) == 'Low'
test3 = blood_pressure(110, 70) == 'Normal'
test4 = blood_pressure(133, 82) == 'Prehigh'
test5 = blood_pressure(141, 99) == 'Stage 1 high'
test6 = blood_pressure(189, 101) == 'Stage 2 high'
test7 = blood_pressure(90, 60) == 'Normal'
test8 = blood_pressure(170, 80) == 'Stage 2 high'
test9 = blood_pressure(140, 50) == 'Stage 1 high'
test10 = blood_pressure(160, 60) == 'Stage 2 high'
all_tests_passed = test0 and test1 and test2 and test3 and test4 and test5 and test6 and test7 and test8 and test9 and test10
print("All tests passed:", all_tests_passed)
Problem 5.15: Candy Exchange#
The owner of a candy shop devised a plan to reduce littering in front of the shop: “Bring back five pieces of candy wrapping, and get one candy for free!” This poses a question: If you have a certain number of candies, how many candies can you actually end up eating? Here we assume that you keep returning the wrappers as long as possible.
Create a function candy_exchange
that takes the number of candies you have as input, and returns the number of candies you can end up eating.
For example, let’s say you start with 73 candies. After eating these candies, you are left with 73 wrappers. You have eaten 73 candies, and you have 73 wrappers. You exchange 70 wrappers for 14 new candies, which you eat. You have now eaten 87 candies, and you have 17 wrappers. Continuing this way, we can summarize the status in the table below, showing that you can eat 91 candies in total.
Candies eaten |
73 |
87 |
90 |
91 |
---|---|---|---|---|
Wrappers |
73 |
17 |
5 |
1 |
The function should have the following specifications:
candy_exchange.py
candy_exchange(n)
Simulates the exchange of wrappers for more candies.
Parameters:
|
|
The number of candies you have. |
Returns:
|
The number of candies you can end up eating. |
The script solving this problem was presented in the live demo. You can now make a function based on it and test it with the following:
Show tests
test0 = candy_exchange(73) == 91
test1 = candy_exchange(12) == 14
test2 = candy_exchange(22) == 27
test3 = candy_exchange(91) == 113
test4 = candy_exchange(182) == 227
test5 = candy_exchange(16) == 19
test6 = candy_exchange(1) == 1
test7 = candy_exchange(5) == 6
test8 = candy_exchange(13) == 16
test9 = candy_exchange(36) == 44
test10 = candy_exchange(94) == 117
all_tests_passed = (test0 and test1 and test2 and test3 and test4 and test5
and test6 and test7 and test8 and test9 and test10)
print("All tests passed:", all_tests_passed)
Problem 5.16: Fibonacci Sequence Check#
The Fibonacci sequence is a series of numbers where each number is the sum of the two preceding ones. The sequence starts as follows:
Create a function fibonacci_check
that takes an integer as input, and returns which position this integer has in the list of fibonacci numbers. If the number is not in the list, the function should return -1
.
To avoid ambiguities, you can assume the input is 2 or greater.
For example, the number 5 is the 6th fibonacci number, so fibonacci_check(5)
should return 6.
Here are some additional examples:
>>> fibonacci_check(5)
6
>>> fibonacci_check(14)
-1
>>> fibonacci_check(14930352)
37
The function specifications are:
fibonacci_check.py
fibonacci_check(n)
Determines which Fibonacci number the input is.
Parameters:
|
positive |
The number we wish to test. |
Returns:
|
The position in the list of Fibonacci numbers. If it is not in the list, return |